def test_aes_gcm(backend, wycheproof): key = binascii.unhexlify(wycheproof.testcase["key"]) iv = binascii.unhexlify(wycheproof.testcase["iv"]) aad = binascii.unhexlify(wycheproof.testcase["aad"]) msg = binascii.unhexlify(wycheproof.testcase["msg"]) ct = binascii.unhexlify(wycheproof.testcase["ct"]) tag = binascii.unhexlify(wycheproof.testcase["tag"]) if wycheproof.valid or wycheproof.acceptable: enc = Cipher(algorithms.AES(key), modes.GCM(iv), backend).encryptor() enc.authenticate_additional_data(aad) computed_ct = enc.update(msg) + enc.finalize() computed_tag = enc.tag assert computed_ct == ct assert computed_tag == tag dec = Cipher( algorithms.AES(key), modes.GCM(iv, tag, min_tag_length=len(tag)), backend ).decryptor() dec.authenticate_additional_data(aad) computed_msg = dec.update(ct) + dec.finalize() assert computed_msg == msg elif len(iv) == 0: with pytest.raises(ValueError): Cipher(algorithms.AES(key), modes.GCM(iv), backend) else: dec = Cipher( algorithms.AES(key), modes.GCM(iv, tag, min_tag_length=len(tag)), backend ).decryptor() dec.authenticate_additional_data(aad) dec.update(ct) with pytest.raises(InvalidTag): dec.finalize()
def main(): if type(cipher_key) != str or len(cipher_key) != cipher_key_bytelen: return "no key", 500 auth = request.args.get('auth', None) if auth is None: cleartext = '{"userid":%d,"is_admin":0}' % random.randint(1000000, 2000000) iv = os.urandom(cipher_block_bytelen) padder = padding.PKCS7(cipher.block_size).padder() padded_data = padder.update(cleartext) + padder.finalize() encryptor = Cipher(cipher(cipher_key), modes.CBC(iv), backend=backend).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() return redirect('/?auth=' + binascii.hexlify(iv + ciphertext)) try: received = binascii.unhexlify(auth) except: return "hex error", 400 # print "received" # hexdump.hexdump(received) # sys.stdout.flush() if len(received) < cipher_block_bytelen * 2: return "input too short", 400 iv, ciphertext = received[:cipher_block_bytelen], received[cipher_block_bytelen:] decryptor = Cipher(cipher(cipher_key), modes.CBC(iv), backend=backend).decryptor() decrypted = decryptor.update(ciphertext) + decryptor.finalize() # print "decrypted" # hexdump.hexdump(decrypted) # sys.stdout.flush() unpadder = padding.PKCS7(cipher.block_size).unpadder() unpadded = unpadder.update(decrypted) try: unpadded += unpadder.finalize() except ValueError: return "padding error", 400 # print "unpadded" # hexdump.hexdump(unpadded) # sys.stdout.flush() try: decoded = unpadded.decode('utf-8') parsed = json.loads(decoded) except: return "parsing error", 400 if type(parsed) != dict or 'userid' not in parsed or 'is_admin' not in parsed: return "parsing error", 400 if parsed['is_admin']: return "Hello user #%d, you are admin!" % parsed['userid'] else: return "Hello user #%d!" % parsed['userid']
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 encrypt_v3(a_key, a_token, a_verbose = False): # Get sha-256 of key l_key = hashlib.sha256(a_key).hexdigest().decode('hex') # Generate iv l_iv = os.urandom(G_IV_SIZE_BYTES) # TODO Make constant... # Construct an AES-GCM Cipher object with the given key and a # randomly generated IV. l_encryptor = Cipher( algorithms.AES(l_key), modes.GCM(l_iv), backend=default_backend() ).encryptor() # Encrypt the plaintext and get the associated ciphertext. # GCM does not require padding. l_ciphertext = l_encryptor.update(a_token) + l_encryptor.finalize() l_iv_ciphertext = l_iv + l_ciphertext + l_encryptor.tag #print 'TAG (len:%d) : %s'%(len(l_encryptor.tag), l_encryptor.tag) if a_verbose: print('+-------------------------------------------------------------') print('| l_iv: %s'%(l_iv.encode('hex'))) print('| l_ciphertext: %s'%(l_ciphertext.encode('hex'))) print('| l_tag: %s'%(l_encryptor.tag.encode('hex'))) print('+-------------------------------------------------------------') print('| l_encoded_token: %s'%(l_iv_ciphertext.encode('hex'))) print('+-------------------------------------------------------------') return url_safe_base64_encode(l_iv_ciphertext)
def decrypt(data: bytes, privkey: datatypes.PrivateKey, shared_mac_data: bytes = b'') -> bytes: """Decrypt data with ECIES method using the given private key 1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) ) 2) verify tag 3) decrypt ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R) [where R = r*G, and recipientPublic = recipientPrivate*G] """ if data[:1] != b'\x04': raise DecryptionError("wrong ecies header") # 1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) ) shared = data[1:1 + PUBKEY_LEN] key_material = ecdh_agree(privkey, keys.PublicKey(shared)) key = kdf(key_material) key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:] key_mac = sha256(key_mac).digest() tag = data[-KEY_LEN:] # 2) Verify tag expected_tag = hmac_sha256(key_mac, data[1 + PUBKEY_LEN:- KEY_LEN] + shared_mac_data) if not bytes_eq(expected_tag, tag): raise DecryptionError("Failed to verify tag") # 3) Decrypt algo = CIPHER(key_enc) blocksize = algo.block_size // 8 iv = data[1 + PUBKEY_LEN:1 + PUBKEY_LEN + blocksize] ciphertext = data[1 + PUBKEY_LEN + blocksize:- KEY_LEN] ctx = Cipher(algo, MODE(iv), default_backend()).decryptor() return ctx.update(ciphertext) + ctx.finalize()
def encrypt(data: bytes, pubkey: datatypes.PublicKey, shared_mac_data: bytes = b'') -> bytes: """Encrypt data with ECIES method to the given public key 1) generate r = random value 2) generate shared-secret = kdf( ecdhAgree(r, P) ) 3) generate R = rG [same op as generating a public key] 4) 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag """ # 1) generate r = random value ephemeral = generate_privkey() # 2) generate shared-secret = kdf( ecdhAgree(r, P) ) key_material = ecdh_agree(ephemeral, pubkey) key = kdf(key_material) key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:] key_mac = sha256(key_mac).digest() # 3) generate R = rG [same op as generating a public key] ephem_pubkey = ephemeral.public_key # Encrypt algo = CIPHER(key_enc) iv = os.urandom(algo.block_size // 8) ctx = Cipher(algo, MODE(iv), default_backend()).encryptor() ciphertext = ctx.update(data) + ctx.finalize() # 4) 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag msg = b'\x04' + ephem_pubkey.to_bytes() + iv + ciphertext # the MAC of a message (called the tag) as per SEC 1, 3.5. tag = hmac_sha256(key_mac, msg[1 + PUBKEY_LEN:] + force_bytes(shared_mac_data)) return msg + tag
def unwrap(self, key, ek): rk = self.get_key(key, 'decrypt') # Implement RFC 3394 Key Unwrap - 2.2.3 # TODO: Use cryptography once issue #1733 is resolved iv = 'a6a6a6a6a6a6a6a6' Aiv = unhexlify(iv) R = [ek[i:i+8] for i in range(0, len(ek), 8)] A = R.pop(0) n = len(R) for j in range(5, -1, -1): for i in range(n - 1, -1, -1): AtR = _encode_int((_decode_int(A) ^ ((n*j)+i+1)), 64) + R[i] d = Cipher(algorithms.AES(rk), modes.ECB(), backend=self.backend).decryptor() B = d.update(AtR) + d.finalize() A = B[:8] R[i] = B[-8:] if A != Aiv: raise InvalidJWEData('Decryption Failed') cek = b''.join(R) return cek
def decrypt(self, n, ad, ciphertext): ''' Returns plaintext or raises MessageAuthenticationFailure exception if fail to authenticate. ''' if len(ciphertext) < 16: raise ValueError( 'Invalid ciphertext length (len={0}), must be >16 bytes.'.format(len(ciphertext)) ) n = self._nonce(n) decryptor = Cipher( algorithms.AES(self.key), modes.GCM(n, ciphertext[-16:]), backend=default_backend() ).decryptor() decryptor.authenticate_additional_data(ad) try: plaintext = decryptor.update(ciphertext[:-16]) + decryptor.finalize() except _InvalidTag: raise MessageAuthenticationFailure except: raise return plaintext
def decrypt(self, data, ttl=None): """ :type data: bytes :type ttl: int :rtype: bytes """ data = self._signer.unsign(data, ttl) iv = data[:16] ciphertext = data[16:] 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 # Remove padding 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_aesgcm(key, nonce, ciphertext_tag, associated_data): """ Decrypts a ciphertext with associated data with AES GCM. Args: key: encryption key nonce: nonce for encryption ciphertext_tag: ciphertext with appended tag to decrypt associated_data: additional authenticated associated data (the AD in AEAD) Returns: decrypted plaintext """ if len(ciphertext_tag) < MAC_BYTES: raise NoiseError('Truncated ciphertext (length < authentication tag length).') algo = algorithms.AES(key) assert len(nonce) == 12, 'Expected 96 bit nonce for AES-GCM' ciphertext, tag = ciphertext_tag[:-MAC_BYTES], ciphertext_tag[-MAC_BYTES:] mode = modes.GCM(nonce, tag) decryptor = Cipher(algo, mode, backend).decryptor() decryptor.authenticate_additional_data(associated_data) try: return decryptor.update(ciphertext) + decryptor.finalize() except InvalidTag as invalid_tag: raise NoiseError('GMAC failure') from invalid_tag
def decrypt(self, orig_pkt, assoclen=None): """decrypt a MACsec frame for this Secure Association""" hdr = copy.deepcopy(orig_pkt) del hdr[MACsec].payload pktlen = len(orig_pkt) if self.send_sci: hdrlen = NOSCI_LEN + SCI_LEN else: hdrlen = NOSCI_LEN if assoclen is None or not self.do_encrypt: if self.do_encrypt: assoclen = hdrlen else: assoclen = pktlen - self.icvlen iv = self.make_iv(hdr) assoc, ct, icv = MACsecSA.split_pkt(orig_pkt, assoclen, self.icvlen) decryptor = Cipher( algorithms.AES(self.key), modes.GCM(iv, icv), backend=default_backend() ).decryptor() decryptor.authenticate_additional_data(assoc) pt = assoc[hdrlen:assoclen] pt += decryptor.update(ct) pt += decryptor.finalize() hdr[MACsec].type = struct.unpack('!H', pt[0:2])[0] hdr[MACsec].payload = Raw(pt[2:]) return hdr
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 decrypt(value, key, stash=None): """ Return a decrypted value """ # extract fields using a regex res = re.match(r'^ENC\[AES256_GCM,data:(.+),iv:(.+),aad:(.+),tag:(.+)\]$', value) # if the value isn't in encrypted form, return it as is if res is None: return value enc_value = b64decode(res.group(1)) iv = b64decode(res.group(2)) aad = b64decode(res.group(3)) tag = b64decode(res.group(4)) decryptor = Cipher(algorithms.AES(key), modes.GCM(iv, tag), default_backend() ).decryptor() decryptor.authenticate_additional_data(aad) cleartext = decryptor.update(enc_value) + decryptor.finalize() if stash: # save the values for later if we need to reencrypt stash['iv'] = iv stash['aad'] = aad stash['cleartext'] = cleartext return cleartext
def decrypt(data, key): iv = data[0:16] data = data[16:] cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()).decryptor() data = cipher.update(data) + cipher.finalize() padder = padding.PKCS7(128).unpadder() return padder.update(data) + padder.finalize()
def decrypt(self, data): """ Decrypts an AESGCM payload. Relies on constants: :attr:`~crypto.aesgcm.IV_SIZE` :attr:`~crypto.aesgcm.TAG_SIZE` :param data: The raw data to decrypt :type data: bytes :returns: Decrypted data :rtype: bytes """ iv = data[:IV_SIZE] payload = data[IV_SIZE: -TAG_SIZE] tag = data[-TAG_SIZE:] decryptor = Cipher( algorithms.AES(self.key), modes.GCM(iv, tag), backend=default_backend() ).decryptor() decryptor.authenticate_additional_data(iv) return decryptor.update(payload) + decryptor.finalize()
def lookup_origin_text( self, secure_text: str, valid_length: Optional[int]=None) -> str: try: encrypted_text_reader = io.BytesIO(base64.b64decode(secure_text)) except: # Unable to decode the data. return None try: iv = encrypted_text_reader.read(16) length = struct.unpack("l", encrypted_text_reader.read(8))[0] ciphertext = encrypted_text_reader.read(length) tag = encrypted_text_reader.read(16) except: # Unable to split the data. return None decryptor = AESCipher( aes_algorithms.AES(self._security_secret), aes_modes.GCM(iv, tag), backend=aes_backend() ).decryptor() try: content = decryptor.update(ciphertext) + decryptor.finalize() except: # Unable to decrypt and/or verify the data. return None timestamp = struct.unpack("l", content[:8])[0] text = content[8:] if valid_length and int(time.time()) - timestamp > valid_length: return None # Data Expired. return ensure_str(text)
def encrypt(self, data): """ .. warning:: This should really have thread controls in it. If two threads are simutaneously encrypting, there is a small chance that the IVs would be the same. This would be **extremely** bad. :param data: The data to encrypt :type data: bytes :returns: IV + payload + TAG :rtype: bytes """ # Grab && increment iv iv = self.iv self.iv = (int.from_bytes(iv, 'big') + 1).to_bytes(len(iv), 'big') # TODO: Do we have to make the encryptor every time? # Make the encryptor encryptor = Cipher(algorithms.AES(self.key), modes.GCM(iv), backend=default_backend() ).encryptor() # Encrypt the data encryptor.authenticate_additional_data(iv) ciphertext = encryptor.update(data) + encryptor.finalize() return iv + ciphertext + encryptor.tag
def encrypt(self, orig_pkt, assoclen=None): """encrypt a MACsec frame for this Secure Association""" hdr = copy.deepcopy(orig_pkt) del hdr[MACsec].payload del hdr[MACsec].type pktlen = len(orig_pkt) if self.send_sci: hdrlen = NOSCI_LEN + SCI_LEN else: hdrlen = NOSCI_LEN if assoclen is None or not self.do_encrypt: if self.do_encrypt: assoclen = hdrlen else: assoclen = pktlen iv = self.make_iv(orig_pkt) assoc, pt, _ = MACsecSA.split_pkt(orig_pkt, assoclen) encryptor = Cipher( algorithms.AES(self.key), modes.GCM(iv), backend=default_backend() ).encryptor() encryptor.authenticate_additional_data(assoc) ct = encryptor.update(pt) + encryptor.finalize() hdr[MACsec].payload = Raw(assoc[hdrlen:assoclen] + ct + encryptor.tag) return hdr
def aes_encrypt(passphrase, data): enc_salt = os.urandom(32) enc_iv = os.urandom(16) kdf = PBKDF2HMAC( algorithm=hashes.SHA1(), length=32, salt=enc_salt, iterations=1000, backend=default_backend(), ) enc_key = kdf.derive(passphrase) data += '\x00' * (16 - (len(data) % 16)) cipher = Cipher( algorithms.AES(enc_key), modes.CBC(enc_iv), backend=default_backend() ).encryptor() enc_data = cipher.update(data) + cipher.finalize() return '\n'.join([ base64.b64encode(enc_salt), base64.b64encode(enc_iv), base64.b64encode(enc_data), ])
def aes_key_wrap(wrapping_key, key_to_wrap, backend): if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") if len(key_to_wrap) < 16: raise ValueError("The key to wrap must be at least 16 bytes") if len(key_to_wrap) % 8 != 0: raise ValueError("The key to wrap must be a multiple of 8 bytes") # RFC 3394 Key Wrap - 2.2.1 (index method) encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] n = len(r) for j in range(6): for i in range(n): # every encryption operation is a discrete 16 byte chunk (because # AES has a 128-bit block size) and since we're using ECB it is # safe to reuse the encryptor for the entire operation b = encryptor.update(a + r[i]) # pack/unpack are safe as these are always 64-bit chunks a = struct.pack( ">Q", struct.unpack(">Q", b[:8])[0] ^ ((n * j) + i + 1) ) r[i] = b[-8:] assert encryptor.finalize() == b"" return a + b"".join(r)
def aes_key_unwrap(wrapping_key, wrapped_key, backend): if len(wrapped_key) < 24: raise ValueError("Must be at least 24 bytes") if len(wrapped_key) % 8 != 0: raise ValueError("The wrapped key must be a multiple of 8 bytes") if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] a = r.pop(0) n = len(r) for j in reversed(range(6)): for i in reversed(range(n)): # pack/unpack are safe as these are always 64-bit chunks atr = struct.pack( ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1) ) + r[i] # every decryption operation is a discrete 16 byte chunk so # it is safe to reuse the decryptor for the entire operation b = decryptor.update(atr) a = b[:8] r[i] = b[-8:] assert decryptor.finalize() == b"" if not bytes_eq(a, aiv): raise InvalidUnwrap() return b"".join(r)
def generate_secure_text(self, origin_text: str) -> str: """ Encrypt and sign the origin text by ``cryptography`` library using AES GCM algorithm. :arg origin_text: is a string that will be encrypted by the provided security secret. """ iv = os.urandom(16) content = struct.pack( "l", int(time.time())) + ensure_bytes(origin_text) encryptor = AESCipher( aes_algorithms.AES(ensure_bytes(self.__security_secret)), aes_modes.GCM(iv), backend=aes_backend() ).encryptor() ciphertext = encryptor.update(content) + encryptor.finalize() final_encrypted_text = iv final_encrypted_text += struct.pack("l", len(ciphertext)) final_encrypted_text += ciphertext final_encrypted_text += encryptor.tag return ensure_str(base64.b64encode(final_encrypted_text))
def decrypt_file(cipher_text): iv = cipher_text[:IV_LEN] decryptor = Cipher( algorithms.AES(key), modes.GCM(iv, cipher_text[IV_LEN:IV_LEN+TAG_LEN]), backend=b.default_backend()).decryptor() return decryptor.update(cipher_text[IV_LEN+TAG_LEN:]) + decryptor.finalize()
def decrypt(packed_encrypted_data, key, mac_key='', backend=BACKEND): """ Decrypts packed encrypted data as returned by encrypt with the same key. If extra data is present, returns plaintext, extra_data. If not, returns plaintext. Raises InvalidTag on authentication failure. """ header, ciphertext, iv, tag, extra_data = load_data(packed_encrypted_data) algorithm, mode, authentication_algorithm = header.split('_', 2) if algorithm.lower() in hashlib.algorithms_guaranteed: return cryptographyless.decrypt(packed_encrypted_data, key, mac_key, backend) mode_args = (iv, tag) if mode in AEAD_MODES else (iv, ) decryptor = Cipher(getattr(algorithms, algorithm)(key), getattr(modes, mode)(*mode_args), backend=BACKEND).decryptor() if mode in AEAD_MODES: decryptor.authenticate_additional_data(extra_data) else: if not mac_key: raise ValueError("mac_key not supplied for {} mode".format(header)) if not verify_mac(mac_key, save_data(tag, header + ciphertext + iv + extra_data), authentication_algorithm): raise InvalidTag("Failed to authenticate data") plaintext = decryptor.update(ciphertext) + decryptor.finalize() if extra_data: return (plaintext, extra_data) else: return plaintext
def unwrap(self, key, keylen, ek, headers): rk = self._get_key(key, 'decrypt') # Implement RFC 3394 Key Unwrap - 2.2.3 # TODO: Use cryptography once issue #1733 is resolved iv = 'a6a6a6a6a6a6a6a6' aiv = unhexlify(iv) r = [ek[i:i + 8] for i in range(0, len(ek), 8)] a = r.pop(0) n = len(r) for j in range(5, -1, -1): for i in range(n - 1, -1, -1): da = _decode_int(a) atr = _encode_int((da ^ ((n * j) + i + 1)), 64) + r[i] d = Cipher(algorithms.AES(rk), modes.ECB(), backend=self.backend).decryptor() b = d.update(atr) + d.finalize() a = b[:8] r[i] = b[-8:] if a != aiv: raise InvalidJWEData('Decryption Failed') cek = b''.join(r) if len(cek) != keylen: raise InvalidJWEKeyLength(keylen, len(cek)) return cek
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 decrypt(key, associated_data, iv, ciphertext, tag): # Construct a Cipher object, with the key, iv, and additionally the # GCM tag used for authenticating the message. # OK.. all the objects passed in to this function are of type bytearray, but, it turns # out that the Cipher suite needs strings, despite saying in the documentation that it needs # bytes. Consequently all the parameter objects had to be converted to strings, hence the str() # around each one. # The moral of this story is strong typing is good. try: decryptor = Cipher( algorithms.AES(str(key)), modes.GCM(str(iv), str(tag)), backend=default_backend() ).decryptor() # We put associated_data back in or the tag will fail to verify # when we finalize the decryptor. decryptor.authenticate_additional_data(str(associated_data)) # Decryption gets us the authenticated plaintext. # If the tag does not match an InvalidTag exception will be raised. ret = decryptor.update(str(ciphertext)) + decryptor.finalize() except Exception as e: print(" Failed to de-crypt Measurement with exception: {}: {}".format(e.__class__.__name__, e)) ret = None return ret
def encrypt(encryption_key, iv, data): """Encrypt the payload.""" padder = padding.PKCS7(algorithms.AES.block_size).padder() data = padder.update(data.encode()) + padder.finalize() encryptor = Cipher(algorithms.AES(encryption_key), modes.CBC(iv), default_backend()).encryptor() return base64.urlsafe_b64encode(encryptor.update(data) + encryptor.finalize())
def aes_decrypt(passphrase, data): data = data.split('\n') if len(data) < 3: raise ValueError('Invalid encryption data') enc_salt = base64.b64decode(data[0]) enc_iv = base64.b64decode(data[1]) enc_data = base64.b64decode(data[2]) kdf = PBKDF2HMAC( algorithm=hashes.SHA1(), length=32, salt=enc_salt, iterations=1000, backend=default_backend(), ) enc_key = kdf.derive(passphrase) cipher = Cipher( algorithms.AES(enc_key), modes.CBC(enc_iv), backend=default_backend() ).decryptor() data = cipher.update(enc_data) + cipher.finalize() return data.replace('\x00', '')
def encrypt(data='', key='', mac_key='', iv=None, extra_data='', algorithm="AES", mode="GCM", backend=BACKEND, iv_size=16, hash_algorithm="SHA256", return_mode="cryptogram"): """ Encrypts data with the specified key. Returns packed encrypted bytes. If an iv is not supplied a random one of iv_size will be generated. By default, the GCM mode of operation is used and the iv is automatically included in the extra_data authenticated by the mode. Note that not all algorithms may support all modes of operation with all backends. A mac key is required when GCM mode is not in used. This function will refuse to encrypt data without authentication/integrity checks, as this is considered a serious flaw in security. Technically speaking, 'iv' is not always the correct term for the parameter passed, depending on the mode of operation used. However, using two different fields for what are functionally the same would increase complexity needlessly. """ assert data and key, "data" if not data else "key" if algorithm.lower() in hashlib.algorithms_guaranteed: return cryptographyless.encrypt(data, key, iv, extra_data, algorithm, mode, backend, iv_size, mac_key, hash_algorithm) header = algorithm + '_' + mode if mode not in AEAD_MODES: if not mac_key: raise ValueError("Unable to authenticate data because no mac key was supplied for {} mode".format(header)) else: header += "_" + hash_algorithm else: header += "_" + "AEAD" if not iv and iv != 0: # 0 is a valid nonce for CTR mode. iv = random_bytes(iv_size) if mode != "ECB": mode_args = (iv, ) else: mode_args = tuple() encryptor = Cipher(getattr(algorithms, algorithm)(key), getattr(modes, mode)(*mode_args), backend=BACKEND).encryptor() if mode in AEAD_MODES: encryptor.authenticate_additional_data(extra_data) ciphertext = encryptor.update(data) + encryptor.finalize() if mode in AEAD_MODES: mac_tag = encryptor.tag else: mac_tag = generate_mac(mac_key, header + ciphertext + iv + extra_data, hash_algorithm) if return_mode == "cryptogram": return save_data(header, ciphertext, iv, mac_tag, extra_data) else: assert return_mode == "values" return header, ciphertext, iv, mac_tag, extra_data
def aes_key_wrap_with_padding( wrapping_key: bytes, key_to_wrap: bytes, backend: typing.Any = None, ) -> bytes: if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap)) # pad the key to wrap if necessary pad = (8 - (len(key_to_wrap) % 8)) % 8 key_to_wrap = key_to_wrap + b"\x00" * pad if len(key_to_wrap) == 8: # RFC 5649 - 4.1 - exactly 8 octets after padding encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() b = encryptor.update(aiv + key_to_wrap) assert encryptor.finalize() == b"" return b else: r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] return _wrap_core(wrapping_key, aiv, r)
def list_command(args): print("received list command") #PEER_LIST['server'] key = make_aes_key(PEER_LIST['server']['encryption_key']) print key print len(key) iv = os.urandom(12) encryptor = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend()).encryptor() encryption_prep = {'ask': args.user} cipherkt = encryptor.update( json.dumps(encryption_prep)) + encryptor.finalize() tagkey = encryptor.tag pickled_packet = pickle.dumps({ 'list_please': cipherkt, 'IV': iv, 'TAG': tagkey, 'ask': args.user }) PEER_SOCKETS['server'].send(base64.b64encode(pickled_packet))
def solve_puzzle(args, pack): server_socket = PEER_SOCKETS['server'] puz_num = pack['puzz'] ans_puz = len(get_primes(puz_num)) encryptor = Cipher(algorithms.AES(MASTER_KEY), modes.GCM(MASTER_IV), backend=default_backend()).encryptor() Na = random.randint(0, 65535) puzz_ans_packet = {'puzzle': ans_puz, 'Na': Na} packet_prep = json.dumps(puzz_ans_packet) cipherpuzzle = encryptor.update(packet_prep) + encryptor.finalize() tag = encryptor.tag aes_packet = {'solution': cipherpuzzle, 'iv': MASTER_IV, 'tag': tag} aes_packet_pickle = pickle.dumps(aes_packet).encode('base64', 'strict') server_socket.send(aes_packet_pickle)
def decrypt_aes_gcm(key, initial_value, cipher_text, aad=None): """ Decrypt using AES-GCM Args: aes encryption key cipher text and tag initial value additional authenticated data Return: (true, plain text) """ cipher = Cipher(algorithms.AES(key), modes.GCM(initial_value, cipher_text[-16:]), backend=default_backend()).decryptor() if aad: cipher.authenticate_additional_data(aad) try: plaintext = cipher.update(cipher_text[:-16]) + cipher.finalize() return plaintext except InvalidTag: print 'GCM decryption failed'
def _unwrap_core(wrapping_key, a, r, backend): # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() n = len(r) for j in reversed(range(6)): for i in reversed(range(n)): # pack/unpack are safe as these are always 64-bit chunks atr = ( struct.pack( ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1) ) + r[i] ) # every decryption operation is a discrete 16 byte chunk so # it is safe to reuse the decryptor for the entire operation b = decryptor.update(atr) a = b[:8] r[i] = b[-8:] assert decryptor.finalize() == b"" return a, r
def decifrar(msg, passphrase): ciphertext = msg['ciph'] salt = msg['salt'] tag = msg['tag'] iv = msg['iv'] key = passwd(passphrase, salt) #gerar mac utilizando a informação recebida e comparar if tag == mac(key, ciphertext): #desencriptar cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend()).decryptor() plaintext = cipher.update(ciphertext) + cipher.finalize() print('Mensagem cifrada:', ciphertext) print('Mensagem decifrada:', plaintext) else: print('Tags diferentes') plaintext = b"erro" return plaintext
def encrypt(key, plaintext, utf8_random, iv=None, associated_data=None): """Encrypt as done in Turtl: AES GCM with a prefix telling if it's UTF8 or binary, """ # Generate a random 96-bit IV if needed if iv is None: iv = os.urandom(12) if isinstance(plaintext, str): utf8byte = chr(math.floor(utf8_random * (256 - 128)) + 128) plaintext = utf8byte.encode() + plaintext.encode() else: utf8byte = chr(math.floor(utf8_random * (256 - 128))) plaintext = utf8byte.encode() + plaintext encryptor = Cipher( algorithms.AES(key), modes.GCM(iv), backend=default_backend() ).encryptor() encryptor.authenticate_additional_data(associated_data) ciphertext = encryptor.update(plaintext) + encryptor.finalize() return (iv, ciphertext, encryptor.tag)
def aes_decrypt(_key, iv, payload): """ Use AES128 GCM with the given key and iv to decrypt the payload. """ if len(_key) >= 32: # XEP-0384 log.debug('XEP Compliant Key/Tag') data = payload key = _key[:16] tag = _key[16:] else: # Legacy log.debug('Legacy Key/Tag') data = payload[:-16] key = _key tag = payload[-16:] if os.name == 'nt': _backend = backend else: _backend = default_backend() decryptor = Cipher(algorithms.AES(key), GCM(iv, tag=tag), backend=_backend).decryptor() return decryptor.update(data) + decryptor.finalize()
def decrypt(self, ciphertext, ref_key, media_info): derived = HKDFv3().deriveSecrets(ref_key, media_info, 112) parts = ByteUtil.split(derived, 16, 32) iv = parts[0] key = parts[1] mac_key = derived[48:80] media_ciphertext = ciphertext[:-10] mac_value = ciphertext[-10:] mac = hmac.new(mac_key, digestmod=hashlib.sha256) mac.update(iv) mac.update(media_ciphertext) if mac_value != mac.digest()[:10]: raise ValueError("Invalid MAC") cipher_decryptor = Cipher( algorithms.AES(key), modes.CBC(iv), backend=default_backend() ).decryptor() return cipher_decryptor.update(media_ciphertext) + cipher_decryptor.finalize()
def decrypt_AES(self, key, iv, data_encrypted, modo, tag=None): if modo == "CBC": cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) decryptor = cipher.decryptor() unpadder = padding.PKCS7(128).unpadder() data = decryptor.update(data_encrypted) + decryptor.finalize() info = unpadder.update(data) + unpadder.finalize() return info elif modo == "GCM": decryptor = Cipher( algorithms.AES(key), modes.GCM(iv, tag), ).decryptor() decryptor.authenticate_additional_data(b'associated_data') return decryptor.update(data_encrypted) + decryptor.finalize() else: print("Erro") sys.exit(0)
def gcm_encrypt(plaintext, key, associated_data): # AES len(decode(key))*8 GCM # only 128, 192 or 256 bits long supported. try: key = decode(key) except Error: return False # 12 bytes IV is strongly suggested. do NOT change it. iv = os.urandom(12) encryptor = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend).encryptor() encryptor.authenticate_additional_data(associated_data.encode('utf-8')) return encode( encryptor.update(plaintext.encode('utf-8')) + encryptor.finalize(), iv, encryptor.tag)
def _encrypt(pt, key, alg, iv=None): if iv is None: iv = b'\x00' * (alg.block_size // 8) if alg.is_insecure: raise PGPInsecureCipher( "{:s} is not secure. Do not use it for encryption!".format( alg.name)) if not alg.is_supported: raise PGPEncryptionError("Cipher {:s} not supported".format(alg.name)) try: encryptor = Cipher(alg.cipher(key), modes.CFB(iv), default_backend()).encryptor() except UnsupportedAlgorithm as ex: # pragma: no cover six.raise_from(PGPEncryptionError, ex) else: return bytearray(encryptor.update(pt) + encryptor.finalize())
def receive_session_key(args, data): #print data print 'SESSION STUFF' server_socket = PEER_SOCKETS['server'] tagkey = data['tag'] kt_packet = data['acceptance'] iv = data['IV'] decryptor = Cipher(algorithms.AES(MASTER_KEY), modes.GCM(iv, tagkey), backend=default_backend()).decryptor() decrypted_packet = pickle.loads( base64.b64decode(decryptor.update(kt_packet) + decryptor.finalize())) #add nonce check PEER_LIST['server']['encryption_key'] = decrypted_packet['session_key'] PEER_LIST[args.user]['TGT'] = decrypted_packet['TGT'] print 'TGT and session key received' print PEER_LIST print 'Connected to remote server. You can start sending messages'
def encrypt(key, plaintext, associated_data): # Generate a random 96-bit IV. iv = os.urandom(12) # Construct an AES-GCM Cipher object with the given key and a # randomly generated IV. encryptor = Cipher( algorithms.AES(key), modes.GCM(iv), backend=default_backend() ).encryptor() # associated_data will be authenticated but not encrypted, # it must also be passed in on decryption. encryptor.authenticate_additional_data(associated_data) # Encrypt the plaintext and get the associated ciphertext. # GCM does not require padding. ciphertext = encryptor.update(plaintext) + encryptor.finalize() return (iv, ciphertext, encryptor.tag)
def decrypt(master_keys, ciphertext_blob, encryption_context): """Decrypt a ciphertext blob using a master key material. NOTE: This is not necessarily what KMS does, but it retains the same properties. NOTE: This function is NOT compatible with KMS APIs. :param dict master_keys: Mapping of a KmsBackend's known master keys :param bytes ciphertext_blob: moto-structured ciphertext blob encrypted under a moto master key in master_keys :param dict[str, str] encryption_context: KMS-style encryption context :returns: plaintext bytes and moto key ID :rtype: bytes and str """ try: ciphertext = _deserialize_ciphertext_blob(ciphertext_blob=ciphertext_blob) except Exception: raise InvalidCiphertextException() aad = _serialize_encryption_context(encryption_context=encryption_context) try: key = master_keys[ciphertext.key_id] except KeyError: raise AccessDeniedException( "The ciphertext refers to a customer master key that does not exist, " "does not exist in this region, or you are not allowed to access." ) try: decryptor = Cipher( algorithms.AES(key.key_material), modes.GCM(ciphertext.iv, ciphertext.tag), backend=default_backend(), ).decryptor() decryptor.authenticate_additional_data(aad) plaintext = decryptor.update(ciphertext.ciphertext) + decryptor.finalize() except Exception: raise InvalidCiphertextException() return plaintext, ciphertext.key_id
def decriptografar(self): if self.__formulaHashOuCriptoEscolhida in self._Criptografia_para_escolher: cripto = self.__formulaHashOuCriptoEscolhida.split('_') algoritmo = getattr(algorithms, cripto[0]) block_size = getattr(algoritmo, 'block_size', None) try: msgEnc = bytes.fromhex(self._txtEntradaDados.GetValue()) chave = bytes.fromhex(self._txtChave.GetValue()) iv = bytes.fromhex(self._txtIV.GetValue()) if len(cripto) > 1: modo = getattr(modes, cripto[1], None) if cripto[1] == 'GCM': tag = msgEnc[-16:] msgEnc = msgEnc[0:-16] modo = None if modo is None else modo(iv, tag) else: modo = None if modo is None else modo(iv) else: modo = None if modo is not None: decriptor = Cipher(algoritmo(chave), modo, backend=default_backend()).decryptor() else: decriptor = Cipher(algoritmo(chave, iv), modo, backend=default_backend()).decryptor() mensagemDecriptada = decriptor.update( msgEnc) + decriptor.finalize() if block_size is not None: try: unpadder = pad.PKCS7(block_size).unpadder() mensagemDecriptada = unpadder.update( mensagemDecriptada) + unpadder.finalize() except: pass self._txtSaidaDados.Clear() self._txtSaidaDados.WriteText(mensagemDecriptada.decode()) except ValueError as error: self.error_dialog(error.args[0])
def encrypt_into_file(infile, key=None, nonce=None, outfile=None): if isinstance(infile, bytes): infile = BytesIO(infile) elif isinstance(infile, str): infile = BytesIO(base64.b64decode(infile)) if not outfile: outfile = tempfile.NamedTemporaryFile( suffix=".encrypt", dir=settings.FILE_UPLOAD_TEMP_DIR ) nonce = os.urandom(13) if not key: key = os.urandom(32) encryptor = Cipher(algorithms.AES(key), modes.GCM(nonce)).encryptor() chunk = infile.read(512) while chunk: assert isinstance(chunk, bytes) outfile.write(encryptor.update(chunk)) chunk = infile.read(512) outfile.write(encryptor.finalize()) outfile.write(encryptor.tag) return outfile, nonce, key
def _decrypt_cryptography(cls, b_salt, b_ciphertext, b_password, key_length): bs = algorithms.AES.block_size // 8 b_key, b_iv = cls._aes_derive_key_and_iv(b_password, b_salt, key_length, bs) cipher = C_Cipher(algorithms.AES(b_key), modes.CBC(b_iv), CRYPTOGRAPHY_BACKEND).decryptor() unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() try: b_plaintext_envelope = unpadder.update( cipher.update(b_ciphertext) + cipher.finalize() ) + unpadder.finalize() except ValueError: # In VaultAES, ValueError: invalid padding bytes can mean bad # password was given raise AnsibleError("Decryption failed") b_plaintext, b_this_sha, b_test_sha = cls._parse_plaintext_envelope(b_plaintext_envelope) if b_this_sha != b_test_sha: raise AnsibleError("Decryption failed") return b_plaintext
def encrypt(key, iv, plaintext, associated_data): '''encrypt plaintext and mac with associated_data under key and iv uses AES-256-GCM ''' # Construct an AES-GCM Cipher object with the given key and a # randomly generated parse_rescue_block. encryptor = Cipher( algorithms.AES(key), modes.GCM(iv), backend=default_backend() ).encryptor() # associated_data will be authenticated but not encrypted, # it must also be passed in on decryption. encryptor.authenticate_additional_data(associated_data) # Encrypt the plaintext and get the associated ciphertext. # GCM does not require padding. ciphertext = encryptor.update(plaintext) + encryptor.finalize() return (ciphertext, encryptor.tag)
def decrypt(self): """Decrypt a blob using LPS. Implements FALLBACK and DP methods to derive or obtain the encryption key from the one stored in the PSE/credential file and then uses that encryption key to decrypt the credential using the AES cipher. LPS-protected PSEs/credentials are verified with both a CRC32 checksum and an HMAC. Validation of the checksum and HMAC is not implemented. :return: decrypted object :rtype: string :raise NotImplemented: if the LPS method is not implemented :raise SAP_LPS_Decryption_Error: if there's an error decrypting the object """ # Validate supported version if self.version != 2: log_lps.error("Version not supported") raise SAP_LPS_Decryption_Error("Version not supported") # TODO: Calculate and validate CRC32 # Decrypt the encryption key using the LPS method if self.lps_type in lps_encryption_key_decryptor: encryption_key = lps_encryption_key_decryptor[self.lps_type](self) else: log_lps.error("Invalid LPS decryption method") raise SAP_LPS_Decryption_Error("Invalid LPS decryption method") # Decrypt the cipher text with the encryption key iv = "\x00" * 16 decryptor = Cipher(algorithms.AES(encryption_key), modes.CBC(iv), backend=default_backend()).decryptor() plain = decryptor.update(self.encrypted_data) + decryptor.finalize() # TODO: Calculate and validate HMAC return plain
def wrap(self, key, keylen, cek): rk = self.get_key(key, 'encrypt') if not cek: cek = os.urandom(keylen) # Implement RFC 3394 Key Unwrap - 2.2.2 # TODO: Use cryptography once issue #1733 is resolved iv = 'a6a6a6a6a6a6a6a6' A = unhexlify(iv) R = [cek[i:i+8] for i in range(0, len(cek), 8)] n = len(R) for j in range(0, 6): for i in range(0, n): e = Cipher(algorithms.AES(rk), modes.ECB(), backend=self.backend).encryptor() B = e.update(A + R[i]) + e.finalize() A = _encode_int(_decode_int(B[:8]) ^ ((n*j)+i+1), 64) R[i] = B[-8:] ek = A for i in range(0, n): ek += R[i] return (cek, ek)
def decrypt(self, ciphertext, ciphertext_key, iv, tag, encryption_context={}): """Decrypt CIS payload using KMS encrypted key. :ciphertext: encrypted payload :ciphertext_key: encrypted KMS derived key :iv: AES initialization vector used to encrypt payload :tag: AES GCM authentication code """ if self.plaintext_key is None: self.plaintext_key = self._decrypt_envelope_with_kms( ciphertext_key, encryption_context) decryptor = Cipher(algorithms.AES(self.plaintext_key), modes.GCM(iv, tag), backend=default_backend()).decryptor() return decryptor.update(ciphertext) + decryptor.finalize()
async def decrypt_file(key: bytes, input_file_name: str, output_file_name: str, associated_data: bytes, chunk_size: int = CHUNK_SIZE) -> None: async with aiofiles.open(input_file_name, 'rb') as fin, aiofiles.open( output_file_name, 'wb') as fout: _version, iv, tag = struct.unpack( '<Q12s16s', await fin.read(struct.calcsize('Q12s16s'))) if _version != AESGCMEncrypt.VERSION: raise AESGCMEncrypt.VersionException( f'Except {AESGCMEncrypt.VERSION} but {_version} found.') decryptor = Cipher( algorithms.AES(key), # type: ignore modes.GCM(iv, tag), # type: ignore backend=default_backend()).decryptor() decryptor.authenticate_additional_data( associated_data) # type: ignore # reader = lib_aes_gcm.chunk_reader(fin, file_size) while chunk := await fin.read(chunk_size): await fout.write(decryptor.update(chunk)) await fout.write(decryptor.finalize())
def decrypt(self, buf, ad=None): if len(buf) == 0: raise ValueError('buf should not be empty') ct, tag = buf[:self._tag_len * -1], buf[self._tag_len * -1:] if self._decryptor_skey is None: iv, ct = ct[:self._iv_len], ct[self._iv_len:] IV_CHECKER.check(self.__key, iv) self._decryptor_skey = self.key_expand(self.__key, iv, hashlib.sha1) del self.__key nonce = struct.pack('<Q', self._decryptor_nonce) + b'\x00\x00\x00\x00' self._decryptor_nonce += 1 decryptor = Cipher(self.algorithm(self._decryptor_skey), modes.GCM(nonce, tag), backend=default_backend()).decryptor() if ad: decryptor.authenticate_additional_data(ad) return decryptor.update(ct) + decryptor.finalize()
class Decryptor(object): """Abstract decryption handler. :param algorithm: Algorithm used to encrypt this body :type algorithm: aws_encryption_sdk.identifiers.Algorithm :param bytes key: Raw source key :param bytes associated_data: Associated Data to send to decryption subsystem :param bytes iv: IV value with which to initialize decryption subsystem :param bytes tag: Tag with which to validate ciphertext """ def __init__(self, algorithm, key, associated_data, iv, tag): """Prepares initial values.""" self.source_key = key # Construct a decryptor object with the given key and a provided IV. # This is intentionally generic to leave an option for non-Cipher decryptor types in the future. self._decryptor = Cipher(algorithm.encryption_algorithm(key), algorithm.encryption_mode(iv, tag), backend=default_backend()).decryptor() # Put associated_data back in or the tag will fail to verify when the _decryptor is finalized. self._decryptor.authenticate_additional_data(associated_data) def update(self, ciphertext): """Updates _decryptor with provided ciphertext. :param bytes ciphertext: Ciphertext to decrypt :returns: Decrypted plaintext :rtype: bytes """ return self._decryptor.update(ciphertext) def finalize(self): """Finalizes and closes _decryptor. :returns: Final decrypted plaintext :rtype: bytes """ return self._decryptor.finalize()
def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None): backend = _get_backend(backend) if len(wrapped_key) < 16: raise InvalidUnwrap("Must be at least 16 bytes") if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") if len(wrapped_key) == 16: # RFC 5649 - 4.2 - exactly two 64-bit blocks decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() b = decryptor.update(wrapped_key) assert decryptor.finalize() == b"" a = b[:8] data = b[8:] n = 1 else: r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] encrypted_aiv = r.pop(0) n = len(r) a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend) data = b"".join(r) # 1) Check that MSB(32,A) = A65959A6. # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let # MLI = LSB(32,A). # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of # the output data are zero. (mli, ) = struct.unpack(">I", a[4:]) b = (8 * n) - mli if (not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not 8 * (n - 1) < mli <= 8 * n or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b))): raise InvalidUnwrap() if b == 0: return data else: return data[:-b]
def decrypt(self, ciphertext, associated_data=b"authenticated but not encrypted payload"): # Construct a Cipher object, with the key, iv, and additionally the # GCM tag used for authenticating the message. iv, ciphertext = ciphertext[:self._block_size_bytes], ciphertext[ self._block_size_bytes:] tag, ciphertext = ciphertext[:self._block_size_bytes], ciphertext[ self._block_size_bytes:] decryptor = Cipher(algorithms.AES(self._key), modes.GCM(iv, tag), backend=default_backend()).decryptor() # We put associated_data back in or the tag will fail to verify # when we finalize the decryptor. decryptor.authenticate_additional_data(associated_data) # Decryption gets us the authenticated plaintext. # If the tag does not match an InvalidTag exception will be raised. return decryptor.update(ciphertext) + decryptor.finalize()
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
def decrypt(data: bytes, privkey: datatypes.PrivateKey, shared_mac_data: bytes = b'') -> bytes: """Decrypt data with ECIES method using the given private key 1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) ) 2) verify tag 3) decrypt ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R) [where R = r*G, and recipientPublic = recipientPrivate*G] """ if data[:1] != b'\x04': raise DecryptionError("wrong ecies header") # 1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) ) shared = data[1:1 + PUBKEY_LEN] try: key_material = ecdh_agree(privkey, keys.PublicKey(shared)) except _InvalidPublicKey as exc: raise DecryptionError( f"Failed to generate shared secret with pubkey {shared!r}: {exc}" ) from exc key = kdf(key_material) key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:] key_mac = sha256(key_mac).digest() tag = data[-KEY_LEN:] # 2) Verify tag expected_tag = hmac_sha256(key_mac, data[1 + PUBKEY_LEN:- KEY_LEN] + shared_mac_data) if not bytes_eq(expected_tag, tag): raise DecryptionError("Failed to verify tag") # 3) Decrypt algo = CIPHER(key_enc) blocksize = algo.block_size // 8 iv = data[1 + PUBKEY_LEN:1 + PUBKEY_LEN + blocksize] ciphertext = data[1 + PUBKEY_LEN + blocksize:- KEY_LEN] ctx = Cipher(algo, MODE(iv), default_backend()).decryptor() return ctx.update(ciphertext) + ctx.finalize()
def encrypt(plaintext, key): # AES len(decode(key))*8 CBC # only 128, 192 or 256 bits long supported. try: key = decode(key) except Error: return False # iv size = aes block size = 128 bits = 16 bytes iv = os.urandom(16) encryptor = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend).encryptor() plaintext = plaintext.encode('utf-8') if len(plaintext) % 16 != 0: plaintext += b' ' * (16 - len(plaintext) % 16) return encode(encryptor.update(plaintext) + encryptor.finalize(), iv)