def __init__(self, logger): self.IK = X25519PrivateKey.generate() self.SPK = X25519PrivateKey.generate() self.OPK = X25519PrivateKey.generate() self.peer_keys = defaultdict(dict) self.sessions = defaultdict(lambda: SessionState.new()) self.logger = logger
def load_bob_keys() -> (X25519PrivateKey, X25519PrivateKey, X25519PrivateKey): # If existing, load the saved keys for bob. # If they do not already exists, generate new keys and save them. # Generate OPKb once and do not save it. # Returns 3 keys: # IK: X25519PrivateKey # SPKb: X25519PrivateKey # OPKb: X25519PrivateKey OPKb = X25519PrivateKey.generate() try: with open(path_keys_bob, 'rb') as f: lines = f.read() assert (len(lines) == 2 * key_length) IK_bytes = lines[:key_length] SPKb_bytes = lines[key_length:] IK = deserialize_private_key(IK_bytes) SPKb = deserialize_private_key(SPKb_bytes) print("Loaded saved keys.") except FileNotFoundError: print("No keys found. Creating new keys...") IK = X25519PrivateKey.generate() SPKb = X25519PrivateKey.generate() with open(path_keys_bob, 'wb') as f: for key in [IK, SPKb]: f.write(serialize_private_key(key)) print("Keys saved.") pass return (IK, SPKb, OPKb)
def is_available(cls): try: X25519PrivateKey.generate() except UnsupportedAlgorithm: return False else: return True
def test_x25519_unsupported(backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): X25519PublicKey.from_public_bytes(b"0" * 32) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): X25519PrivateKey.from_private_bytes(b"0" * 32) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM): X25519PrivateKey.generate()
def __init__(self): self.IdentityPri = X25519PrivateKey.generate() self.IdentityPub = self.IdentityPri.public_key() self.SignedPri = X25519PrivateKey.generate() self.SignedPub = self.SignedPri.public_key() self.OneTimePri = X25519PrivateKey.generate() self.OneTimePub = self.OneTimePri.public_key() self.EphemeralPri = X25519PrivateKey.generate() self.EphemeralPub = self.EphemeralPri.public_key()
def __init__ (self): # generate pre-key bundle # ideally, this is published to a server self.IK = X25519PrivateKey.generate () # identity key self.SPK = X25519PrivateKey.generate () # signed pre-key self.OPK = X25519PrivateKey.generate () # one time key # initiator - boolean to determine whether this client is initating a connection # helps with x3dh, i think ... self.init = False
def __init__(self, name): # generate Bob's keys self.__name = name # Identity self.__IPK = X25519PrivateKey.generate() # Pre signed key self.__SPK = X25519PrivateKey.generate() # One time pre key self.__OPK = X25519PrivateKey.generate() # Ephemeral key self.__EFK = X25519PrivateKey.generate()
def isCryptographyAdvanced(): """ Check if the cryptography library is present, and if it supports X25519, ChaCha20Poly1305 and such (v2.0 or later). """ try: from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey # noqa: E501 X25519PrivateKey.generate() except Exception: return False else: return True
def get_shared_secret(client_private_key, server_public_key, cryptographic_group): # x25519 (x00 x1d) if cryptographic_group == b"\x00\x1d": private_key = X25519PrivateKey.from_private_bytes( client_private_key) public_key = X25519PublicKey.from_public_bytes(server_public_key) return private_key.exchange(public_key) # x448 (x00 x1e) elif cryptographic_group == b"\x00\x1e": private_key = X448PrivateKey.from_private_bytes(client_private_key) public_key = X448PublicKey.from_public_bytes(server_public_key) return private_key.exchange(public_key) # secp256r1 (x00 x17) elif cryptographic_group == b"\x00\x17": return Crypto_Helper.get_shared_secret_secpr1( client_private_key, server_public_key, SECP256R1) # secp384r1 (x00 x18) elif cryptographic_group == b"\x00\x18": return Crypto_Helper.get_shared_secret_secpr1( client_private_key, server_public_key, SECP384R1) # secp521r1 (x00 x19) elif cryptographic_group == b"\x00\x19": return Crypto_Helper.get_shared_secret_secpr1( client_private_key, server_public_key, SECP521R1)
def accept(self): """Accept an incoming connection & initialize the encryption layer for that client Returns ------- returns (socket, addr) of the client """ clt, addr = super().accept() # Generate a private key server_key = X25519PrivateKey.generate() pubkey = server_key.public_key().public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw) data = clt.recv(32) # Receive client public Key clt.sendall(pubkey) # send public key to client public_key = X25519PublicKey.from_public_bytes(data) # get Shared key shared_key = server_key.exchange(public_key) shared_key = HKDF(algorithm=hashes.SHA256(), length=48, salt=None, info=b'handshake data', backend=default_backend()).derive(shared_key) encrypted_socket = wrap_socket(clt, False, handshaked=True) encrypted_socket.cipher = Cipher(algorithms.AES(shared_key[0:32]), modes.CBC(shared_key[32:]), backend=default_backend()) return encrypted_socket, addr
def _handshake(self): """Open a socket to address, port and initialize the encryption layer by exchanging a key using X25519. The key is used as an AES key throughout the communication. Returns ------- return itself """ private_key = X25519PrivateKey.generate() pubkey = private_key.public_key().public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw) # send client public key super().send(pubkey) # receive server public Key data = super().recv(32) # from public key get shared_key server_key = X25519PublicKey.from_public_bytes(data) shared_key = private_key.exchange(server_key) key = HKDF(algorithm=hashes.SHA256(), length=48, salt=None, info=b'handshake data', backend=default_backend()).derive(shared_key) self.cipher = Cipher(algorithms.AES(key[0:32]), modes.CBC(key[32:]), backend=default_backend()) return self
def modify(packet): pkt = dpkt.ip6.IP6(packet.get_payload()) if is_icmp_neighbour_message(pkt): packet.accept() return global client_id aes_key_text = pkt.data[:256] aes_key_text = asymmetrickeys.decrypt(aes_key_text) nonce = struct.unpack(">I", pkt.data[256:260])[0] public_ecdhe_key = pkt.data[260:292] ci = struct.unpack(">I", pkt.data[292:296])[0] aes_key = AESGCM(aes_key_text) decrypted_block = bytes( aes_key.decrypt(bytes(nonce), pkt.data[296:-288], '')) ip_b = decrypted_block[:16] # --- Header 2 header_2 = pkt.data[-288:] ecdhe = X25519PrivateKey.generate() shared_key = ecdhe.exchange( X25519PublicKey.from_public_bytes(public_ecdhe_key)) derived_key = HKDF(algorithm=hashes.SHA512(), length=32, info=None, salt=None, backend=default_backend()).derive(shared_key) key = AESGCM(derived_key) nonce = random.randint(0, 4294967295) encrypted_header = key.encrypt(bytes(nonce), header_2, '') signature = sign(ecdhe.public_key().public_bytes(), asymmetrickeys) header_2 = ecdhe.public_key().public_bytes() + signature + struct.pack( ">I", nonce) + encrypted_header + struct.pack(">I", client_id) client_id = client_id + 1 # Finalize packet pkt.data = decrypted_block[16:] + header_2 pkt.plen = len(pkt.data) pkt.dst = ip_b sockfd.sendto(bytes(pkt), (socket.inet_ntop(socket.AF_INET6, ip_b), 0)) packet.drop()
def wg_derive_pubkey(privkey): privkey_data = base64.b64decode(privkey.encode("ascii")) x = X25519PrivateKey.from_private_bytes(privkey_data) p = x.public_key() pubkey_data = p.public_bytes(Encoding.Raw, PublicFormat.Raw) pubkey = base64.b64encode(pubkey_data) return pubkey.decode("ascii")
def encrypt(self, plaintext): """ Encrypts information for the identity. :param plaintext: The plaintext to be encrypted as *bytes*. :returns: Ciphertext token as *bytes*. :raises: *KeyError* if the instance does not hold a public key. """ if self.pub != None: ephemeral_key = X25519PrivateKey.generate() ephemeral_pub_bytes = ephemeral_key.public_key().public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) shared_key = ephemeral_key.exchange(self.pub) derived_key = derived_key = HKDF( algorithm=hashes.SHA256(), length=32, salt=self.get_salt(), info=self.get_context(), ).derive(shared_key) fernet = Fernet(base64.urlsafe_b64encode(derived_key)) ciphertext = base64.urlsafe_b64decode(fernet.encrypt(plaintext)) token = ephemeral_pub_bytes + ciphertext return token else: raise KeyError( "Encryption failed because identity does not hold a public key" )
def generate_key( algorithm: CoseAlgorithms, key_ops: KeyOps, curve_type: CoseEllipticCurves = CoseEllipticCurves.X25519 ) -> 'OKP': """ Generate a random OKP COSE key object. :param algorithm: Specify the CoseAlgorithm to use. :param key_ops: Specify the key operation (KeyOps). :param curve_type: Specify curve, must be X25519 or X448. """ if curve_type == CoseEllipticCurves.X25519: private_key = X25519PrivateKey.generate() elif curve_type == CoseEllipticCurves.X448: private_key = X448PrivateKey.generate() else: raise CoseIllegalCurve( f"curve must be of type {CoseEllipticCurves.X25519} or {CoseEllipticCurves.X448}" ) encoding = Encoding(serialization.Encoding.Raw) private_format = PrivateFormat(serialization.PrivateFormat.Raw) public_format = PublicFormat(serialization.PublicFormat.Raw) encryption = serialization.NoEncryption() return OKP(alg=CoseAlgorithms(algorithm), key_ops=KeyOps(key_ops), crv=CoseEllipticCurves(curve_type), x=private_key.public_key().public_bytes( encoding, public_format), d=private_key.private_bytes(encoding, private_format, encryption))
def __init__(self, test, src, port): super(VppWgInterface, self).__init__(test) self.port = port self.src = src self.private_key = X25519PrivateKey.generate() self.public_key = self.private_key.public_key()
def test_public_bytes_bad_args(self, backend): key = X25519PrivateKey.generate().public_key() with pytest.raises(ValueError): key.public_bytes( None, serialization.PublicFormat.Raw # type: ignore[arg-type] )
def register(cls, password: bytes): """ Generate a new account. :param password The password for encrypting the keys. :return a Registration. """ reg = cls() # gen signature keypair sign_object = Ed25519PrivateKey.generate() reg.sign_pub = sign_object.public_key().public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw) sign = sign_object.private_bytes(serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption()) reg.sign_sig = sign_object.sign(sign) # the private signature key's hash become the account's ID reg.identity = blake2b(sign).digest() # gen encryption keypair xchg_object = X25519PrivateKey.generate() reg.xchg_pub = xchg_object.public_key().public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw) xchg = xchg_object.private_bytes(serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption()) reg.xchg_sig = sign_object.sign(xchg) # encrypt the private keys reg.set_passwd(sign, xchg, password) return reg
def load_private_key(self, prv_bytes): """ Load a private key into the instance. :param prv_bytes: The private key as *bytes*. :returns: True if the key was loaded, otherwise False. """ try: self.prv_bytes = prv_bytes[:Identity.KEYSIZE // 8 // 2] self.prv = X25519PrivateKey.from_private_bytes(self.prv_bytes) self.sig_prv_bytes = prv_bytes[Identity.KEYSIZE // 8 // 2:] self.sig_prv = Ed25519PrivateKey.from_private_bytes( self.sig_prv_bytes) self.pub = self.prv.public_key() self.pub_bytes = self.pub.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) self.sig_pub = self.sig_prv.public_key() self.sig_pub_bytes = self.sig_pub.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) self.update_hashes() return True except Exception as e: raise e RNS.log("Failed to load identity key", RNS.LOG_ERROR) RNS.log("The contained exception was: " + str(e), RNS.LOG_ERROR) return False
def keygen_public(key_size, alg, hash_alg, curve): if alg == 'rsa': key_pair = RSA.generate(key_size) priv_key = key_pair.exportKey() pub_key = key_pair.publickey().exportKey() priv_key_dict = {'alg' : 'rsa', 'type' : 'private', 'size': key_size, 'hash' : hash_alg, 'key' : priv_key} pub_key_dict = {'alg' : 'rsa', 'type' : 'public', 'size': key_size, 'hash' : hash_alg, 'key' : pub_key} #return priv_key_dict, pub_key_dict return [priv_key_dict, pub_key_dict] elif alg == 'ECC': if curve == 'X25519': key_pair = X25519PrivateKey.generate() pub_key = key_pair.public_key().public_bytes() priv_key_dict = {'alg' : 'ecc', 'curve' : 'x25519', 'type' : 'private', 'hash' : hash_alg, 'key': key_pair} pub_key_dict = {'alg' : 'ecc', 'curve' : 'x25519', 'type' : 'public', 'hash' : hash_alg, 'key' : pub_key} elif curve == 'P-256': #SECP256r1 key_pair = ec.generate_private_key(ec.SECP256R1(), default_backend()) priv_key = key_pair.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serializtion.NoEncryption) pub_key = key_pair.public_key().public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) priv_key_dict = {'alg' : 'ecc', 'curve' : 'p256', 'type' : 'private', 'hash' : hash_alg, 'key': priv_key} pub_key_dict = {'alg' : 'ecc', 'curve' : 'p256', 'type' : 'public', 'hash' : hash_alg, 'key' : pub_key} return priv_key_dict, pub_key_dict else: print('SA_ERROR:', alg, 'not yet implemented.', flush = True)
def create_keys(self): self.prv = X25519PrivateKey.generate() self.prv_bytes = self.prv.private_bytes( encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption()) self.sig_prv = Ed25519PrivateKey.generate() self.sig_prv_bytes = self.sig_prv.private_bytes( encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption()) self.pub = self.prv.public_key() self.pub_bytes = self.pub.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) self.sig_pub = self.sig_prv.public_key() self.sig_pub_bytes = self.sig_pub.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) self.update_hashes() RNS.log("Identity keys created for " + RNS.prettyhexrep(self.hash), RNS.LOG_VERBOSE)
def __init__(self, private_key, ephemeral_public, encryption_alg="AES-PMAC-SIV", digest_alg=hashes.SHA256(), salt=None): """ Create an XSTREAM decryptor object using our private key and an ephemeral public key :param private_key: 32-byte X25519 private key (i.e. private scalar) :param ephemeral_public: 32-byte X25519 ephemeral public key from XSTREAM encryption :param encryption_alg: symmetric encryption algorithm to use with STREAM (default "AES-PMAC-SIV") :param digest_alg: digest algorithm to use with HKDF (default "SHA256") :param salt: (optional) salt value to pass to HKDF (default None) """ # Perform an X25519 elliptic curve Diffie-Hellman operation and use # the resulting shared secret to derive a symmetric key (using HKDF) symmetric_key = kdf( private_key=X25519PrivateKey._from_private_bytes(private_key), public_key=X25519PublicKey.from_public_bytes(ephemeral_public), digest_alg=digest_alg, length=SYMMETRIC_KEY_SIZE, salt=salt) super(Decryptor, self).__init__(encryption_alg, symmetric_key, NONCE)
def isCryptographyAdvanced(): """ Check if the cryptography module is present, and if it supports X25519, ChaCha20Poly1305 and such. Notes: - cryptography >= 2.0 is required - OpenSSL >= 1.1.0 is required """ try: from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey # noqa: E501 X25519PrivateKey.generate() except Exception: return False else: return True
def x25519_key_derivation( self, public_key: 'OKP', context: CoseKDFContext = b'', alg: Optional[CoseAlgorithms] = None, curve: Optional[CoseEllipticCurves] = None) -> Tuple[bytes, bytes]: self._check_key_conf(alg, KeyOps.DERIVE_KEY, public_key, curve) try: alg_cfg = config(CoseAlgorithms(self.alg)) except KeyError as err: raise CoseIllegalAlgorithm(err) p = X25519PublicKey.from_public_bytes(public_key.x) d = X25519PrivateKey.from_private_bytes(self.d) shared_secret = d.exchange(p) derived_key = alg_cfg.kdf( algorithm=alg_cfg.hash(), length=int(context.supp_pub_info.key_data_length / 8), salt=None, info=context.encode(), backend=default_backend()).derive(shared_secret) return shared_secret, derived_key
def modify(packet): pkt = dpkt.ip6.IP6(packet.get_payload()) if is_icmp_neighbour_message(pkt): packet.accept() return aes_key_text = pkt.data[:256] aes_key_text = asymmetrickeya.decrypt(aes_key_text) nonce = struct.unpack(">I", pkt.data[256:260])[0] ecdhe = pkt.data[260:292] ci = struct.unpack(">I", pkt.data[292:296])[0] aes_key = AESGCM(aes_key_text) decrypted_block = bytes(aes_key.decrypt(bytes(nonce), pkt.data[296:], '')) ip_s = decrypted_block[:16] ecdhe_ac = X25519PrivateKey.generate() signature = sign(ecdhe_ac.public_key().public_bytes(), asymmetrickeya) pkt.data = decrypted_block[16:] + ecdhe_ac.public_key().public_bytes( ) + signature pkt.plen = len(pkt.data) pkt.dst = ip_s sockfd.sendto(bytes(pkt), (socket.inet_ntop(socket.AF_INET6, ip_s), 0)) packet.drop()
def test_profileA(self): hn_privkey = unhexlify( 'c53c22208b61860b06c62e5406a7b330c2b577aa5558981510d128247d38bd1d') hn_pubkey = unhexlify( '5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650') eph_privkey = unhexlify( 'c80949f13ebe61af4ebdbd293ea4f942696b9e815d7e8f0096bbf6ed7de62256') eph_pubkey = unhexlify( 'b2e92f836055a255837debf850b528997ce0201cb82adfe4be1f587d07d8457d') shared_key = unhexlify( '028ddf890ec83cdf163947ce45f6ec1a0e3070ea5fe57e2b1f05139f3e82422a') # plaintext = bytes.fromhex('00012080f6') ciphertext = unhexlify('cb02352410') mactag = unhexlify('cddd9e730ef3fa87') x1 = X25519(eph_privkey) x2 = X25519(hn_privkey) ue = ECIES_UE(profile='A') ue.EC.priv_key = X25519PrivateKey.from_private_bytes(eph_privkey) hn = ECIES_HN(profile='A', hn_priv_key=hn_privkey) ue.generate_sharedkey(hn_pubkey, fresh=False) ue_pk, ue_ct, ue_mac = ue.protect(plaintext) hn_ct = hn.unprotect(ue_pk, ue_ct, ue_mac) self.assertEqual(x1.get_pubkey(), eph_pubkey) self.assertEqual(x1.generate_sharedkey(hn_pubkey), shared_key) self.assertEqual(x2.get_pubkey(), hn_pubkey) self.assertEqual(x2.generate_sharedkey(eph_pubkey), shared_key) self.assertEqual(ue_ct, ciphertext) self.assertEqual(ue_mac, mactag) self.assertEqual(hn_ct, plaintext)
def ecies_hkdf(self, enckey, plainkey): if isinstance(enckey, ecdsa.ECDSA256P1Public): newpk = ec.generate_private_key(ec.SECP256R1(), default_backend()) shared = newpk.exchange(ec.ECDH(), enckey._get_public()) else: newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) derived_key = HKDF(algorithm=hashes.SHA256(), length=48, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) encryptor = Cipher(algorithms.AES(derived_key[:16]), modes.CTR(bytes([0] * 16)), backend=default_backend()).encryptor() cipherkey = encryptor.update(plainkey) + encryptor.finalize() mac = hmac.HMAC(derived_key[16:], hashes.SHA256(), backend=default_backend()) mac.update(cipherkey) ciphermac = mac.finalize() if isinstance(enckey, ecdsa.ECDSA256P1Public): pubk = newpk.public_key().public_bytes( encoding=Encoding.X962, format=PublicFormat.UncompressedPoint) else: pubk = newpk.public_key().public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw) return cipherkey, ciphermac, pubk
def generate( public_key, encryption_alg="AES-PMAC-SIV", digest_alg=hashes.SHA256(), salt=None, csrng=os.urandom, ): """ Generate an XSTREAM encryptor object with a random ephemeral key :param public_key: 32-byte X25519 public key (i.e. compressed Montgomery-u coordinate) :param encryption_alg: symmetric encryption algorithm to use with STREAM (default "AES-PMAC-SIV") :param digest_alg: digest algorithm to use with HKDF (default "SHA256") :param salt: (optional) salt value to pass to HKDF (default None) :param csrng: (optional) secure random number generator used to generate ephemeral key (default os.urandom) :return: STREAM encryptor and ephemeral public key """ ephemeral_scalar = X25519PrivateKey._from_private_bytes( csrng(X25519_KEY_SIZE)) symmetric_key = kdf( private_key=ephemeral_scalar, public_key=X25519PublicKey.from_public_bytes(public_key), digest_alg=digest_alg, length=SYMMETRIC_KEY_SIZE, salt=salt) enc = Encryptor(encryption_alg, symmetric_key, NONCE) return enc, ephemeral_scalar.public_key().public_bytes()
def __init__(self): self.s = socket.socket() host = socket.gethostname() port = 12345 self.s.connect((host, port)) self.messages = [] private_key_bob = X25519PrivateKey.generate() public_key_bob = private_key_bob.public_key() peer_public_alice_raw = (self.s.recv(2048)) #print(peer_public_alice_raw) self.s.send(public_key_bob.public_bytes(Encoding.Raw, PublicFormat.Raw)) peer_public_alice = X25519PublicKey.from_public_bytes( peer_public_alice_raw) shared_key = private_key_bob.exchange(peer_public_alice) derived_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data', backend=default_backend()).derive(shared_key) self.f = Fernet(base64.urlsafe_b64encode(derived_key)) t = threading.Thread(target=self.recvMessages, args=(self.s, )) t.start()
def generate_public_private_key(): """ generate_public_private_key uses curve25519 to generate a public and private key pair """ private_key = X25519PrivateKey.generate() return private_key.public_key(), private_key
def test_buffer_protocol(self, backend): private_bytes = bytearray(os.urandom(32)) key = X25519PrivateKey.from_private_bytes(private_bytes) assert key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption() ) == private_bytes
def test_rfc7748(self, vector, backend): private = binascii.unhexlify(vector["input_scalar"]) public = binascii.unhexlify(vector["input_u"]) shared_key = binascii.unhexlify(vector["output_u"]) private_key = X25519PrivateKey.from_private_bytes(private) public_key = X25519PublicKey.from_public_bytes(public) computed_shared_key = private_key.exchange(public_key) assert computed_shared_key == shared_key
def key_exchange(): key_pair = X25519PrivateKey.generate() public_key = key_pair.public_key() peer_public_key = X25519PublicKey.from_public_bytes(base64.b64decode(request.get_json().get('data').encode('utf-8'))) secret = key_pair.exchange(peer_public_key) id = base64.b64encode(urandom(16)).decode('utf-8') users[id] = secret return jsonify({'id': id, 'public_key': base64.b64encode( public_key.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw)).decode('utf-8')})
def test_rfc7748_1000_iteration(self, backend): old_private = private = public = binascii.unhexlify( b"090000000000000000000000000000000000000000000000000000000000" b"0000" ) shared_key = binascii.unhexlify( b"684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d9953" b"2c51" ) private_key = X25519PrivateKey.from_private_bytes(private) public_key = X25519PublicKey.from_public_bytes(public) for _ in range(1000): computed_shared_key = private_key.exchange(public_key) private_key = X25519PrivateKey.from_private_bytes( computed_shared_key ) public_key = X25519PublicKey.from_public_bytes(old_private) old_private = computed_shared_key assert computed_shared_key == shared_key
def isCryptographyAdvanced(): """ Check if the cryptography library is present, and if it supports X25519, ChaCha20Poly1305 and such (v2.0 or later). """ try: import cryptography except ImportError: return False from distutils.version import LooseVersion lib_valid = LooseVersion(cryptography.__version__) >= LooseVersion("2.0") if not lib_valid: return False try: from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey X25519PrivateKey.generate() except: return False else: return True
def test_pub_priv_bytes_raw(self, private_bytes, public_bytes, backend): private_key = X25519PrivateKey.from_private_bytes(private_bytes) assert private_key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption() ) == private_bytes assert private_key.public_key().public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw ) == public_bytes public_key = X25519PublicKey.from_public_bytes(public_bytes) assert public_key.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw ) == public_bytes
def test_null_shared_key_raises_error(self, backend): """ The vector used here is taken from wycheproof's x25519 test vectors """ public = binascii.unhexlify( "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157" ) private = binascii.unhexlify( "78f1e8edf14481b389448dac8f59c70b038e7cf92ef2c7eff57a72466e115296" ) private_key = X25519PrivateKey.from_private_bytes( private ) public_key = X25519PublicKey.from_public_bytes(public) with pytest.raises(ValueError): private_key.exchange(public_key)
def test_invalid_public_bytes(self, backend): key = X25519PrivateKey.generate().public_key() with pytest.raises(ValueError): key.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.SubjectPublicKeyInfo ) with pytest.raises(ValueError): key.public_bytes( serialization.Encoding.PEM, serialization.PublicFormat.PKCS1 ) with pytest.raises(ValueError): key.public_bytes( serialization.Encoding.PEM, serialization.PublicFormat.Raw )
def test_x25519(backend, wycheproof): assert list(wycheproof.testgroup.items()) == [("curve", "curve25519")] private_key = X25519PrivateKey.from_private_bytes( binascii.unhexlify(wycheproof.testcase["private"]) ) public_key = X25519PublicKey.from_public_bytes( binascii.unhexlify(wycheproof.testcase["public"]) ) assert wycheproof.valid or wycheproof.acceptable expected = binascii.unhexlify(wycheproof.testcase["shared"]) if expected == b"\x00" * 32: assert wycheproof.acceptable # OpenSSL returns an error on all zeros shared key with pytest.raises(ValueError): private_key.exchange(public_key) else: assert private_key.exchange(public_key) == expected
def test_invalid_private_bytes(self, backend): key = X25519PrivateKey.generate() with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.Raw, None ) with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8, None ) with pytest.raises(ValueError): key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.Raw, serialization.NoEncryption() )
def test_deprecated_public_bytes(self, backend): key = X25519PrivateKey.generate().public_key() with pytest.warns(utils.DeprecatedIn25): key.public_bytes()
def test_generate(self, backend): key = X25519PrivateKey.generate() assert key assert key.public_key()
def test_invalid_type_exchange(self, backend): key = X25519PrivateKey.generate() with pytest.raises(TypeError): key.exchange(object())
def test_invalid_length_from_private_bytes(self, backend): with pytest.raises(ValueError): X25519PrivateKey.from_private_bytes(b"a" * 31) with pytest.raises(ValueError): X25519PrivateKey.from_private_bytes(b"a" * 33)
def test_round_trip_private_serialization(self, encoding, fmt, encryption, passwd, load_func, backend): key = X25519PrivateKey.generate() serialized = key.private_bytes(encoding, fmt, encryption) loaded_key = load_func(serialized, passwd, backend) assert isinstance(loaded_key, X25519PrivateKey)
def test_public_bytes_bad_args(self, backend): key = X25519PrivateKey.generate().public_key() with pytest.raises(ValueError): key.public_bytes(None, serialization.PublicFormat.Raw) with pytest.raises(ValueError): key.public_bytes(serialization.Encoding.Raw)
def test_public_bytes(self, private_bytes, public_bytes, backend): private_key = X25519PrivateKey._from_private_bytes(private_bytes) assert private_key.public_key().public_bytes() == public_bytes public_key = X25519PublicKey.from_public_bytes(public_bytes) assert public_key.public_bytes() == public_bytes
def __generate_key(self): # Generate private and public key pair for client self.client_private_key = X25519PrivateKey.generate() self.client_public_key = self.client_private_key.public_key().public_bytes()