def test_constantStrEqual_zero_len(self): str1 = '' str2 = 'test' try: import hmac.compare_digest with mock.patch('hmac.compare_digest', side_effect=ImportError()) as _: self.assertFalse(util.constantStrEqual(str1, str2)) except ImportError: self.assertFalse(util.constantStrEqual(str1, str2))
def deriveRelayCrypto(self, cell): '''Derive shared key material for this ntor handshake; create and return actual cipher and hash instances inside a RelayCrypto object. .. note:: See tor-spec Section 5.1.4, 5.2.2 for more details. :param cell cell: Created2 cell or Extended2 cell used to derive shared keys :returns: **oppy.crypto.relaycrypto.RelayCrypto** object initialized with the derived key material. ''' self.is_bad = False hdata = cell.hdata relay_pubkey = cell.hdata[: CURVE25519_PUBKEY_LEN] AUTH = hdata[CURVE25519_PUBKEY_LEN: CURVE25519_PUBKEY_LEN + DIGEST_LEN] secret_input = self._buildSecretInput(relay_pubkey) verify = util.makeHMACSHA256(msg=secret_input, key=T_VERIFY) auth_input = self._buildAuthInput(verify, relay_pubkey) auth_input = util.makeHMACSHA256(msg=auth_input, key=T_MAC) self.is_bad |= util.constantStrEqual(AUTH, auth_input) ret = self._makeRelayCrypto(secret_input) # don't fail until the very end to avoid leaking timing information if self.is_bad: raise KeyDerivationFailed() return ret
def deriveRelayCrypto(self, cell): '''Derive shared key material for this ntor handshake; create and return actual cipher and hash instances inside a RelayCrypto object. .. note:: See tor-spec Section 5.1.4, 5.2.2 for more details. :param cell cell: Created2 cell or Extended2 cell used to derive shared keys :returns: **oppy.crypto.relaycrypto.RelayCrypto** object initialized with the derived key material. ''' self.is_bad = False hdata = cell.hdata relay_pubkey = cell.hdata[:CURVE25519_PUBKEY_LEN] AUTH = hdata[CURVE25519_PUBKEY_LEN:CURVE25519_PUBKEY_LEN + DIGEST_LEN] secret_input = self._buildSecretInput(relay_pubkey) verify = util.makeHMACSHA256(msg=secret_input, key=T_VERIFY) auth_input = self._buildAuthInput(verify, relay_pubkey) auth_input = util.makeHMACSHA256(msg=auth_input, key=T_MAC) self.is_bad |= util.constantStrEqual(AUTH, auth_input) ret = self._makeRelayCrypto(secret_input) # don't fail until the very end to avoid leaking timing information if self.is_bad: raise KeyDerivationFailed() return ret
def test_constantStrEqual_have_compare_digest(self): try: import hmac.compare_digest except ImportError: return str1 = 'test1' str2 = 'test2' with mock.patch('hmac.compare_digest', return_value='ret') as mock_cd: ret = util.constantStrEqual(str1, str2) mock_cd.assert_called_once_with(str1, str2) self.assertEqual(ret, 'ret')
def _ASN1KeysEqual(key1, key2): try: key1_ASN1 = SSLCrypto.dump_privatekey(SSLCrypto.FILETYPE_ASN1, key1) key2_ASN1 = SSLCrypto.dump_privatekey(SSLCrypto.FILETYPE_ASN1, key2) # no need for constant time comparison here because both keys tested # are sent to us by the relay. doing it anyway in case i accidentally # use this function somewhere else in the future return crypto.constantStrEqual(key1_ASN1, key2_ASN1) except Exception as e: msg = "Failed to parse ASN1 key: {}.".format(e) logging.debug(msg) return False