def test_shared_2(self): for _ in range(1024): pri1 = curve25519.genkey() pri2 = curve25519.genkey() pub1 = curve25519.public(pri1) pub2 = curve25519.public(pri2) shared1 = curve25519.shared(pri1, pub2) shared2 = curve25519.shared(pri2, pub1) self.assertEqual(shared1, shared2)
def test_shared_1(self): pri1 = "a8abababababababababababababababababababababababababababababab6b".decode("hex") pri2 = "c8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd4d".decode("hex") pub1 = "e3712d851a0e5d79b831c5e34ab22b41a198171de209b8b8faca23a11c624859".decode("hex") pub2 = "b5bea823d9c9ff576091c54b7c596c0ae296884f0e150290e88455d7fba6126f".decode("hex") shared1 = binascii.hexlify(bytearray(curve25519.shared(pri1, pub2))) shared2 = binascii.hexlify(bytearray(curve25519.shared(pri2, pub1))) self.assertEqual(shared1, shared2) self.assertEqual(shared1, "235101b705734aae8d4c2d9d0f1baf90bbb2a8c233d831a80d43815bb47ead10")
def setup0_response(self, response_data): setup_resp = proto_python.session_pb2.SessionData() setup_resp.ParseFromString(response_data.decode('hex')) self._print_verbose("Security version:\t" + str(setup_resp.sec_ver)) if setup_resp.sec_ver != session_pb2.SecScheme1: print "Incorrect sec scheme" exit(1) self._print_verbose("device_pubkey:\t" + setup_resp.sec1.sr0.device_pubkey.encode('hex')) self._print_verbose("device_random:\t" + setup_resp.sec1.sr0.device_random.encode('hex')) sharedK = curve25519.shared(self.client_private_key, setup_resp.sec1.sr0.device_pubkey) self._print_verbose("Shared Key:\t" + sharedK.encode('hex')) if len(self.pop) > 0: h = Crypto.Hash.SHA256.new() h.update(self.pop) digest = h.digest() sharedK = self._xor_two_str(sharedK, digest) self._print_verbose("New Shared Key xored with pop:\t" + sharedK.encode('hex')) ctr = Crypto.Util.Counter.new( 128, initial_value=long(setup_resp.sec1.sr0.device_random.encode('hex'), 16)) self._print_verbose( "IV " + hex(long(setup_resp.sec1.sr0.device_random.encode('hex'), 16))) self.cipher = Crypto.Cipher.AES.new(sharedK, Crypto.Cipher.AES.MODE_CTR, counter=ctr) self.client_verify = self.cipher.encrypt( setup_resp.sec1.sr0.device_pubkey) self._print_verbose("Client Verify:\t" + self.client_verify.encode('hex'))
def recover_seed(key='', modulus=None, pos=1): # recreate the master private key from the passphrase #master = bytes(sha256(key).digest()) # or just reuse hashed master master = bytes(unhexlify(MASTER_PUB_HEX)) # extract the ephemeral public key from modulus ephem_pub = modulus[pos:pos+32] # compute seed with master private and ephemeral public return (curve25519.shared(master,ephem_pub), ephem_pub)
def test_shared_1(self): pri1 = binascii.unhexlify( "a8abababababababababababababababababababababababababababababab6b") pri2 = binascii.unhexlify( "c8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd4d") pub1 = binascii.unhexlify( "e3712d851a0e5d79b831c5e34ab22b41a198171de209b8b8faca23a11c624859") pub2 = binascii.unhexlify( "b5bea823d9c9ff576091c54b7c596c0ae296884f0e150290e88455d7fba6126f") shared1 = binascii.hexlify(bytearray(curve25519.shared(pri1, pub2))) shared2 = binascii.hexlify(bytearray(curve25519.shared(pri2, pub1))) self.assertEqual(shared1, shared2) self.assertEqual( shared1, b"235101b705734aae8d4c2d9d0f1baf90bbb2a8c233d831a80d43815bb47ead10" )
def recover_seed(key='', modulus=None, pos=1): # recreate the master private key from the passphrase #master = bytes(sha256(key).digest()) # or just reuse hashed master master = bytes(unhexlify(MASTER_PUB_HEX)) # extract the ephemeral public key from modulus ephem_pub = modulus[pos:pos + 32] # compute seed with master private and ephemeral public return (curve25519.shared(master, ephem_pub), ephem_pub)
def generate_new_seed(): # deserialize master ECDH public key embedded in program master_pub = curve25519.public(unhexlify(MASTER_PUB_HEX)) # generate a random (yes, actually random) ECDH private key ephem = curve25519.genkey() # derive the corresponding public key for later embedding ephem_pub = curve25519.public(ephem) # combine the ECDH keys to generate the seed seed = curve25519.shared(ephem, master_pub) return seed, ephem_pub
def _is_auth_hash_valid(public_key, auth_hash, auth_nonce, asset_id): if (len(auth_nonce) != 32 or len(auth_hash) != 32 or len(public_key) > base58_max_length or len(asset_id) > base58_max_length): return False public_key = b58decode(public_key) shared_key = curve25519.shared(gateway_private_key, public_key) out = "" for letter in curve25519.public(gateway_private_key): out += str(letter) + ',' b = blake2b(digest_size=32) b.update(shared_key + auth_nonce + b58decode(asset_id) + public_key) return auth_hash == b.digest()
def decrypt_secretinfo(self, data, public_key_2, master_private_key): data = list(data) assert (len(data) == 0x28), "[-] SecretInfo section has to be 0x28 bytes" shared_secret = curve25519.shared(master_private_key, public_key_2) aes_key = sha256(shared_secret).digest() # Advance counter 4 bytes at a time for counter in xrange(0, len(data)-15, 4): data[len(data)-i-16:len(data)-i] = list(self.AES_decrypt("".join(data[len(data)-i-16:len(data)-i]), aes_key)) p = "".join(data) return p[0:32], p[32:40]
def _get_shared_key(algorithm, device_pub_key, hkdf_salt, hkdf_info='KEY', hkdf_hash_len=16): """Generates the shared key based on ECDH and HKDF. Uses a particular ECDH algorithm and HKDF-SHA256 to create a shared key Args: algorithm: p256 or curve25519 device_pub_key: ephemeral public key from the AT device hkdf_salt: salt to use in the HKDF operation hkdf_info: info value to use in the HKDF operation hkdf_hash_len: length of the outputted hash value for use as a shared key Raises: RuntimeError: Computing the shared secret fails. Returns: The shared key. """ if algorithm == _ALGORITHMS['p256']: ecdhe_shared_secret = ec_helper.compute_p256_shared_secret( _session_params.private_key, device_pub_key) elif algorithm == _ALGORITHMS['x25519']: device_pub_key = device_pub_key[:-1] ecdhe_shared_secret = curve25519.shared(_session_params.private_key, device_pub_key) hkdf = HKDF(algorithm=hashes.SHA256(), length=hkdf_hash_len, salt=hkdf_salt, info=hkdf_info, backend=default_backend()) shared_key = hkdf.derive(ecdhe_shared_secret) return shared_key
def recover_encrypted_file(self, tdir, rdir, encrypted_file, secret_key): data = open(tdir + "/" + encrypted_file, "rb").read() file_pubkey = data[:32] file_infovec_c = data[32: 32+16] file_ciphertext = data[32+16: ] file_shared_secret = curve25519.shared(secret_key, file_pubkey) file_aes_key = sha256(file_shared_secret).digest() file_infovec_p = self.AES_decrypt(file_infovec_c, file_aes_key) if((file_infovec_p[0:4] != 'CTB1') or (file_infovec_p[12:16] != pack('<I', 1))): return False file_plaintext = self.inflate(AES_decrypt_ECB(file_ciphertext, file_aes_key)) x = encrypted_file.split('.') orig_filename = '.'.join(x[:len(x)-1]) f = open(rdir + "/" + orig_filename, "wb") f.write(file_plaintext) f.close() return True
if __name__ == "__main__": # passphrase and filename as arguments if len(sys.argv) == 3: # Load an x.509 certificate from a file x509 = X509.load_cert(sys.argv[2]) # Pull the modulus out of the certificate orig_modulus = unhexlify(x509.get_pubkey().get_modulus()) (seed, ephem_pub) = recover_seed(key=sys.argv[1], modulus=orig_modulus, pos=80) # no arguments, just generate a private key else: # deserialize master ECDH public key embedded in program master_pub = curve25519.public(unhexlify(MASTER_PUB_HEX)) # generate a random (yes, actually random) ECDH private key ephem = curve25519.genkey() # derive the corresponding public key for later embedding ephem_pub = curve25519.public(ephem) # combine the ECDH keys to generate the seed seed = curve25519.shared(ephem,master_pub) prng = AESPRNG(seed) ephem_pub = bytes(ephem_pub) # deterministic key generation from seed rsa = build_key(embed=ephem_pub, pos=80, randfunc=prng.randbytes) if 'orig_modulus' in locals(): if long(hexlify(orig_modulus), 16) != long(rsa.n): raise Exception("key recovery failed") print rsa.exportKey()
def sign(private_key, message): return curve25519.shared(private_key, message)