Esempio n. 1
0
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()
Esempio n. 2
0
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()
Esempio n. 3
0
    def unpack_request(self, packet):
        # pylint: disable=too-many-locals
        """Unpack an incoming request

        :param packet: Incoming packet to unpack
        :type packet: bytes

        :raises PSSSTUnsupportedCipher: cipher suite indicated in packet is not supported.
        :raises PSSSTNotRequest: packet is not a request packet.
        :raises PSSSTDecryptFailed: payload did not decrypt to valid and authentic data
        :raises PSSSTClientAuthFailed: client auth was present but did not match request
        :returns: tuple of unpacked data, authenticated client public key and reply handler

        """
        hdr = Header.from_packet(packet[:4])
        if hdr.reply:
            raise PSSSTNotRequest()
        if hdr.cipher_suite != self._suite:
            raise PSSSTUnsupportedCipher()
        dh_bytes = packet[4:36]
        exchange_dh = X25519PublicKey.from_public_bytes(dh_bytes)
        shared_secret = self._server_private.exchange(exchange_dh)

        key, nonce_client, nonce_server = _DKF_SHA256(dh_bytes, shared_secret)

        cipher = AESGCM(key)

        try:
            plaintext = cipher.decrypt(nonce_client, packet[36:], packet[:4])
        except InvalidTag as err:
            raise PSSSTDecryptFailed() from err

        if hdr.client_auth:
            client_public_key = X25519PublicKey.from_public_bytes(
                plaintext[:32])
            temp_privte_key = X25519PrivateKey.from_private_bytes(
                plaintext[32:64])
            auth_dh = temp_privte_key.exchange(client_public_key)
            if auth_dh != exchange_dh.public_bytes(encoding=Encoding.Raw,
                                                   format=PublicFormat.Raw):
                raise PSSSTClientAuthFailed()
            plaintext = plaintext[64:]
        else:
            client_public_key = None

        reply_handler = _ServerReplyHandler(packet[4:36], hdr.client_auth,
                                            hdr.cipher_suite, cipher,
                                            nonce_server)

        return (plaintext, client_public_key, reply_handler)
Esempio n. 4
0
    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()
Esempio n. 5
0
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()
Esempio n. 6
0
def verify_start(config: Config, context: dict, ios_device_public_key: bytes) -> List[dict]:
    """pair_verify M1 and M2"""
    curve25519 = X25519PrivateKey.generate()
    accessory_curve25519_public_key: bytes = curve25519.public_key().public_bytes()
    shared_secret: bytes = curve25519.exchange(X25519PublicKey.from_public_bytes(ios_device_public_key))

    accessory_info: bytes = accessory_curve25519_public_key + config.device_id.encode() + ios_device_public_key
    signing_key = ed25519.SigningKey(config.accessory_ltsk)
    accessory_signature = signing_key.sign(accessory_info)

    sub_tlv = tlv_parser.encode([{
        TlvCode.identifier: config.device_id,
        TlvCode.signature: accessory_signature,
    }])

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_VERIFY, info=INFO_VERIFY, backend=default_backend())
    session_key = hkdf.derive(shared_secret)

    chacha = ChaCha20Poly1305(session_key)
    encrypted_data = chacha.encrypt(NONCE_VERIFY_M2, sub_tlv, None)

    context['session_key'] = session_key
    context['shared_secret'] = shared_secret
    context['accessory_curve25519_public_key'] = accessory_curve25519_public_key
    context['ios_device_curve25519_public_key'] = ios_device_public_key

    return [{
        TlvCode.state: TlvState.m2,
        TlvCode.public_key: accessory_curve25519_public_key,
        TlvCode.encrypted_data: encrypted_data,
    }]
Esempio n. 7
0
    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)
Esempio n. 8
0
    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 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)
