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 check_integrity(self, token, ttl=None): # check integrity of files # with our implementation, this is actually superfluous, since if the integrity is compromised, you can't get to # this function. We check the integrity when we decrypt. 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: raise InvalidToken h = HMAC(self._signing_key, hashes.SHA512(), backend=self._backend) h.update(data[:-64]) try: h.verify(data[-64:]) except InvalidSignature: raise InvalidToken
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 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 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 _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 _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 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 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 decrypt_ctr(key, iv, aad, data): """ verify HMAC and decrypt using CTR mode key: 16 byte key iv: 12 bytes nonce. 4 zero bytes are appended to create the 16 byte nonce used for CTR mode aad: bytes. additional unencrypted data to include in the signature data: bytes. plaint text to encrypt """ nonce = iv + b'\x00\x00\x00\x00' ct = data[:-16] tag = data[-16:] h = HMAC(key, SHA256(), backend=default_backend()) h.update(aad) h.update(ct) act = h.finalize()[:16] if not bytes_eq(tag, act): raise ValueError() decryptor = Cipher(AES(key), CTR(nonce), backend=default_backend()).decryptor() return decryptor.update(ct) + decryptor.finalize()
def encrypt_ctr(key, iv, aad, data): """ encrypt using CTR then sign with an HMAC Note: this implementation is similar to AES-CCM, but is slower. The implementation is left in only for benchmarking purposes. Note: in theory this should parallize well, however in practice it is about 2x slower than GCM mode. The HMAC is not the bottleneck key: 16 byte key iv: 12 bytes nonce. 4 zero bytes are appended to create the 16 byte nonce used for CTR mode aad: bytes. additional unencrypted data to include in the signature data: bytes. plaint text to encrypt future work: require key to be 32 bytes, and then use 16 bytes for the HMAC and the other 16 bytes for CTR mode """ nonce = iv + b'\x00\x00\x00\x00' encryptor = Cipher(AES(key), CTR(nonce), backend=default_backend()).encryptor() ct = encryptor.update(data) + encryptor.finalize() h = HMAC(key, SHA256(), backend=default_backend()) h.update(aad) h.update(ct) tag = h.finalize()[:16] return ct + tag
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 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 checkHMAC(self, fp, segments_start, segments_end, fileHMAC): '''Check the file's integrity''' filehash = HMAC(self.hmackey, primitives.hashes.SHA256(), backend) filehash.update(self.FileMACPrefix) for segmentIndex, startpos, datalen in self.segment_ranges(segments_start, segments_end): print(" Segment %d" % (segmentIndex)) fp.seek(startpos) segmentIV = fp.read(self.SegIVLen) segmentMAC = fp.read(self.SegMACLen) # Verify the segment's own MAC against the segment data segmenthash = HMAC(self.hmackey, primitives.hashes.SHA256(), backend) segmenthash.update(segmentIV) segmenthash.update(struct.pack('>I', segmentIndex)) segmenthash.update(fp.read(datalen)) # The cryptography module doesn't handle truncated HMACs directly computed = segmenthash.finalize() assert primitives.constant_time.bytes_eq(computed[:self.SegMACLen], segmentMAC) # Add the segment's MAC to the file-MAC context filehash.update(segmentMAC) # Finally, verify the file MAC print(" File hash") filehash.verify(fileHMAC) # Raises on mismatch.
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
class FernetDecryptMiddleware(BaseMiddleware): """ Decrypt data based on Fernet from the Cryptography library. - Algorithm: AES-128 - Mode: CBC - Padding: PKCS#7 - MAC: SHA-256, Encrypt-then-MAC - Key: User-provided - IV: First 16-bytes of data """ readable = True 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 flush(self): if self.decryptor: data = self.decryptor.finalize() self.decryptor = None self.hmac.update(data) self.hmac.verify(self.check) if data: return self.unpadder.update(data) + self.unpadder.finalize() else: return self.unpadder.finalize() return b'' def read(self, data): if not self.decryptor: if len(data) < 16: self.iv = data return b'' else: self.iv = data[:16] data = data[16:] self.decryptor = Cipher(algorithms.AES(self.key[16:]), modes.CBC(self.iv), backend=default_backend()).decryptor() if not data: return b'' data = self.check + data self.check = data[-32:] data = data[:-32] self.hmac.update(data) data = self.decryptor.update(data) return self.unpadder.update(data)
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 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 hmac(key, data, hash_alg, backend): h = HMAC( key, hash_alg, backend=backend ) h.update(data) return h.finalize()
def _verify(data, mac_key): h = HMAC(mac_key, _MAC_HASH, _backend) h.update(data[:-_MAC_LEN]) try: h.verify(data[-_MAC_LEN:]) return True except InvalidSignature: return False
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 __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 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 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 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 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 _p_hash(self, hash_algorithm, secret, seed, output_length): result = bytearray() i = 1 while len(result) < output_length: h = HMAC(secret, hash_algorithm, default_backend()) h.update(self._a(secret, hash_algorithm, i, seed)) h.update(seed) result.extend(h.finalize()) i += 1 return bytes(result[:output_length])
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 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 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 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 _check_hmac( halg: hashes.HashAlgorithm, hmackey: bytes, enc_cred: bytes, name: bytes, expected: bytes, ): h = HMAC(hmackey, halg(), backend=default_backend()) h.update(enc_cred) h.update(name) h.verify(expected)
def decrypt(self: SSSSData, key: SSSSKey, name: str) -> bytes: keys = key.derive_keys(name) ct = self.ciphertext hm = HMAC(keys.hmac_key, SHA256(), backend = default_backend()) hm.update(ct) hm.verify(self.mac) iv = IV(self.iv) return aes256ctr(iv, keys.aes_key, ct)
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 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 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 _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 _p_hash(hash_algorithm, secret, seed, output_length): """ A seed expansion function that uses a single hash function to expand a secret and seed into the number of bytes specified by output_length. """ result = bytearray() i = 1 while len(result) < output_length: h = HMAC(secret, hash_algorithm, default_backend()) h.update(_a(secret, hash_algorithm, i, seed)) h.update(seed) result.extend(h.finalize()) i += 1 return bytes(result[:output_length])
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 opdata1_verify_overall_hmac(hmac_key, item): verifier = HMAC(hmac_key, SHA256(), backend=_backend) for key, value in sorted(item.items()): if key == 'hmac': continue if isinstance(value, bool): value = str(int(value)).encode('utf-8') else: value = str(value).encode('utf-8') verifier.update(key.encode('utf-8')) verifier.update(value) expected = base64.b64decode(item['hmac']) try: verifier.verify(expected) except InvalidSignature: raise ValueError("HMAC did not match for data dictionary")
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 _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 _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 __init__(self, key, backend=None): if backend is None: backend = default_backend() key = base64.urlsafe_b64decode(key) if len(key) != 32: raise ValueError( "Fernet key must be 32 url-safe base64-encoded bytes." ) h = HMAC(key, hashes.SHA256(), backend=backend) h.update(b"\x00") self._signing_key = h.finalize()[:16] h = HMAC(key, hashes.SHA256(), backend=backend) h.update(b"\x01") self._encryption_key = h.finalize()[:16] self._backend = backend
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, 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 _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)