def _verify_signature(self, data): h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32]) try: h.verify(data[-32:]) except InvalidSignature: raise InvalidToken
def verifyThenDecrypt(cipher, emailTime, key): encryptKey = key[16:] signKey = key[:16] payload = base64.urlsafe_b64decode(cipher) #verify timestamp to prevent replay try: timestamp, = struct.unpack(">Q", payload[1:9]) except struct.error: raise ValueError('Invalid message') if timestamp + TTL < emailTime: raise Exception('Invalid timestamp: replay attack detected') #verify HMAC hasher = HMAC(signKey, hashes.SHA256(), backend=default_backend()) hasher.update(payload[:-32]) try: hasher.verify(payload[-32:]) except InvalidSignature: raise Exception('Invalid HMAC: data modification detected') #decrypt cipher text iv = payload[9:25] ciphertext = payload[25:-32] decryptor = Cipher(algorithms.AES(encryptKey), modes.CBC(iv), default_backend()).decryptor() paddedPlaintext = decryptor.update(ciphertext) paddedPlaintext += decryptor.finalize() unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() plaintext = unpadder.update(paddedPlaintext) plaintext += unpadder.finalize() return plaintext
def enc(self, byts): ''' Encrypt the given bytes and return an envelope dict in msgpack form. Args: byts (bytes): The message to be encrypted. Returns: bytes: The encrypted message. This is a msgpacked dictionary containing the IV, ciphertext and HMAC values. ''' iv = os.urandom(16) # pad the bytes using PKCS7 padr = padding.PKCS7(self.bsize).padder() byts = padr.update(byts) + padr.finalize() mode = modes.CBC(iv) algo = algorithms.AES(self.ekey) encr = Cipher(algo, mode, self.bend).encryptor() # encrypt the bytes and prepend the IV byts = encr.update(byts) + encr.finalize() macr = HMAC(self.skey, hashes.SHA256(), backend=self.bend) macr.update(iv + byts) hmac = macr.finalize() envl = {'iv': iv, 'hmac': hmac, 'data': byts} return s_msgpack.en(envl)
def _encrypt_from_parts(self, data, current_time, iv): if not isinstance(data, bytes): raise TypeError("data must be bytes.") # PROBLEM: MAC-then-Encrypt # HMAC(HDR+R) h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) basic_parts = (b"\x80" + struct.pack(">Q", current_time) + data) h.update(basic_parts) hmac = h.finalize() # R+T+pad padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data + hmac) + padder.finalize() print('Message:', data, 'MAC:', hmac, 'Pad:', padded_data[len(data + hmac):], sep=' ') print('Plaintext to be encrypted: ', padded_data) encryptor = Cipher(algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() final_message = b"\x80" + \ struct.pack(">Q", current_time) + iv + ciphertext return base64.urlsafe_b64encode(final_message)
def decrypt(privkey, data): s = serialize.Deserializer(data) iv = s.bytes(16) curve = s.uint(2) assert curve == 0x02ca x_len = s.uint(2) assert x_len <= 32 # TODO Should we assert this? And should we assert no leading zero bytes? x = s.bytes(x_len) y_len = s.uint(2) assert y_len <= 32 # TODO Should we assert this? And should we assert no leading zero bytes? y = s.bytes(y_len) encrypted = s.bytes(-32) assert encrypted != b'' mac = s.bytes(32) pubkey = x.rjust(32, b'\x00') + y.rjust(32, b'\x00') public_key = _pub_to_public(pubkey) private_key = _priv_to_private(privkey) secret = private_key.exchange(ec.ECDH(), public_key) key = hashlib.sha512(secret).digest() enckey = key[0:32] mackey = key[32:64] maccer = HMAC(mackey, hashes.SHA256(), openssl.backend) maccer.update(data[0:-32]) maccer.verify(mac) cipher = Cipher(algorithms.AES(enckey), modes.CBC(iv), openssl.backend) decryptor = cipher.decryptor() padded = decryptor.update(encrypted) + decryptor.finalize() unpadder = padding.PKCS7(128).unpadder() return unpadder.update(padded) + unpadder.finalize()
def encrypt(pubkey, data): public_key = _pub_to_public(pubkey) private_key = ec.generate_private_key(ec.SECP256K1(), openssl.backend) secret = private_key.exchange(ec.ECDH(), public_key) key = hashlib.sha512(secret).digest() enckey = key[0:32] mackey = key[32:64] iv = os.urandom(16) padder = padding.PKCS7(128).padder() paddeddata = padder.update(data) + padder.finalize() cipher = Cipher(algorithms.AES(enckey), modes.CBC(iv), openssl.backend) encryptor = cipher.encryptor() ciphertext = encryptor.update(paddeddata) + encryptor.finalize() s = serialize.Serializer() s.bytes(iv) s.uint(0x02ca, 2) public_numbers = private_key.public_key().public_numbers() x = public_numbers.x.to_bytes(32, 'big').lstrip(b'\x00') s.uint(len(x), 2) s.bytes(x) y = public_numbers.y.to_bytes(32, 'big').lstrip(b'\x00') s.uint(len(y), 2) s.bytes(y) s.bytes(ciphertext) maccer = HMAC(mackey, hashes.SHA256(), openssl.backend) maccer.update(s.data) mac = maccer.finalize() s.bytes(mac) return s.data
def _a(self, secret, hash_algorithm, n, seed): if n == 0: return seed else: h = HMAC(secret, hash_algorithm, default_backend()) h.update(self._a(secret, hash_algorithm, n - 1, seed)) return h.finalize()
def _encrypt_from_parts(self, data, adata="", salt="", signing_key="", encryption_key=""): if not isinstance(data, bytes): raise TypeError("data must be bytes.") # print("signing_key = " + str(len(signing_key)), signing_key) # print("encryption_key = " + str(len(encryption_key)), encryption_key) padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher(algorithms.AES(encryption_key), modes.CBC("0" * 16), self._backend).encryptor() # ctx = AES( iv || msg ) ctx = encryptor.update(padded_data) + encryptor.finalize() basic_parts = (b"\x82" + salt + ctx) h = HMAC(signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts + adata) # tag = HMAC( 0x81 || iv || ctx ) tag = h.finalize() return base64.urlsafe_b64encode(basic_parts + tag)
def salted_hmac(key_salt, value, secret=None): """ Returns the HMAC-HASH of 'value', using a key generated from key_salt and a secret (which defaults to settings.SECRET_KEY). A different key_salt should be passed in for every application of HMAC. :type key_salt: any :type value: any :type secret: any :rtype: HMAC """ if secret is None: secret = settings.SECRET_KEY key_salt = force_bytes(key_salt) secret = force_bytes(secret) # We need to generate a derived key from our base key. We can do this by # passing the key_salt and our base key through a pseudo-random function and # SHA1 works nicely. digest = hashes.Hash(settings.CRYPTOGRAPHY_DIGEST, backend=settings.CRYPTOGRAPHY_BACKEND) digest.update(key_salt + secret) key = digest.finalize() # If len(key_salt + secret) > sha_constructor().block_size, the above # line is redundant and could be replaced by key = key_salt + secret, since # the hmac module does the same thing for keys longer than the block size. # However, we need to ensure that we *always* do this. h = HMAC(key, settings.CRYPTOGRAPHY_DIGEST, backend=settings.CRYPTOGRAPHY_BACKEND) h.update(force_bytes(value)) return h
def _decrypt_data(self, data, timestamp, ttl): current_time = int(time.time()) if ttl is not None: if timestamp + ttl < current_time: raise InvalidToken if current_time + _MAX_CLOCK_SKEW < timestamp: raise InvalidToken h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32]) try: h.verify(data[-32:]) except InvalidSignature: raise InvalidToken iv = data[9:25] ciphertext = data[25:-32] decryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).decryptor() plaintext_padded = decryptor.update(ciphertext) try: plaintext_padded += decryptor.finalize() except ValueError: raise InvalidToken unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() unpadded = unpadder.update(plaintext_padded) try: unpadded += unpadder.finalize() except ValueError: raise InvalidToken return unpadded
def sign(self, pairs): """ Generate a signature for a sequence of (key, value) pairs @param pairs: The pairs to sign, in order @type pairs: Iterable[six.text_type, six.text_type], six.binary_type is deprecated @return: The binary signature of this sequence of pairs @rtype: six.binary_type """ warning_msg = "Binary values for pairs are deprecated. Use text input instead." pairs = [(string_to_text(a, warning_msg), string_to_text(b, warning_msg)) for a, b in pairs] kv = kvform.seqToKV(pairs) try: algorithm = self.hmac_algorithms[self.assoc_type] except KeyError: raise ValueError('Unknown association type: %r' % (self.assoc_type, )) hmac = HMAC(self.secret, algorithm, backend=default_backend()) hmac.update(kv.encode('utf-8')) return hmac.finalize()
def aes_cbc_dec(aesKey, bsEncMsg, bsMacMsg): ''' AuthenticatedEncryption - Check mac then decrypt given encrypted message. ''' ### Prepare for mac sha256 = SHA256() hmac = HMAC(aesKey, sha256, default_backend()) ### do mac hmac.update(bsEncMsg) macMsg = hmac.finalize() if (macMsg != bsMacMsg): raise Exception("ERRR:AEDecrypt:Mismatch, skipping") return None ### Prepare for decryption blockLen = 16 iv = os.urandom(blockLen) aes = AES(aesKey) cbc = CBC(iv) aesCbc = Cipher(aes, cbc, default_backend()) aesCbcDec = aesCbc.decryptor() ### do decrypt decMsg = aesCbcDec.update(bsEncMsg) decFina = aesCbcDec.finalize() decMsg = decMsg + decFina # do pkcs7 depadding unpad = PKCS7(blockLen * 8).unpadder() decMsg = unpad.update(decMsg) decMsg += unpad.finalize() # Discard the initial random block, as corresponding enc and this dec uses # non communicated random iv and inturn discardable random 0th block decMsg = decMsg[blockLen:] return decMsg
def scramble_salt(self, password, salt, server_key, client_key, rounds=None): """Scrambles a given salt using the specified server key. """ msg = salt + server_key + client_key hmac_digest = self.salt_key(password, salt, rounds) hash = Hash(self.ALGORITHM(), self.backend) hash.update(hmac_digest) hash_digest = hash.finalize() key_hash = Hash(self.ALGORITHM(), self.backend) key_hash.update(hash_digest) key_hash_digest = key_hash.finalize() sig = HMAC(key_hash_digest, self.ALGORITHM(), self.backend) sig.update(msg) sig_digest = sig.finalize() return self.xor(sig_digest, hash_digest)
def encrypt_with_hmac(self, data, data_id, iv): if not isinstance(data, bytes): raise TypeError("data must be bytes.") if not isinstance(data_id, int): raise TypeError("data_id must be int.") main_parts = ( struct.pack(config.FORMAT_CHAR, data_id) + data ) # PKCS7 padding padded_data = self.add_padding(main_parts, algorithms.AES.block_size) # AES with CBC mode encryptor = Cipher(algorithms.AES(self.aes_key), modes.CBC(iv), backend=self.backend).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() basic_parts = ( b"\x80" + iv + ciphertext ) h = HMAC(self.mac_key, hashes.SHA256(), backend=self.backend) h.update(basic_parts) hmac = h.finalize() return basic_parts + hmac
def process_header(self, data): if self._cipher_key_len is None: if data[0:6] != FILEMAGIC: raise EncryptorError("Invalid magic bytes") self._cipher_key_len = struct.unpack(">H", data[6:8])[0] else: pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) try: plainkey = self.rsa_private_key.decrypt(data, pad) except AssertionError: raise EncryptorError("Decrypting key data failed") if len(plainkey) != 64: raise EncryptorError("Integrity check failed") key = plainkey[0:16] nonce = plainkey[16:32] auth_key = plainkey[32:64] self._header_size = 8 + len(data) self.cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()).decryptor() self.authenticator = HMAC(auth_key, SHA256(), backend=default_backend())
def decrypt_encryption_key_fallback(self): """Decrypts the encryption key using the FALLBACK method. In this method, the context string, usually "CredEncryption" or "PSEEncryption", is encrypted using a derivation of a fixed key hardcoded in CommonCryptoLib, and used as key to encrypt the actual encryption key used in the file with the AES cipher. :return: Encryption key decrypted :rtype: string """ log_lps.debug("Obtaining encryption key with FALLBACK LPS mode") digest = Hash(SHA1(), backend=default_backend()) digest.update(cred_key_lps_fallback) hashed_key = digest.finalize() hmac = HMAC(hashed_key, SHA1(), backend=default_backend()) hmac.update(self.context) default_key = hmac.finalize()[:16] iv = "\x00" * 16 decryptor = Cipher(algorithms.AES(default_key), modes.CBC(iv), backend=default_backend()).decryptor() encryption_key = decryptor.update( self.encrypted_key) + decryptor.finalize() return encryption_key
def signature(self, value): """ :type value: any :rtype: HMAC """ h = HMAC(self.key, self.digest, backend=settings.CRYPTOGRAPHY_BACKEND) h.update(force_bytes(value)) return h
def _get_hmac(key, ciphertext, digest_method): hmac = HMAC( key, get_digest(digest_method), backend=default_backend() ) hmac.update(ciphertext) return hmac.finalize()
def hmac_verify(key, data, hash_alg, backend, sig = None): h = HMAC( key, hash_alg, backend=backend ) h.update(data) return h.verify(sig)
def hmac(key, data, hash_alg, backend): h = HMAC( key, hash_alg, backend=backend ) h.update(data) return h.finalize()
class Decryptor(object): def __init__(self, rsa_private_key_pem): if not isinstance(rsa_private_key_pem, bytes): rsa_private_key_pem = rsa_private_key_pem.encode("ascii") self.rsa_private_key = serialization.load_pem_private_key( data=rsa_private_key_pem, password=None, backend=default_backend()) self.cipher = None self.authenticator = None self.buf = b"" def update(self, data): self.buf += data if self.cipher is None: if len(self.buf) < 8: return b"" if self.buf[0:6] != FILEMAGIC: raise EncryptorError("Invalid magic bytes") cipherkeylen = struct.unpack(">H", self.buf[6:8])[0] if len(self.buf) < 8 + cipherkeylen: return b"" pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) try: plainkey = self.rsa_private_key.decrypt(self.buf[8:8 + cipherkeylen], pad) except AssertionError: raise EncryptorError("Decrypting key data failed") if len(plainkey) != 64: raise EncryptorError("Integrity check failed") key = plainkey[0:16] nonce = plainkey[16:32] auth_key = plainkey[32:64] self.cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()).decryptor() self.authenticator = HMAC(auth_key, SHA256(), backend=default_backend()) self.buf = self.buf[8 + cipherkeylen:] if len(self.buf) < 32: return b"" self.authenticator.update(self.buf[:-32]) result = self.cipher.update(self.buf[:-32]) self.buf = self.buf[-32:] return result def finalize(self): if self.cipher is None: return b"" # empty encrypted input yields empty plaintext output elif self.buf != self.authenticator.finalize(): raise EncryptorError("Integrity check failed") result = self.cipher.finalize() self.buf = b"" self.cipher = None self.authenticator = None return result
def __init__(self, key, iv=None): self.key = key self.iv = iv self.check = b'' self.decryptor = None self.unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() self.hmac = HMAC(key[:16], hashes.SHA256(), backend=default_backend())
def __call__(self, request): hmac = HMAC(self.secret.encode('utf-8'), SHA512(), default_backend()) hmac.update(request.body.encode('utf-8')) signature = hexlify(hmac.finalize()) request.headers['Key'] = self.key request.headers['Sign'] = signature return request
def calculate_hmac(key, data): """Shortcut for calculating HMAC of a string.""" h = HMAC( key=key, algorithm=hashes.SHA256(), backend=backend ) h.update(data) return h.finalize()
def verify_hmac(key, data, signature): """Shortcut for verifying HMAC of a string.""" h = HMAC( key=key, algorithm=hashes.SHA256(), backend=backend ) h.update(data) return h.verify(signature)
def symmetric_encrypt(data, key, hmac_key=None): if hmac_key: prefix = randbytes(3) hmac = HMAC(hmac_key, SHA1(), backend) hmac.update(prefix + data) iv = hmac.finalize()[:13] + prefix else: iv = randbytes(16) return symmetric_encrypt_with_iv(data, key, iv)
def __init__(self, key=None, iv=None): self.key = key or os.urandom(32) self.iv = iv or os.urandom(16) self.encryptor = Cipher(algorithms.AES(self.key[16:]), modes.CBC(self.iv), backend=default_backend()).encryptor() self.padder = padding.PKCS7(algorithms.AES.block_size).padder() self.hmac = HMAC(key[:16], hashes.SHA256(), backend=default_backend()) self.header = False
def derive_keyhash_v2(domain, password, salt, iterations): kdf = PBKDF2HMAC(algorithm=SHA512(), length=64, salt=salt, iterations=iterations, backend=_CRYPTO_BACKEND) derived_key = kdf.derive((domain + password).encode('utf-8')) hf = HMAC(derived_key, SHA256(), backend=_CRYPTO_BACKEND) hf.update(domain.encode('utf-8')) return hf.finalize()
def MyencryptMAC(plaintext, key, HMACkey): #if(len(key) < 32): #return "ERROR: Key must be 32 Bytes or bigger" #HMAC: maybe replace plaintext to key.encode() according to lab instructions cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(plaintext) h = HMAC(HMACkey, hashes.SHA256(), backend=default_backend()) h.update(plaintext.encode()) tag = h.finalize() return (ciphertext, iv, tag)
def aes_cbc_enc(aesKey, sPlainMsg): ''' AuthenticatedEncryption - Do a encrypt then mac operation on given message. a random iv is generated but not transmitted, instead a random block is prepended to the message and encrypted. Inturn the same can be discarded during decrypting. Each CBC block depends on the previous encrypted block so the 0th block acts as a inplace iv at one level. Encryption uses AES in CBC mode with PKCS7 padding where required. MAC uses HMAC with SHA256 As encryption and mac using independent algorithms so the key is shared wrt encryption and mac operations. With aes length of key passed is independent of the block size used, and user can use any valid aes key size. This is similar to the age old encrypt as well as sign messages to ensure confidentiality as well as authenticity. But then instead of using asymm logic for signing, use a hash with hidden key based logic. Also make sure that one checks the authenticity before trying to use it or work on it, so that new oracles arent opened up, beyond the minimal unavoidable oracle. ''' ### Prepare for encryption blockLen = 16 iv = os.urandom(blockLen) aes = AES(aesKey) cbc = CBC(iv) aesCbc = Cipher(aes, cbc, default_backend()) aesCbcEnc = aesCbc.encryptor() random0thBlock = os.urandom(blockLen) # This allows iv to be discarded # so also while decrypting discard the 0th block plainMsg = random0thBlock + sPlainMsg.encode('utf-8') # do PKCS7 padding if bInternalPadder: padLen = blockLen - (len(plainMsg) % blockLen) for i in range(padLen): plainMsg += int.to_bytes(padLen, 1, 'little') else: pad = PKCS7(blockLen * 8).padder() plainMsg = pad.update(plainMsg) plainMsg += pad.finalize() ### do encrypt encMsg = aesCbcEnc.update(plainMsg) encFina = aesCbcEnc.finalize() encMsg = encMsg + encFina ### Prepare for mac sha256 = SHA256() hmac = HMAC(aesKey, sha256, default_backend()) ### do mac hmac.update(encMsg) macMsg = hmac.finalize() return encMsg, macMsg
def _encrypt(enc_key, mac_key, salt, data, version): iv = os.urandom(_IV_LEN) padder = PKCS7(AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher(AES(enc_key), CBC(iv), _backend).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() all_data = b''.join((version.value, salt, iv, ciphertext)) h = HMAC(mac_key, _MAC_HASH, _backend) h.update(all_data) hmac = h.finalize() return all_data + hmac
def generate_mac(key, data, algorithm="SHA256", backend=BACKEND): """ Returns a message authentication code for verifying the integrity and authenticity of data by entities that possess the key. Note this is a lower level function then apply_mac and only returns the mac itself. The mac is generated via HMAC with the specified algorithm and key. """ hasher = HMAC(key, getattr(hashes, algorithm.upper())(), backend=backend) hasher.update(algorithm + '::' + data) return hasher.finalize()
def compute_verify_data(self, basekey, handshake_context): hash_len = self.hash.digest_size finished_key = self.expand_label(basekey, b"finished", b"", hash_len) h = Hash(self.hash, backend=default_backend()) h.update(handshake_context) hash_value = h.finalize() hm = HMAC(finished_key, self.hash, default_backend()) hm.update(hash_value) return hm.finalize()
def _a(secret, hash_algorithm, n, seed): """ a() is defined as: a(0) = seed a(i) = HMAC_hash(secret, A(i-1)) """ if n == 0: return seed else: h = HMAC(secret, hash_algorithm, default_backend()) h.update(_a(secret, hash_algorithm, n - 1, seed)) return h.finalize()
def decrypt(self, token, ttl=None): if not isinstance(token, bytes): raise TypeError("token must be bytes.") current_time = int(time.time()) try: data = base64.urlsafe_b64decode(token) except (TypeError, binascii.Error): raise InvalidToken if not data or six.indexbytes(data, 0) != 0x80: raise InvalidToken try: timestamp, = struct.unpack(">Q", data[1:9]) except struct.error: raise InvalidToken if ttl is not None: if timestamp + ttl < current_time: raise InvalidToken if current_time + _MAX_CLOCK_SKEW < timestamp: print (">>>", current_time) print (">>>", timestamp) raise InvalidToken h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32]) try: # verify everything in data except for tag is the same as original h.verify(data[-32:]) except InvalidSignature: raise InvalidToken iv = data[9:25] ciphertext = data[25:-32] decryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).decryptor() plaintext_padded = decryptor.update(ciphertext) try: plaintext_padded += decryptor.finalize() except ValueError: raise InvalidToken unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() unpadded = unpadder.update(plaintext_padded) try: unpadded += unpadder.finalize() except ValueError: raise InvalidToken return unpadded
def get_shared_key(self, key_length=32, shared_secret=None): if not shared_secret and not self.shared_secret: raise ArithmeticError("No shared secret provided.") elif shared_secret and not self.shared_secret: self.shared_secret = shared_secret hash_provider = HMAC( hex(self.shared_secret).encode('utf-8'), SHA512(), default_backend()) for i in range(0, 10000): hash_provider.update(hex(i).encode('utf-8')) shared_digest = base64.b64encode(hash_provider.finalize()) return shared_digest[:key_length]
def _encrypt_cryptography(b_plaintext, b_key1, b_key2, b_iv): cipher = C_Cipher(algorithms.AES(b_key1), modes.CTR(b_iv), CRYPTOGRAPHY_BACKEND) encryptor = cipher.encryptor() padder = padding.PKCS7(algorithms.AES.block_size).padder() b_ciphertext = encryptor.update(padder.update(b_plaintext) + padder.finalize()) b_ciphertext += encryptor.finalize() # COMBINE SALT, DIGEST AND DATA hmac = HMAC(b_key2, hashes.SHA256(), CRYPTOGRAPHY_BACKEND) hmac.update(b_ciphertext) b_hmac = hmac.finalize() return to_bytes(hexlify(b_hmac), errors='surrogate_or_strict'), hexlify(b_ciphertext)
def verify_mac(key, packed_data, algorithm="SHA256", backend=BACKEND): """ Verifies a message authentication code as obtained by apply_mac. Successful comparison indicates integrity and authenticity of the data. Returns data is comparison succeeds; Otherwise returns pride.functions.security.INVALID_TAG. """ mac, data = load_data(packed_data) hasher = HMAC(key, getattr(hashes, algorithm.upper())(), backend=backend) hasher.update(algorithm + '::' + data) try: hasher.verify(mac) except InvalidSignature: return INVALID_TAG else: return data
def MyencryptMAC(message, EncKey, HMACKey): # encrypts message with encryption key c, iv = myencrypt(message, EncKey) if len(HMACKey) != KEY_BYTES: # prints error message sys.stderr.write('Error: HMAC key length must be 32 bytes.') else: # generates tag using HMAC on ciphertext generated above tag = HMAC(HMACKey, hashes.SHA256(), backend=default_backend()) tag.update(c) tag = tag.finalize() return c, iv, tag
def _encrypt_from_parts(self, data, current_time, iv): if isinstance(data, six.text_type): raise TypeError("Unicode-objects must be encoded before encryption") padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher(algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() basic_parts = b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts) hmac = h.finalize() return base64.urlsafe_b64encode(basic_parts + hmac)
def update(self, data): self.buf += data if self.cipher is None: if len(self.buf) < 8: return b"" if self.buf[0:6] != FILEMAGIC: raise EncryptorError("Invalid magic bytes") cipherkeylen = struct.unpack(">H", self.buf[6:8])[0] if len(self.buf) < 8 + cipherkeylen: return b"" pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) try: plainkey = self.rsa_private_key.decrypt(self.buf[8:8 + cipherkeylen], pad) except AssertionError: raise EncryptorError("Decrypting key data failed") if len(plainkey) != 64: raise EncryptorError("Integrity check failed") key = plainkey[0:16] nonce = plainkey[16:32] auth_key = plainkey[32:64] self.cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()).decryptor() self.authenticator = HMAC(auth_key, SHA256(), backend=default_backend()) self.buf = self.buf[8 + cipherkeylen:] if len(self.buf) < 32: return b"" self.authenticator.update(self.buf[:-32]) result = self.cipher.update(self.buf[:-32]) self.buf = self.buf[-32:] return result
def opdata1_decrypt_key(data, key, hmac_key, aes_size=C_AES_SIZE, ignore_hmac=False): """Decrypt encrypted item keys""" hmac_key = make_utf8(hmac_key) key_size = KEY_SIZE[aes_size] iv, cryptext, expected_hmac = struct.unpack("=16s64s32s", data) if not ignore_hmac: verifier = HMAC(hmac_key, SHA256(), backend=_backend) verifier.update(iv + cryptext) try: verifier.verify(expected_hmac) except InvalidSignature: raise ValueError("HMAC did not match for opdata1 key") aes = Cipher(algorithms.AES(key), modes.CBC(iv), backend=_backend) decryptor = aes.decryptor() decrypted = decryptor.update(cryptext) + decryptor.finalize() crypto_key, mac_key = decrypted[:key_size], decrypted[key_size:] return crypto_key, mac_key
def decrypt(self, data, ttl=None): if not isinstance(data, bytes): raise TypeError("data must be bytes.") current_time = int(time.time()) if not data or six.indexbytes(data, 0) != 0x80: raise InvalidToken try: timestamp, = struct.unpack(">Q", data[1:9]) except struct.error: raise InvalidToken if ttl is not None: if timestamp + ttl < current_time: raise InvalidToken if current_time + _MAX_CLOCK_SKEW < timestamp: raise InvalidToken h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32]) try: h.verify(data[-32:]) except InvalidSignature: raise InvalidToken iv = data[9:25] ciphertext = data[25:-32] decryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).decryptor() plaintext_padded = decryptor.update(ciphertext) try: plaintext_padded += decryptor.finalize() except ValueError: raise InvalidToken unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() unpadded = unpadder.update(plaintext_padded) try: unpadded += unpadder.finalize() except ValueError: raise InvalidToken return unpadded
def _decrypt_cryptography(cls, b_ciphertext, b_crypted_hmac, b_key1, b_key2, b_iv): # b_key1, b_key2, b_iv = self._gen_key_initctr(b_password, b_salt) # EXIT EARLY IF DIGEST DOESN'T MATCH hmac = HMAC(b_key2, hashes.SHA256(), CRYPTOGRAPHY_BACKEND) hmac.update(b_ciphertext) try: hmac.verify(unhexlify(b_crypted_hmac)) except InvalidSignature as e: raise AnsibleVaultError('HMAC verification failed: %s' % e) cipher = C_Cipher(algorithms.AES(b_key1), modes.CTR(b_iv), CRYPTOGRAPHY_BACKEND) decryptor = cipher.decryptor() unpadder = padding.PKCS7(128).unpadder() b_plaintext = unpadder.update( decryptor.update(b_ciphertext) + decryptor.finalize() ) + unpadder.finalize() return b_plaintext
def _encrypt_from_parts(self, data, current_time, iv): utils._check_bytes("data", data) padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() basic_parts = ( b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext ) h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts) hmac = h.finalize() return base64.urlsafe_b64encode(basic_parts + hmac)
def _encrypt_from_parts(self, data, current_time, iv): if not isinstance(data, bytes): raise TypeError("data must be bytes.") padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() basic_parts = ( b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext ) h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts) hmac = h.finalize() return basic_parts + hmac
def encryptThenMac(data, key): #set up keys, current timestamp and initialization vector encryptKey = key[16:] signKey = key[:16] curTime = int(time.time()) iv = os.urandom(16) #pad the data and encrypt using AES in CBC mode padder = padding.PKCS7(algorithms.AES.block_size).padder() paddedData = padder.update(data) + padder.finalize() encryptor = Cipher(algorithms.AES(encryptKey), modes.CBC(iv), default_backend()).encryptor() cipher = encryptor.update(paddedData) + encryptor.finalize() #get the HMAC using SHA256 of the combined parts and return everything combined parts = (b"\x80" + struct.pack(">Q", curTime) + iv + cipher) hasher = HMAC(signKey, hashes.SHA256(), backend=default_backend()) hasher.update(parts) hmac = hasher.finalize() return base64.urlsafe_b64encode(parts + hmac)
def _encrypt_from_parts(self, data, iv, associated_data): if not isinstance(data, bytes): raise TypeError("data must be bytes.") padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() basic_parts = ( b"\x81" + iv + ciphertext + associated_data ) h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts) hmac = h.finalize() # TAG return base64.urlsafe_b64encode(b"\x81" + iv + ciphertext + hmac)
def decrypt(self, token, associated_data=b"", ttl=None): if not isinstance(token, bytes): raise TypeError("token must be bytes.") current_time = int(time.time()) try: data = base64.urlsafe_b64decode(token) except (TypeError, binascii.Error): raise InvalidToken if not data or (six.indexbytes(data, 0) != 0x81): raise InvalidToken h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32] + associated_data) try: h.verify(data[-32:]) except InvalidSignature: raise InvalidToken iv = data[1:17] ciphertext = data[17:-32] decryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).decryptor() plaintext_padded = decryptor.update(ciphertext) try: plaintext_padded += decryptor.finalize() except ValueError: raise InvalidToken unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() unpadded = unpadder.update(plaintext_padded) try: unpadded += unpadder.finalize() except ValueError: raise InvalidToken return unpadded
class Encryptor: def __init__(self, rsa_public_key_pem): if not isinstance(rsa_public_key_pem, bytes): rsa_public_key_pem = rsa_public_key_pem.encode("ascii") self.rsa_public_key = serialization.load_pem_public_key(rsa_public_key_pem, backend=default_backend()) self.cipher = None self.authenticator = None def update(self, data): ret = b"" if self.cipher is None: key = os.urandom(16) nonce = os.urandom(16) auth_key = os.urandom(32) self.cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()).encryptor() self.authenticator = HMAC(auth_key, SHA256(), backend=default_backend()) pad = padding.OAEP(mgf=padding.MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None) cipherkey = self.rsa_public_key.encrypt(key + nonce + auth_key, pad) ret = FILEMAGIC + struct.pack(">H", len(cipherkey)) + cipherkey cur = self.cipher.update(data) self.authenticator.update(cur) if ret: return ret + cur else: return cur def finalize(self): if self.cipher is None: return b"" # empty plaintext input yields empty encrypted output ret = self.cipher.finalize() self.authenticator.update(ret) ret += self.authenticator.finalize() self.cipher = None self.authenticator = None return ret
def _encrypt_from_parts(self, data, adata="", salt = "", signing_key = "", encryption_key = ""): if not isinstance(data, bytes): raise TypeError("data must be bytes.") # print("signing_key = " + str(len(signing_key)), signing_key) # print("encryption_key = " + str(len(encryption_key)), encryption_key) padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher( algorithms.AES(encryption_key), modes.CBC("0"*16), self._backend ).encryptor() # ctx = AES( iv || msg ) ctx = encryptor.update(padded_data) + encryptor.finalize() basic_parts = ( b"\x82" + salt + ctx ) h = HMAC(signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts + adata) # tag = HMAC( 0x81 || iv || ctx ) tag = h.finalize() return base64.urlsafe_b64encode( basic_parts + tag )