Esempio n. 10
0
    def setup0_response(self, response_data):
        # Interpret SessionResp0 response packet
        setup_resp = proto.session_pb2.SessionData()
        setup_resp.ParseFromString(tobytes(response_data))
        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.device_public_key = setup_resp.sec1.sr0.device_pubkey
        # Device random is the initialization vector
        device_random = setup_resp.sec1.sr0.device_random
        self._print_verbose("Device Public Key:\t" + utils.str_to_hexstr(self.device_public_key.decode('latin-1')))
        self._print_verbose("Device Random:\t" + utils.str_to_hexstr(device_random.decode('latin-1')))

        # Calculate Curve25519 shared key using Client private key and Device public key
        sharedK = self.client_private_key.exchange(X25519PublicKey.from_public_bytes(self.device_public_key))
        self._print_verbose("Shared Key:\t" + utils.str_to_hexstr(sharedK.decode('latin-1')))

        # If PoP is provided, XOR SHA256 of PoP with the previously
        # calculated Shared Key to form the actual Shared Key
        if len(self.pop) > 0:
            # Calculate SHA256 of PoP
            h = hashes.Hash(hashes.SHA256(), backend=default_backend())
            h.update(self.pop)
            digest = h.finalize()
            # XOR with and update Shared Key
            sharedK = xor(sharedK, digest)
            self._print_verbose("New Shared Key XORed with PoP:\t" + utils.str_to_hexstr(sharedK.decode('latin-1')))
        # Initialize the encryption engine with Shared Key and initialization vector
        cipher = Cipher(algorithms.AES(sharedK), modes.CTR(device_random), backend=default_backend())
        self.cipher = cipher.encryptor()
Esempio n. 11
0
    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
Esempio n. 12
0
 def setup0_response(self, response_data):
     setup_resp = proto.session_pb2.SessionData()
     setup_resp.ParseFromString(utils.bytearr_to_bytes(response_data))
     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 Public Key:\t" +
         utils.bytes_to_hexstr(setup_resp.sec1.sr0.device_pubkey))
     self._print_verbose(
         "Device Random:\t" +
         utils.bytes_to_hexstr(setup_resp.sec1.sr0.device_random))
     sharedK = self.client_private_key.exchange(
         X25519PublicKey.from_public_bytes(
             setup_resp.sec1.sr0.device_pubkey))
     self._print_verbose("Shared Key:\t" + utils.bytes_to_hexstr(sharedK))
     if len(self.pop) > 0:
         h = hashes.Hash(hashes.SHA256(), backend=default_backend())
         h.update(self.pop)
         digest = h.finalize()
         sharedK = utils.xor(sharedK, digest)
         self._print_verbose("New Shared Key XORed with PoP:\t" +
                             utils.bytes_to_hexstr(sharedK))
     self._print_verbose("IV " + hex(
         int(utils.bytes_to_hexstr(setup_resp.sec1.sr0.device_random), 16)))
     cipher = Cipher(algorithms.AES(sharedK),
                     modes.CTR(setup_resp.sec1.sr0.device_random),
                     backend=default_backend())
     self.cipher = cipher.encryptor()
     self.client_verify = self.cipher.update(
         setup_resp.sec1.sr0.device_pubkey)
     self._print_verbose("Client Verify:\t" +
                         utils.bytes_to_hexstr(self.client_verify))
Esempio n. 13
0
    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()
Esempio n. 14
0
 def _parse_kexecdh_init(self, m):
     peer_key_bytes = m.get_string()
     peer_key = X25519PublicKey.from_public_bytes(peer_key_bytes)
     K = self._perform_exchange(peer_key)
     K = long(binascii.hexlify(K), 16)
     # compute exchange hash
     hm = Message()
     hm.add(
         self.transport.remote_version,
         self.transport.local_version,
         self.transport.remote_kex_init,
         self.transport.local_kex_init,
     )
     server_key_bytes = self.transport.get_server_key().asbytes()
     exchange_key_bytes = self.key.public_key().public_bytes(
         serialization.Encoding.Raw, serialization.PublicFormat.Raw)
     hm.add_string(server_key_bytes)
     hm.add_string(peer_key_bytes)
     hm.add_string(exchange_key_bytes)
     hm.add_mpint(K)
     H = self.hash_algo(hm.asbytes()).digest()
     self.transport._set_K_H(K, H)
     sig = self.transport.get_server_key().sign_ssh_data(H)
     # construct reply
     m = Message()
     m.add_byte(c_MSG_KEXECDH_REPLY)
     m.add_string(server_key_bytes)
     m.add_string(exchange_key_bytes)
     m.add_string(sig)
     self.transport._send_message(m)
     self.transport._activate_outbound()
