def test_CMAC_verify(self): # test CMAC verification function key = Fernet.generate_key() fernet = Fernet(key) # test against the cryptography.io library APIs for i in range(20): M = os.urandom(i) K = os.urandom(16) # use library API generation c = cmac.CMAC(algorithms.AES(K), backend=default_backend()) c.update(M) lib_cmac = c.finalize() # verify a library generated cmac assert fernet._AES_CMAC_verify(K, M, len(M), lib_cmac) # verify against our own API cmac_ = fernet._AES_CMAC_generate(K, M, len(M)) assert fernet._AES_CMAC_verify(K, M, len(M), cmac_) # # library verify our generated cmac c = cmac.CMAC(algorithms.AES(K), backend=default_backend()) c.update(M) try: c.verify(cmac_) except Exception: raise Exception
def test_AuthenticationCorrectness(self): signing_key = self.fernet._signing_key data = byteblock(0) auth = cmac.CMAC(ciphers.algorithms.AES(signing_key), backend=default_backend()) auth.update(data) hazmat_tag = auth.finalize() fernet_tag = self.fernet._cmac(data) assert hazmat_tag == fernet_tag for l in xrange(1, 207): data = os.urandom(l) auth = cmac.CMAC(ciphers.algorithms.AES(signing_key), backend=default_backend()) auth.update(data) hazmat_tag = auth.finalize() fernet_tag = self.fernet._cmac(data) assert hazmat_tag == fernet_tag
def derive_session_keys(self): mac = cmac.CMAC(AES(self.KDK), OPENSSL_BACKEND) mac.update(b'\x01MK\x00\x80\x00') self.MK = mac.finalize() mac = cmac.CMAC(AES(self.KDK), OPENSSL_BACKEND) mac.update(b'\x01SK\x00\x80\x00') self.SK = mac.finalize()
def test_cmac(self): backend = MultiBackend([DummyCMACBackend([algorithms.AES])]) fake_key = b"\x00" * 16 assert backend.cmac_algorithm_supported( algorithms.AES(fake_key)) is True cmac.CMAC(algorithms.AES(fake_key), backend) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): cmac.CMAC(algorithms.TripleDES(fake_key), backend)
def derive_key(shared_key, label): shared_key_le = shared_key[::-1] key_0_str = "00000000000000000000000000000000".decode("hex") c1 = cmac.CMAC(algorithms.AES(key_0_str), backend=default_backend()) c1.update(shared_key_le) cmac_key0 = str(c1.finalize()) derive_key_str = ("01" + label.encode("hex") + "008000").decode("hex") c2 = cmac.CMAC(algorithms.AES(cmac_key0), backend=default_backend()) c2.update(derive_key_str) derived_key = c2.finalize() return derived_key
def final_handshake(self, url_base, auth_bytes): maccer = cmac.CMAC(AES(self.SK), OPENSSL_BACKEND) maccer.update(auth_bytes) mac = maccer.finalize() iv = bytearray(12) # assemble the json msg4 = {} msg4['iv'] = base64.b64encode(iv).decode('utf-8') msg4['payload'] = base64.b64encode(auth_bytes).decode('utf-8') msg4['mac'] = base64.b64encode(mac).decode('utf-8') jmsg4 = json.dumps(msg4) # send the message s_cookie = {'Cookie': 'session-id=' + self.SESSION_ID} req = requests.post(url_base + '/attestation/2', headers=s_cookie, data=jmsg4) if req.status_code != 200: error_msg = 'Status code: ' + str( req.status_code) + ': ' + req.json()['error'] raise AttestationException(error_msg)
def _mac(self, key, msg, update_chain=True): c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(self._mac_chain + msg) mac = c.finalize() if update_chain: self._mac_chain = mac return mac[:8]
def __init__(self, key, nonce, mac_len=16): self._mac_len = mac_len self._omac = [cmac.CMAC(algo.AES(key), defb()) for i in range(3)] for i in range(3): self._omac[i].update( bytes(1) * (algo.AES.block_size // 8 - 1) + struct.pack("B", i) # noqa: W503 ) self._omac[0].update(nonce) self._auth = _AuthWrapper(self._omac[1]) # create a cache since cryptography allows us to calculate tag # only once... why... self._omac_cache = [] self._omac_cache.append(self._omac[0].finalize()) self._cipher = CrCipher( algo.AES(key), modes.CTR(self._omac_cache[0]), defb(), ) self.__ctx = None self._updated = False self.__tag = None
def _calculate_mac(key: bytes, chain: bytes, message: bytes) -> Tuple[bytes, bytes]: c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(chain) c.update(message) chain = c.finalize() return chain, chain[:8]
def test_DecryptionCorrectness(self): encryption_key = self.fernet._encryption_key signing_key = self.fernet._signing_key iv = os.urandom(16) ptx = "this is a super secret message" timestamp = struct.pack(">Q", int(time.time())) cipher = ciphers.Cipher(ciphers.algorithms.AES(encryption_key), ciphers.modes.CTR(iv), self._backend) encryptor = cipher.encryptor() ctx = encryptor.update(ptx) + encryptor.finalize() auth = cmac.CMAC(ciphers.algorithms.AES(signing_key), backend=default_backend()) auth.update(b"\x91" + timestamp + iv + ctx) mac = auth.finalize() # Assemble a ciphertext using token created by `cryptography`. Ensure Fermet # 0x91 can decrypt the ciphertext correctly. mocked_result = base64.urlsafe_b64encode(b"\x91" + timestamp + iv + ctx + mac) fernet_result = self.fernet.encrypt(ptx, iv) assert mocked_result == fernet_result assert self.fernet.decrypt(mocked_result) == ptx
def calc_tag_wrapper(key, to_be_maced, algorithm): """ Wrapper function for the supported hmac in COSE :param key: key for computation of the hmac :param to_be_maced: byte string whose integrity need to be protected :param algorithm: chosen hmac, supports hmac with sha256, sha384 and sha512 :return: returns the digest calculated with the chosen hmac function """ try: primitive = cmacs[algorithm] c = cmac.CMAC(primitive(key), backend=default_backend()) c.update(to_be_maced) digest = c.finalize() if algorithm == 'AES-MAC-256/64': # truncate the result to the first 64 bits digest = digest[:8] except KeyError: try: primitive = hmacs[algorithm] h = hmac.HMAC(key, primitive(), backend=default_backend()) h.update(to_be_maced) digest = h.finalize() if algorithm == 'HS256/64': # truncate the result to the first 64 bits digest = digest[:8] except KeyError as e: raise CoseUnsupportedMAC( "This cipher is not supported by the COSE specification: {}". format(e)) return digest
def cmac_verify(message: bytes, key: bytes, signature: bytes) -> bool: c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(message) try: c.verify(signature) return True except InvalidSignature: return False
def derive_SMK(self): # once the shared secret has been established, the KDK is: # AES-128 CMAC of shared secret with key 0x00..00 mac = cmac.CMAC( AES(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ), OPENSSL_BACKEND) mac.update(self.shared_secret) self.KDK = mac.finalize() # derive the SMK using KDK as a key over text b'\x01SMK\x00\x80\x00' mac = cmac.CMAC(AES(self.KDK), OPENSSL_BACKEND) mac.update(b'\x01SMK\x00\x80\x00') self.SMK = mac.finalize() # derive VK as the CMAC using KDK of b'\x01VK\x00\x80\x00' mac = cmac.CMAC(AES(self.KDK), OPENSSL_BACKEND) mac.update(b'\x01VK\x00\x80\x00') self.VK = mac.finalize()
def _derive(key: bytes, t: int, context: bytes, L: int = 0x80) -> bytes: # this only supports aes128 if L != 0x80 and L != 0x40: raise ValueError("L must be 0x40 or 0x80") i = b"\0" * 11 + struct.pack("!BBHB", t, 0, L, 1) + context c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(i) return c.finalize()[:L // 8]
def cal_cmac_aes(key: bytes, message: bytes) -> bytes: """ Calculate CMAC with AES-128 :param bytes key: 128-bit length key :param bytes message: message :return: CMAC code """ c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(message) return c.finalize()
def _cmac_aes_digest(key, msg): # type: (bytes, bytes) -> bytes from cryptography.hazmat.primitives import cmac from cryptography.hazmat.primitives.ciphers import algorithms from cryptography.hazmat.backends import default_backend backend = default_backend() c = cmac.CMAC(algorithms.AES(key), backend=backend) c.update(bytes(msg)) return c.finalize()
def _derive(key, t, context, L=0x80): # this only supports aes128 if L != 0x80 and L != 0x40: raise ValueError('L must be 0x40 or 0x80') i = b'\0' * 11 + struct.pack('!BBHB', t, 0, L, 1) + context c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(i) return c.finalize()[:L // 8]
def cal_cmac_algorithm(algorithm: BlockCipherAlgorithm, message: bytes) -> bytes: """ Calculate CMAC with a given block cipher algorithm :param BlockCipherAlgorithm algorithm: the algorithm to use :param bytes message: message :return: CMAC code """ c = cmac.CMAC(algorithm, backend=default_backend()) c.update(message) return c.finalize()
def main(): message = b"message to authenticate" aes_key = os.urandom(32) c = cmac.CMAC(algorithms.AES(aes_key), backend=default_backend()) c.update(message) cmacRes = c.finalize() # Dump hex value dump_hex(message, 'message: ', preFormat="C") dump_hex(aes_key, 'aes_key: ', preFormat="C") dump_hex(cmacRes, 'cmac: ', preFormat="C")
def process_msg1(msg1): try: global symmetric_key x = bytes_to_long(msg1[:32][::-1]) y = bytes_to_long(msg1[32:64][::-1]) gid = msg1[64:68][::-1] context = msg1[-4:] sp_public_key_le = msg1[:64] sp_public_key = ec.EllipticCurvePublicNumbers( x, y, ec.SECP256R1()).public_key(default_backend()) shared_key = private_key.exchange(ec.ECDH(), sp_public_key) derived_key_smk = derive_key(shared_key, "SMK") symmetric_key = derive_key(shared_key, "SK") public_numbers = public_key.public_numbers() public_key_le = long_to_bytes(public_numbers.x)[::-1] + long_to_bytes( public_numbers.y)[::-1] spid = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".decode("hex") quote_type = "0000".decode("hex")[::-1] kdf_id = "0001".decode("hex")[::-1] public_keys_concat = public_key_le + sp_public_key_le sign_pk_concat_encoded = private_key.sign(public_keys_concat, ec.ECDSA(hashes.SHA256())) sign_pk_concat_decoded = utils.decode_dss_signature( sign_pk_concat_encoded) sign_pk_concat = long_to_bytes( sign_pk_concat_decoded[0])[::-1] + long_to_bytes( sign_pk_concat_decoded[1])[::-1] c = cmac.CMAC(algorithms.AES(derived_key_smk), backend=default_backend()) c.update(public_key_le + spid + quote_type + kdf_id + sign_pk_concat) mac = c.finalize() sig_rl_size = format(0, "08x").decode("hex") msg2 = public_key_le + spid + quote_type + kdf_id + sign_pk_concat + mac + sig_rl_size return msg2 except Exception as e: print e return process_msg1(msg1)
def process_msg1(msg1): global symmetric_key x = bytes_to_long(msg1[:32][::-1]) y = bytes_to_long(msg1[32:64][::-1]) gid = msg1[64:68][::-1] context = msg1[-4:] sp_public_key_le = msg1[:64] sp_public_key = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()).public_key(default_backend()) shared_key = private_key.exchange(ec.ECDH(), sp_public_key) derived_key_smk = derive_key(shared_key, "SMK") symmetric_key = derive_key(shared_key, "SK") public_numbers = public_key.public_numbers() public_key_le = long_to_bytes(public_numbers.x)[::-1] + long_to_bytes(public_numbers.y)[::-1] spid = "cb831ce194a3733369575ae6e6e9dbee".decode("hex") quote_type = "0000".decode("hex")[::-1] kdf_id = "0001".decode("hex")[::-1] public_keys_concat = public_key_le + sp_public_key_le sign_pk_concat_encoded = private_key.sign(public_keys_concat, ec.ECDSA(hashes.SHA256())) sign_pk_concat_decoded = utils.decode_dss_signature(sign_pk_concat_encoded) sign_pk_concat = long_to_bytes(sign_pk_concat_decoded[0])[::-1] + long_to_bytes(sign_pk_concat_decoded[1])[::-1] c = cmac.CMAC(algorithms.AES(derived_key_smk), backend=default_backend()) c.update(public_key_le + spid + quote_type + kdf_id + sign_pk_concat) mac = c.finalize() response = requests.get( "https://test-as.sgx.trustedservices.intel.com:443/attestation/sgx/v2/sigrl/" + gid.encode("hex"), cert='client.pem') assert response.status_code == 200 sig_rl = base64.b64decode(response.content) sig_rl_size = format(len(sig_rl), "08x").decode("hex") msg2 = public_key_le + spid + quote_type + kdf_id + sign_pk_concat + mac + sig_rl_size + \ sig_rl + context return msg2
def calculate_mac(current, prev): if prev != None: prev_data = prev[HopField.RANGE_SKIP_FLAGS:HopField.RANGE_END] else: prev_data = b'\0' * (HopField.RANGE_END - HopField.RANGE_SKIP_FLAGS) data = ( struct.pack('!I', self.timestamp) + struct.pack( 'B', current[HopField.FLAGS] & HopField.IMMUTABLE_FLAGS) + current[HopField.RANGE_SKIP_FLAGS:HopField.RANGE_BEFORE_MAC] + prev_data) # print('prev_data: ', len(prev_data), prev_data.encode('hex')) # print('data: ', len(data), data.encode('hex')) assert len(data) == 128 // 8 c = cmac.CMAC(algorithms.AES(HF_MAC_KEY), backend=default_backend()) c.update(data) return c.finalize()
def wrap(master_key, target_key): """ Wraps "target_key" with "master_key" in the simplified SIV mode and returns the wrapped key. :param master_key: The AES key used for wrapping; must be 128, 192 or 256 bits. :param target_key: The key to be wrapped; must be at least one AES block long (128 bits). """ assert len(target_key) >= 16 keys = KeyWrap._expand_key(master_key, 2) cm = cmac.CMAC(algorithms.AES(keys[0]), backend=default_backend()) cm.update(target_key) iv = cm.finalize() assert len(iv) == 16 enc = Cipher(algorithms.AES(keys[1]), modes.CTR(iv), backend=default_backend()).encryptor() ct = enc.update(target_key) + enc.finalize() return iv + ct
def test_CMAC_generate(self): # test AES_CMAC generation key = Fernet.generate_key() fernet = Fernet(key) # test against the cryptographi.io library APIs for i in range(20): M = os.urandom(i) K = os.urandom(16) # use library's API to generate CMAC c = cmac.CMAC(algorithms.AES(K), backend=default_backend()) c.update(M) lib_cmac = c.finalize() # use our function to generate CMAC cmac_ = fernet._AES_CMAC_generate(K, M, len(M)) # verify library CMAC vs our CMAC assert cmac_ == lib_cmac
def unwrap(master_key, wrapped_key): """ Unwraps "wrapped_key" with "master_key" in the simplified SIV mode. If the wrapping was properly authenticated, it returns the target key; otherwise, it raises an "InvalidKey" exception. :param master_key: The AES key used for unwrapping; must be 128, 192 or 256 bits. :param wrapped_key: The ciphertext to be unwrapped; must be at least one AES block long (128 bits). """ assert len(wrapped_key) >= 16 keys = KeyWrap._expand_key(master_key, 2) iv = wrapped_key[0:16] dec = Cipher(algorithms.AES(keys[1]), modes.CTR(iv), backend=default_backend()).decryptor() target_key = dec.update(wrapped_key[16:]) + dec.finalize() assert len(wrapped_key) == len(target_key) + 16 cm = cmac.CMAC(algorithms.AES(keys[0]), backend=default_backend()) cm.update(target_key) ivp = cm.finalize() if iv != ivp: pass return target_key
encryptor = cipher.encryptor() decryptor = cipher.decryptor() cipher_text = encryptor.update(data.encode('latin-1')) cipher_size = len(cipher_text) cipher_dec_text = decryptor.update(cipher_text) if (data.encode('latin-1') == cipher_dec_text): print('CIPHER OK') else: print('CIPHER ERROR, src_size: ' + str(len(data)) + ' decrypt_size :' + str(len(cipher_dec_text))) # Get signature signer = cmac.CMAC(algorithms.AES(aes_cmac_key), backend) if args.force_ivnbinc: cipher_text_for_signature = cipher_text.decode( 'latin') + aes_cbc_iv.decode('latin') + ( NULL * (DECRYPT_PKT_SIZE - 2)) + binascii.unhexlify( '{:04x}'.format(num_dec_pkts - 1)).decode('latin') else: cipher_text_for_signature = cipher_text.decode('latin-1') signer.update(bytes(cipher_text_for_signature, 'latin-1')) signature = signer.finalize() sf = open(FOLDER_SEC + 'signature.txt', "w") line = 'Signature: ' + str(binascii.hexlify(signature)) sf.write(line) sf.close() print('See signature in signature.txt file')
def _calculate_mac(key, chain, message): c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(chain) c.update(message) chain = c.finalize() return chain, chain[:8]
def CMAC(key: bytes, data: bytes): c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) c.update(data) return c.finalize()
iv = os.urandom(16) cipher = Cipher(algorithms.AES(rawkey), modes.CBC(iv), backend=_default_backend) def test_aes(s): encryptor = cipher.encryptor() padder = padding.PKCS7(128).padder() s = padder.update(s) + padder.finalize() r = encryptor.update(s) + encryptor.finalize() cipher_gcm = Cipher(algorithms.AES(rawkey), modes.GCM(iv), backend=_default_backend) aes_cmac = cmac.CMAC(algorithms.AES(rawkey), backend=_default_backend) assert len(rawkey) == 32 def test_aes_cmac(s): c = aes_cmac.copy() c.update(s) d = c.finalize() assert len(d) == 16 def test_aes_gcm(s): encryptor = cipher_gcm.encryptor() r = encryptor.update(s) + encryptor.finalize()
def _prf(self, _: bytes) -> cmac.CMAC: assert self._cipher is not None return cmac.CMAC(self._cipher)