def decrypt_header(self, data: bytes) -> bytes: if len(data) != HEADER_LEN + MAC_LEN: raise ValueError("Unexpected header length: {}".format(len(data))) header_ciphertext = data[:HEADER_LEN] header_mac = data[HEADER_LEN:] mac_secret = self.ingress_mac.digest()[:HEADER_LEN] aes = self.mac_enc(mac_secret)[:HEADER_LEN] self.ingress_mac.update(sxor(aes, header_ciphertext)) expected_header_mac = self.ingress_mac.digest()[:HEADER_LEN] if not bytes_eq(expected_header_mac, header_mac): raise DecryptionError( 'Invalid header mac: expected {}, got {}'.format( expected_header_mac, header_mac)) return self.aes_dec.update(header_ciphertext)
def aesgcm_decrypt(key: AES128Key, nonce: Nonce, cipher_text: bytes, authenticated_data: bytes ) -> bytes: validate_aes128_key(key) validate_nonce(nonce) aesgcm = AESGCM(key) try: plain_text = aesgcm.decrypt(nonce, cipher_text, authenticated_data) except InvalidTag as error: raise DecryptionError() from error else: return plain_text
def decrypt_body(self, data: bytes, body_size: int) -> bytes: read_size = roundup_16(body_size) if len(data) < read_size + MAC_LEN: raise ValueError('Insufficient body length; Got {}, wanted {}'.format( len(data), (read_size + MAC_LEN))) frame_ciphertext = data[:read_size] frame_mac = data[read_size:read_size + MAC_LEN] self.ingress_mac.update(frame_ciphertext) fmac_seed = self.ingress_mac.digest()[:MAC_LEN] self.ingress_mac.update(sxor(self.mac_enc(fmac_seed), fmac_seed)) expected_frame_mac = self.ingress_mac.digest()[:MAC_LEN] if not bytes_eq(expected_frame_mac, frame_mac): raise DecryptionError('Invalid frame mac') return self.aes_dec.update(frame_ciphertext)[:body_size]
def _decrypt_header(self, data: bytes) -> bytes: if len(data) != HEADER_LEN + MAC_LEN: raise ValueError( f"Unexpected header length: {len(data)}, expected {HEADER_LEN} + {MAC_LEN}" ) header_ciphertext = data[:HEADER_LEN] header_mac = data[HEADER_LEN:] mac_secret = self._ingress_mac.digest()[:HEADER_LEN] aes = self._mac_enc(mac_secret)[:HEADER_LEN] self._ingress_mac.update(sxor(aes, header_ciphertext)) expected_header_mac = self._ingress_mac.digest()[:HEADER_LEN] if not hmac.compare_digest(expected_header_mac, header_mac): raise DecryptionError( f'Invalid header mac: expected {expected_header_mac}, got {header_mac}' ) return self._aes_dec.update(header_ciphertext)
def _decrypt_body(self, data: bytes, body_size: int) -> bytes: read_size = roundup_16(body_size) if len(data) < read_size + MAC_LEN: raise ValueError( f'Insufficient body length; Got {len(data)}, wanted {read_size} + {MAC_LEN}' ) frame_ciphertext = data[:read_size] frame_mac = data[read_size:read_size + MAC_LEN] self._ingress_mac.update(frame_ciphertext) fmac_seed = self._ingress_mac.digest()[:MAC_LEN] self._ingress_mac.update(sxor(self._mac_enc(fmac_seed), fmac_seed)) expected_frame_mac = self._ingress_mac.digest()[:MAC_LEN] if not hmac.compare_digest(expected_frame_mac, frame_mac): raise DecryptionError( f'Invalid frame mac: expected {expected_frame_mac}, got {frame_mac}' ) return self._aes_dec.update(frame_ciphertext)[:body_size]
def decode_authentication( ciphertext: bytes, privkey: datatypes.PrivateKey ) -> Tuple[datatypes.PublicKey, bytes, datatypes.PublicKey]: """ Decrypts and decodes the ciphertext msg. Returns the initiator's ephemeral pubkey, nonce, and pubkey. """ if len(ciphertext) < ENCRYPTED_AUTH_MSG_LEN: raise DecryptionError("Auth msg too short: {}".format(len(ciphertext))) elif len(ciphertext) == ENCRYPTED_AUTH_MSG_LEN: sig, initiator_pubkey, initiator_nonce, _ = decode_auth_plain( ciphertext, privkey) else: sig, initiator_pubkey, initiator_nonce, _ = decode_auth_eip8( ciphertext, privkey) # recover initiator ephemeral pubkey from sig # S(ephemeral-privk, ecdh-shared-secret ^ nonce) shared_secret = ecies.ecdh_agree(privkey, initiator_pubkey) ephem_pubkey = sig.recover_public_key_from_msg_hash( sxor(shared_secret, initiator_nonce)) return ephem_pubkey, initiator_nonce, initiator_pubkey