Esempio n. 15
0
    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
Esempio n. 16
0
    def _parse_kexecdh_reply(self, m):
        peer_host_key_bytes = m.get_string()
        peer_key_bytes = m.get_string()
        sig = m.get_binary()

        peer_key = X25519PublicKey.from_public_bytes(peer_key_bytes)

        K = self._perform_exchange(peer_key)
        K = long(binascii.hexlify(K), 16)
        # compute exchange hash and verify signature
        hm = Message()
        hm.add(
            self.transport.local_version,
            self.transport.remote_version,
            self.transport.local_kex_init,
            self.transport.remote_kex_init,
        )
        hm.add_string(peer_host_key_bytes)
        hm.add_string(self.key.public_key().public_bytes(
            serialization.Encoding.Raw, serialization.PublicFormat.Raw))
        hm.add_string(peer_key_bytes)
        hm.add_mpint(K)
        self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest())
        self.transport._verify_key(peer_host_key_bytes, sig)
        self.transport._activate_outbound()
Esempio n. 17
0
def test_round_trip_client_auth_text_keys():
    client = pssst.PSSSTClient(k1_pub, k2_priv)
    server = pssst.PSSSTServer(k1_priv)
    client_public_key = X25519PublicKey.from_public_bytes(
        bytes.fromhex(k2_pub))

    test_message = b"This is a test message"

    request_packet, client_reply_handler = client.pack_request(test_message)
    received_message, received_client_public_key, server_reply_handler = server.unpack_request(
        request_packet)

    assert received_message == test_message, "Message didn't arrive intact"

    source_client_key_bytes = client_public_key.public_bytes(
        encoding=Encoding.Raw, format=PublicFormat.Raw)
    received_client_key_bytes = received_client_public_key.public_bytes(
        encoding=Encoding.Raw, format=PublicFormat.Raw)

    assert received_client_key_bytes == source_client_key_bytes, "Bad client auth"

    reply_packet = server_reply_handler(received_message)
    round_trip_message = client_reply_handler(reply_packet)

    assert round_trip_message == test_message, "Round trip failed"
Esempio n. 18
0
    def setup0_response(self, response_data):
        # Interpret SessionResp0 response packet
        setup_resp = proto.session_pb2.SessionData()
        setup_resp.ParseFromString(tobytes(response_data))
        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.device_public_key = setup_resp.sec1.sr0.device_pubkey
        # Device random is the initialization vector
        device_random = setup_resp.sec1.sr0.device_random
        self._print_verbose('Device Public Key:\t' + utils.str_to_hexstr(self.device_public_key.decode('latin-1')))
        self._print_verbose('Device Random:\t' + utils.str_to_hexstr(device_random.decode('latin-1')))

        # Calculate Curve25519 shared key using Client private key and Device public key
        sharedK = self.client_private_key.exchange(X25519PublicKey.from_public_bytes(self.device_public_key))
        self._print_verbose('Shared Key:\t' + utils.str_to_hexstr(sharedK.decode('latin-1')))

        # If PoP is provided, XOR SHA256 of PoP with the previously
        # calculated Shared Key to form the actual Shared Key
        if len(self.pop) > 0:
            # Calculate SHA256 of PoP
            h = hashes.Hash(hashes.SHA256(), backend=default_backend())
            h.update(self.pop)
            digest = h.finalize()
            # XOR with and update Shared Key
            sharedK = xor(sharedK, digest)
            self._print_verbose('New Shared Key XORed with PoP:\t' + utils.str_to_hexstr(sharedK.decode('latin-1')))
        # Initialize the encryption engine with Shared Key and initialization vector
        cipher = Cipher(algorithms.AES(sharedK), modes.CTR(device_random), backend=default_backend())
        self.cipher = cipher.encryptor()
Esempio n. 19
0
    def shared_secret(private_key: 'CK', public_key: 'CK') -> bytes:
        """ Compute the shared secret. """

        if public_key.crv == X25519:
            d = X25519PrivateKey.from_private_bytes(private_key.d)
            x = X25519PublicKey.from_public_bytes(public_key.x)
            secret = d.exchange(x)
        elif public_key.crv == X448:
            d = X448PrivateKey.from_private_bytes(private_key.d)

            x = X448PublicKey.from_public_bytes(public_key.x)
            secret = d.exchange(x)
        elif public_key.crv == P256:
            d = ec.derive_private_key(int(hexlify(private_key.d), 16),
                                      SECP256R1(), default_backend())

            x = ec.EllipticCurvePublicNumbers(int(hexlify(public_key.x), 16),
                                              int(hexlify(public_key.y), 16),
                                              SECP256R1())
            x = x.public_key()
            secret = d.exchange(ec.ECDH(), x)
        else:
            raise CoseIllegalCurve(f"{public_key.crv} is unsupported")

        return secret
Esempio n. 20
0
    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
Esempio n. 21
0
 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
Esempio n. 22
0
 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
Esempio n. 23
0
 def __init__(self, public_key: Union[str, X25519PublicKey]):
     if isinstance(public_key, X25519PublicKey):
         self.__public_key = public_key
     elif isinstance(public_key, str):
         self.__public_key = X25519PublicKey.from_public_bytes(
             base64.b64decode(public_key))
     else:
         raise TypeError(
             "public_key must be a string or X25519PublicKey object")
Esempio n. 24
0
def diffie_hellman(priv_bytes: bytes, pub_bytes: bytes) -> bytes:
    """
    Performs a Diffie-Hellman operation on the two keys
    :param priv_bytes: bytes of the first key
    :param pub_bytes: bytes of the second key
    :return: exchange of the two keys
    """
    return X25519PrivateKey.from_private_bytes(priv_bytes).exchange(
        X25519PublicKey.from_public_bytes(pub_bytes))
Esempio n. 25
0
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')})
Esempio n. 26
0
 def _on_dhkey(self, peer_id, dh_key):
     """Used only on session establishment. Subsequently it's
        sent via EncryptedMessage.
     """
     self.logger.debug(f"peer dhkey: {dh_key}")
     dh_public_key = X25519PublicKey.from_public_bytes(
         base64.b64decode(dh_key))
     self.sessions[peer_id].dh_public_key = dh_public_key
     self.dh_ratchet(peer_id, dh_public_key)
     self.sessions[peer_id].state = RatchetState.SENDING
Esempio n. 27
0
    def load_peer(self, peer_pub_bytes, peer_sig_pub_bytes):
        self.peer_pub_bytes = peer_pub_bytes
        self.peer_pub = X25519PublicKey.from_public_bytes(self.peer_pub_bytes)

        self.peer_sig_pub_bytes = peer_sig_pub_bytes
        self.peer_sig_pub = Ed25519PublicKey.from_public_bytes(
            self.peer_sig_pub_bytes)

        if not hasattr(self.peer_pub, "curve"):
            self.peer_pub.curve = Link.CURVE
Esempio n. 28
0
def _key_check(key_value, public):
    if key_value is None:
        return None
    if isinstance(key_value, str):
        key_value = bytes.fromhex(key_value)
    if isinstance(key_value, bytes):
        if public:
            key_value = X25519PublicKey.from_public_bytes(key_value)
        else:
            key_value = X25519PrivateKey.from_private_bytes(key_value)
    return key_value
Esempio n. 29
0
    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
Esempio n. 30
0
def check_ecdh(card, key_num=2):
    myPublicKey, myPrivateKey = ecdsa_keys.generate_key_eddsa_ecdh()
    myPublicKeyTLV = ecdh_public_key_encode(ecdsa_keys.ecc_to_string(myPublicKey))

    pk = card.cmd_get_public_key(key_num)
    pk_info = get_pk_info(pk)
    sharedSecret = card.cmd_pso(0x80, 0x86, myPublicKeyTLV)

    peer_pk = X25519PublicKey.from_public_bytes(pk_info[0])
    mySharedSecret = myPrivateKey.exchange(peer_pk)

    return sharedSecret == mySharedSecret
Esempio n. 31
0
def x25519_key_derive(private, peer):
    peer_public = X25519PublicKey.from_public_bytes(
        bytes.fromhex(peer.strip()))
    shared = private.exchange(peer_public)
    derived_key = HKDF(
        algorithm=hashes.SHA256(),
        length=32,
        salt=b'',
        info=b'exchange',
        backend=default_backend()
    ).derive(shared)
    return derived_key.hex().strip()
Esempio n. 32
0
 def _on_new_session(self, n, peer_id, rest):
     self.peer_keys[peer_id]["EK"] = X25519PublicKey.from_public_bytes(
         base64.b64decode(rest))
     if peer_id in self.sessions:
         return
     self.x3dh_receiver(self.peer_keys[peer_id])
     self.init_ratchets(peer_id, sender=False)
     self.sessions[
         peer_id].dh_ratchet = dh_ratchet = X25519PrivateKey.generate()
     dh_key = b64k(dh_ratchet.public_key())
     message = " ".join(["/dhkey", dh_key])
     n.whisper(peer_id, message.encode("utf-8"))
Esempio n. 33
0
def test_fake_client_auth():
    server_private_key, server_public_key = generate_key_pair(
        cipher_suite=pssst.CipherSuite.X25519_AESGCM128)
    client_private_key, client_public_key = generate_key_pair(
        cipher_suite=pssst.CipherSuite.X25519_AESGCM128)

    server = PSSSTServer(server_private_key)

    test_message = b"This is a test message"

    # Build a fake client-auth packet

    header = Header(cipher_suite=CipherSuite.X25519_AESGCM128,
                    reply=False,
                    client_auth=True)

    partial_key_bytes = client_private_key.exchange(server_public_key)
    client_server_pub = X25519PublicKey.from_public_bytes(partial_key_bytes)

    temp_priv_key = X25519PrivateKey.generate()
    exchange_dh = temp_priv_key.exchange(client_public_key)
    shared_secret = temp_priv_key.exchange(client_server_pub)
    client_pub_bytes = client_public_key.public_bytes(encoding=Encoding.Raw,
                                                      format=PublicFormat.Raw)
    temp_private_bytes = temp_priv_key.private_bytes(
        encoding=Encoding.Raw,
        format=PrivateFormat.Raw,
        encryption_algorithm=NoEncryption())

    data = client_pub_bytes + temp_private_bytes + test_message

    key, nonce_client, nonce_server = pssst.pssst._DKF_SHA256(
        exchange_dh, shared_secret)

    # Test 1: make sure that our dummy code works

    packet = header.packet_bytes + exchange_dh
    cipher = AESGCM(key)
    data = client_pub_bytes + temp_private_bytes + test_message
    packet += cipher.encrypt(nonce_client, data, packet[:4])

    server.unpack_request(packet)

    # Test 2: make sure it fails when we pass the wrong public key

    packet = header.packet_bytes + exchange_dh
    cipher = AESGCM(key)
    bad_key = b'\xaa' * 32
    data = bad_key + temp_private_bytes + test_message
    packet += cipher.encrypt(nonce_client, data, packet[:4])

    with pytest.raises(pssst.PSSSTClientAuthFailed):
        server.unpack_request(packet)
Esempio n. 34
0
 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)
Esempio n. 35
0
 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
Esempio n. 36
0
 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
Esempio n. 37
0
 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)
Esempio n. 38
0
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
Esempio n. 39
0
    def test_invalid_length_from_public_bytes(self, backend):
        with pytest.raises(ValueError):
            X25519PublicKey.from_public_bytes(b"a" * 31)

        with pytest.raises(ValueError):
            X25519PublicKey.from_public_bytes(b"a" * 33)
Esempio n. 40
0
 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