def load_keys():
    try:
        tmp_keys = json.load(open(key_path))
        fix_key_perms()
    except:
        keys['my_key'] = curve25519.Private()
        save_keys()
        return

    for key in tmp_keys:
        if key == 'my_key':
            keys[key] = curve25519.Private(b64decode(tmp_keys[key]))
        else:
            keys[key] = curve25519.Public(b64decode(tmp_keys[key]))
Beispiel #2
0
    def decrypt_message(self, ct, decryptor):
        decryptor = self.derive_keys(decryptor)

        pt = self.decrypt(ct, decryptor['message_key'], decryptor['message_counter'])
        if not pt:
            return None

        bob_ephemeral, msg = pt[:32], pt[32:]

        self.receive = decryptor

        # it's encrypted with the same key it advertised.. shouldn't happen.
        if bob_ephemeral == self.receive['bob'].serialize():
            raise
        # it's advertising the receive_pending key, we need to respond again because
        # they may not have gotten it.
        elif self.receive_pending \
          and bob_ephemeral == self.receive_pending['bob'].serialize():
            pass
        # yay a new key! we need to respond.
        elif not self.receive_pending \
          or bob_ephemeral != self.receive_pending['bob'].serialize():

            self.receive_pending = {
                'alice': curve25519.Private(),
                'bob': curve25519.Public(bob_ephemeral),
                'receiver': True,
                'acked': False
            }
        # uncharted territory...
        else:
            raise

        return msg
Beispiel #3
0
def recover_seed(key='', modulus=None, pos=1):
    # recreate the master private key from the passphrase
    master = curve25519.Private(secret=sha256(key).digest())
    # extract the ephemeral public key from modulus
    ephem_pub = curve25519.Public(modulus[pos:pos + 32])
    # compute seed with master private and ephemeral public
    return (master.get_shared_key(ephem_pub), ephem_pub)
Beispiel #4
0
    def login(self):
        self._expected_message_tags = ['s1', 's2', 's3', 's4']

        self._clientId = str(b64encode(os.urandom(16)), 'utf8')
        self._whatsappweb_version = get_whatsappweb_version()

        connection_query_name = 'connection_query'
        self._expected_message_tags.append(connection_query_name)
        connection_query_json = ['admin', 'init', self._whatsappweb_version, self._browser_desc, self._clientId, True]
        self.ws_send(connection_query_name, connection_query_json)
        connection_result = self.wait_query_pop_json(connection_query_name)

        if connection_result['status'] != 200:
            raise ConnectionRefusedError('Websocket connection refused')
        
        self._qrcode = {
            'must_scan': False,
            'id': 0,
            'ref': connection_result['ref'],
            'ttl' : connection_result['ttl'] / 1000 - 1,
            'time' : connection_result['time']}
        self._qrcode['timeout'] = time.time() + self._qrcode['ttl']

        if self._session_path and os.path.exists(self._session_path):
            self.restore_session()
            self.post_login()
        else:
            self._qrcode['must_scan'] = True
            self._privateKey = curve25519.Private()
            self._publicKey = self._privateKey.get_public()

            bin_qrcode = gen_qrcode(self._qrcode['ref'], self._publicKey, self._clientId)
            self._qrcode['qrcode'] = render_qrcode(bin_qrcode)
Beispiel #5
0
 def verify1(self):
     """
     First device verification step.
     """
     self._verify_private = curve25519.Private(secret=self.seed)
     self._verify_public = self._verify_private.get_public()
     verify_public = self._verify_public.serialize()
     return b'\x01\x00\x00\x00' + verify_public + self._auth_public
Beispiel #6
0
 def initialize(self):
     """Initialize operation by generating new keys."""
     self._signing_key = SigningKey(os.urandom(32))
     self._auth_private = self._signing_key.to_seed()
     self._auth_public = self._signing_key.get_verifying_key().to_bytes()
     self._verify_private = curve25519.Private(secret=os.urandom(32))
     self._verify_public = self._verify_private.get_public()
     return self._auth_public, self._verify_public.serialize()
def test_curve25519(r):
    sec1 = bytes(bytearray(r.randbytes(32)))
    sec2 = bytes(bytearray(r.randbytes(32)))
    pub1 = curve25519.Private(sec1).get_public()
    pub2 = curve25519.Private(sec2).get_public()

    session1 = r.randbytes(32)
    lib.curve25519_scalarmult(session1, sec2, pub1.public)
    session2 = r.randbytes(32)
    lib.curve25519_scalarmult(session2, sec1, pub2.public)
    assert bytearray(session1) == bytearray(session2)

    shared1 = curve25519.Private(sec2).get_shared_key(pub1, hashfunc=lambda x: x)
    shared2 = curve25519.Private(sec1).get_shared_key(pub2, hashfunc=lambda x: x)
    assert shared1 == shared2
    assert bytearray(session1) == shared1
    assert bytearray(session2) == shared2
Beispiel #8
0
 def _generate_keys(self, mkey):
     """
     start to generate authentication keys, and allowing to set the
     mac_key value in case exists
     """
     self.private = curve25519.Private()
     self.public = self.private.get_public()
     self.mac_key = mkey
Beispiel #9
0
def generate_keys(seed):
    """Generate server encryption keys from seed."""
    signing_key = SigningKey(seed)
    verify_private = curve25519.Private(secret=seed)
    return ServerKeys(sign=signing_key,
                      auth=signing_key.to_bytes(),
                      auth_pub=signing_key.get_verifying_key().to_bytes(),
                      verify=verify_private,
                      verify_pub=verify_private.get_public())
Beispiel #10
0
    def __init__(self, node):
        # 5.1.4. The "ntor" handshake

        # This handshake uses a set of DH handshakes to compute a set of
        # shared keys which the client knows are shared only with a particular
        # server, and the server knows are shared with whomever sent the
        # original handshake (or with nobody at all).  Here we use the
        # "curve25519" group and representation as specified in "Curve25519:
        # new Diffie-Hellman speed records" by D. J. Bernstein.

        # [The ntor handshake was added in Tor 0.2.4.8-alpha.]

        self.node = node

        # In this section, define:
        #   H(x,t) as HMAC_SHA256 with message x and key t.
        #   H_LENGTH  = 32.
        #   ID_LENGTH = 20.
        #   G_LENGTH  = 32
        #   PROTOID   = "ntor-curve25519-sha256-1"
        #   t_mac     = PROTOID | ":mac"
        #   t_key     = PROTOID | ":key_extract"
        #   t_verify  = PROTOID | ":verify"
        #   MULT(a,b) = the multiplication of the curve25519 point 'a' by the
        #               scalar 'b'.
        #   G         = The preferred base point for curve25519 ([9])
        #   KEYGEN()  = The curve25519 key generation algorithm, returning
        #               a private/public keypair.
        #   m_expand  = PROTOID | ":key_expand"

        # H is defined as hmac()
        # MULT is included in the curve25519 library as get_shared_key()
        # KEYGEN() is curve25519.Private()
        self.protoid = 'ntor-curve25519-sha256-1'
        self.t_mac = self.protoid + ':mac'
        self.t_key = self.protoid + ':key_extract'
        self.t_verify = self.protoid + ':verify'
        self.m_expand = self.protoid + ':key_expand'

        # To perform the handshake, the client needs to know an identity key
        # digest for the server, and an ntor onion key (a curve25519 public
        # key) for that server. Call the ntor onion key "B".  The client
        # generates a temporary keypair:
        #     x,X = KEYGEN()
        self.x = curve25519.Private()
        self.X = self.x.get_public()

        self.B = curve25519.Public(b64decode(self.node['ntor-onion-key']))

        # and generates a client-side handshake with contents:
        #   NODEID      Server identity digest  [ID_LENGTH bytes]
        #   KEYID       KEYID(B)                [H_LENGTH bytes]
        #   CLIENT_PK   X                       [G_LENGTH bytes]
        self.handshake = b64decode(self.node['identity'])
        self.handshake += self.B.serialize()
        self.handshake += self.X.serialize()
Beispiel #11
0
 def verify1(self):
     """First device verification step."""
     self._check_initialized()
     self._verify_private = curve25519.Private(secret=self.seed)
     self._verify_public = self._verify_private.get_public()
     _log_debug('Verification keys',
                Private=self._verify_private.serialize(),
                Public=self._verify_public.serialize())
     verify_public = self._verify_public.serialize()
     return b'\x01\x00\x00\x00' + verify_public + self._auth_public
Beispiel #12
0
    def __init__(self, loop, credentials, atv_device_id):
        """Initialize a new instance of ProxyMrpAppleTV."""
        self.loop = loop
        self.credentials = credentials
        self.atv_device_id = atv_device_id
        self.server = None
        self.buffer = b''
        self.has_paired = False
        self.transport = None
        self.chacha = None
        self.connection = None
        self.input_key = None
        self.output_key = None
        self.mapping = {
            protobuf.DEVICE_INFO_MESSAGE: self.handle_device_info,
            protobuf.CRYPTO_PAIRING_MESSAGE: self.handle_crypto_pairing,
        }

        self._shared = None
        self._session_key = None
        self._signing_key = SigningKey(32 * b'\x01')
        self._auth_private = self._signing_key.to_seed()
        self._auth_public = self._signing_key.get_verifying_key().to_bytes()
        self._verify_private = curve25519.Private(secret=32 * b'\x01')
        self._verify_public = self._verify_private.get_public()

        self.context = SRPContext('Pair-Setup',
                                  str(1111),
                                  prime=constants.PRIME_3072,
                                  generator=constants.PRIME_3072_GEN,
                                  hash_func=hashlib.sha512,
                                  bits_salt=128)
        self.username, self.verifier, self.salt = \
            self.context.get_user_data_triplet()

        context_server = SRPContext('Pair-Setup',
                                    prime=constants.PRIME_3072,
                                    generator=constants.PRIME_3072_GEN,
                                    hash_func=hashlib.sha512,
                                    bits_salt=128)

        self._session = SRPServerSession(
            context_server, self.verifier,
            binascii.hexlify(self._auth_private).decode())
Beispiel #13
0
    def _pair_verify_one(self, tlv_objects):
        """Generate new session key pair and send a proof to the client.

        @param tlv_objects: The TLV data received from the client.
        @type tlv_object: dict
        """
        logger.debug("Pair verify [1/2].")
        client_public = tlv_objects[HAP_TLV_TAGS.PUBLIC_KEY]

        private_key = curve25519.Private()
        public_key = private_key.get_public()
        shared_key = private_key.get_shared_key(
            curve25519.Public(client_public),
            # Key is hashed before being returned, we don't want it; This fixes that.
            lambda x: x,
        )

        mac = self.state.mac.encode()
        material = public_key.serialize() + mac + client_public
        server_proof = self.state.private_key.sign(material)

        output_key = hap_hkdf(shared_key, self.PVERIFY_1_SALT,
                              self.PVERIFY_1_INFO)

        self._set_encryption_ctx(client_public, private_key, public_key,
                                 shared_key, output_key)

        message = tlv.encode(HAP_TLV_TAGS.USERNAME, mac, HAP_TLV_TAGS.PROOF,
                             server_proof)

        cipher = ChaCha20Poly1305(output_key)
        aead_message = bytes(
            cipher.encrypt(self.PVERIFY_1_NONCE, bytes(message), b""))
        data = tlv.encode(
            HAP_TLV_TAGS.SEQUENCE_NUM,
            b"\x02",
            HAP_TLV_TAGS.ENCRYPTED_DATA,
            aead_message,
            HAP_TLV_TAGS.PUBLIC_KEY,
            public_key.serialize(),
        )
        self.send_response(200)
        self.send_header("Content-Type", self.PAIRING_RESPONSE_TYPE)
        self.end_response(data)
Beispiel #14
0
    def __init__(self, ref_dict, priv_key_list, pub_key_list):

        self.conn_data = {
            "private_key": None,
            "public_key": None,
            "secret": None,
            "shared_secret": None,
            "shared_secret_ex": None,
            "aes_key": None,
            "mac_key": None
        }

        self.conn_data["private_key"] = curve25519.Private("".join(
            [chr(x) for x in priv_key_list]))
        self.conn_data["public_key"] = self.conn_data[
            "private_key"].get_public()

        assert (self.conn_data["public_key"].serialize() == "".join(
            [chr(x) for x in pub_key_list]))

        self.conn_data["secret"] = base64.b64decode(ref_dict["secret"])
        self.conn_data["shared_secret"] = self.conn_data[
            "private_key"].get_shared_key(
                curve25519.Public(self.conn_data["secret"][:32]),
                lambda key: key)

        shared_expended = self.conn_data["shared_secret_ex"] = HKDF(
            self.conn_data["shared_secret"], 80)

        check_hmac = hmac_sha256(
            shared_expended[32:64],
            self.conn_data["secret"][:32] + self.conn_data["secret"][64:])

        if check_hmac != self.conn_data["secret"][32:64]:
            raise ValueError("Error hmac mismatch")

        keysDecrypted = AESDecrypt(
            shared_expended[:32],
            shared_expended[64:] + self.conn_data["secret"][64:])

        self.conn_data["aes_key"] = keysDecrypted[:32]
        self.conn_data["mac_key"] = keysDecrypted[32:64]
Beispiel #15
0
    def _pair_verify_one(self, tlv_objects):
        """Generate new session key pair and send a proof to the client.

        @param tlv_objects: The TLV data received from the client.
        @type tlv_object: dict
        """
        logging.debug("Pair verify [1/2].")
        client_public = tlv_objects[HAP_TLV_TAGS.PUBLIC_KEY]

        private_key = curve25519.Private()
        public_key = private_key.get_public()
        shared_key = private_key.get_shared_key(
            curve25519.Public(client_public),
            # Key is hashed before being returned, we don't want it; This fixes that.
            lambda x: x)

        mac = self._state.mac.encode()
        material = public_key.serialize() + mac + client_public
        server_proof = self._state.private_key.sign(material)

        output_key = hap_hkdf(shared_key, PVERIFY_1_SALT, PVERIFY_1_INFO)

        enc_context = {
            "client_public": client_public,
            "private_key": private_key,
            "public_key": public_key,
            "shared_key": shared_key,
            "pre_session_key": output_key
        }

        message = tlv.encode(HAP_TLV_TAGS.USERNAME, mac, HAP_TLV_TAGS.PROOF,
                             server_proof)

        cipher = CHACHA20_POLY1305(output_key, "python")
        aead_message = bytes(
            cipher.seal(PVERIFY_1_NONCE, bytearray(message), b""))
        data = tlv.encode(HAP_TLV_TAGS.SEQUENCE_NUM, b'\x02',
                          HAP_TLV_TAGS.ENCRYPTED_DATA, aead_message,
                          HAP_TLV_TAGS.PUBLIC_KEY, public_key.serialize())
        return data, enc_context
Beispiel #16
0
   def _pair_verify_one(self, tlv_objects):
      """Generate new session key pair and send a proof to the client.

      @param tlv_objects: The TLV data received from the client.
      @type tlv_object: dict
      """
      logger.debug("Pair verify [1/2].")
      client_public = tlv_objects[HAP_TLV_TAGS.PUBLIC_KEY]

      private_key = curve25519.Private()
      public_key = private_key.get_public()
      shared_key = private_key.get_shared_key(
                        curve25519.Public(client_public),
            # Why not randomly hash the key before returning it
            # so that it is incompatible with another
            # implementation and force clients to use hacks?
                        lambda x: x)

      mac = self.accessory.mac.encode()
      material = public_key.serialize() + mac + client_public
      server_proof = self.accessory.private_key.sign(material)

      output_key = hap_hkdf(shared_key, self.PVERIFY_1_SALT, self.PVERIFY_1_INFO)

      self._set_encryption_ctx(client_public, private_key, public_key,
                               shared_key, output_key)

      message = tlv.encode(HAP_TLV_TAGS.USERNAME, mac,
                           HAP_TLV_TAGS.PROOF, server_proof)

      cipher = CHACHA20_POLY1305(output_key, "python")
      aead_message = bytes(
         cipher.seal(self.PVERIFY_1_NONCE, bytearray(message), b""))
      data = tlv.encode(HAP_TLV_TAGS.SEQUENCE_NUM, b'\x02',
                        HAP_TLV_TAGS.ENCRYPTED_DATA, aead_message,
                        HAP_TLV_TAGS.PUBLIC_KEY, public_key.serialize())
      self.send_response(200)
      self.send_header("Content-Type", self.PAIRING_RESPONSE_TYPE)
      self.end_response(data)
Beispiel #17
0
    def initLocalParams(self):
        logging.info('Entering Initlocalparms')
        self.data = self.restoreSession()
        keySecret = None
        if self.data is None:
            self.mydata['clientId'] = base64.b64encode(os.urandom(16))
            keySecret = os.urandom(32)
            self.mydata["keySecret"] = base64.b64encode(keySecret)

        else:
            self.sessionExists = True
            self.mydata = self.data['myData']
            keySecret = base64.b64decode(self.mydata["keySecret"])

        self.clientId = self.mydata['clientId']
        self.privateKey = curve25519.Private(secret=keySecret)
        self.publicKey = self.privateKey.get_public()
        logging.info('ClientId %s' % self.clientId)
        logging.info('Exiting Initlocalparms')

        if self.sessionExists:
            self.setConnInfoParams(base64.b64decode(self.data["secret"]))
Beispiel #18
0
    def derive_keys(self, key=None):
        # initial key exchanges.
        if not key or 'bob' not in key:
            master = self.long_term.get_shared_key(self.bob_long_term, self.derive_key)
            key = key or {}
        # we're sending
        elif 'receiver' not in key:
            master  = self.long_term.get_shared_key(key['bob'], self.derive_key)
            master += key['alice'].get_shared_key(self.bob_long_term, self.derive_key)
            master += key['alice'].get_shared_key(key['bob'], self.derive_key)
        # we are receiving
        else:
            if 'alice' not in key:
                key['alice'] = curve25519.Private()

            master  = key['alice'].get_shared_key(self.bob_long_term, self.derive_key)
            master += self.long_term.get_shared_key(key['bob'], self.derive_key)
            master += key['alice'].get_shared_key(key['bob'], self.derive_key)

        # derive keys
        # increment counter
        if 'counter' in key:
            key['counter'] += 1
        else:
            key['counter'] = 0

        mac_key = self.proto_id + '::poly1305'
        master = poly1305(master + str(key['counter']), mac_key)
        master = self.derive_key(master, 176)
        
        keys = list(struct.unpack('>32s32s32s32s24s24s', master))
        key['exchange_counter'] = keys.pop()
        key['message_counter'] = keys.pop()
        key['exchange_chaff_key'] = keys.pop()
        key['chaff_key'] = keys.pop()
        key['exchange_key'] = keys.pop()
        key['message_key'] = keys.pop()
        return key
Beispiel #19
0
    def encrypt_msg(self, msg):
        self.send = self.derive_keys(self.send)
        self.print_key('Encrypting message.', self.send)

        if not self.send_pending:
            self.send_pending = { 'alice': curve25519.Private() }

        pt  = self.get_public(self.send_pending['alice'])
        pt += msg

        # message buffering
        if 'msgs' not in self.send_pending:
            self.send_pending['msgs'] = []
        self.send_pending['msgs'].append(msg)

        if not self.established():
            return

        ct = self.encrypt(pt, self.send['message_key'],
            self.send['message_counter'])

        blocks = self.mac_blocks(ct, self.send['chaff_key'])
        return self.chaff(blocks)
    def __init__(self, ref_dict, priv_key_list, pub_key_list):
        self.decrypted_serialized_content = None
        self.message_tag = None
        self.decrypted_content = None
        self.original_content = None

        self.private_key = None
        self.public_key = None
        self.secret = None
        self.shared_secret = None
        self.aes_key = None
        self.mac_key = None

        self.private_key = curve25519.Private("".join(
            [chr(x) for x in priv_key_list]))
        self.public_key = self.private_key.get_public()

        assert (self.public_key.serialize() == "".join(
            [chr(x) for x in pub_key_list]))

        self.secret = base64.b64decode(ref_dict["secret"])
        self.shared_secret = self.private_key.get_shared_key(
            curve25519.Public(self.secret[:32]), lambda key: key)

        shared_expended = HKDF(self.shared_secret, 80)

        check_hmac = hmac_sha256(shared_expended[32:64],
                                 self.secret[:32] + self.secret[64:])

        if check_hmac != self.secret[32:64]:
            raise ValueError("Error hmac mismatch")

        keys_decrypted = aes_decrypt(shared_expended[:32],
                                     shared_expended[64:] + self.secret[64:])

        self.aes_key = keys_decrypted[:32]
        self.mac_key = keys_decrypted[32:64]
Beispiel #21
0
    def initLocalParams(self):
        logging.info('Entering Initlocalparms')
        logging.info('Local storage is: {}'.format(self.isLocalStorage))
        self.data = self.restoreSession()
        keySecret = None
        if self.data is None:
            self.mydata['clientId'] = base64.b64encode(os.urandom(16))
            keySecret = os.urandom(32)
            self.mydata["keySecret"] = base64.b64encode(keySecret)

        else:
            self.sessionExists = True
            if not self.isLocalStorage:
                self.mydata = self.data['myData']
                keySecret = base64.b64decode(self.mydata["keySecret"])
            else:
                self.mydata = self.data
                self.data["clientToken"] = json.loads(self.data["WAToken1"])
                self.data["serverToken"] = json.loads(self.data["WAToken2"])
                self.data["clientId"] = json.loads(self.data["WABrowserId"])
                self.mydata = self.data

        self.clientId = self.mydata['clientId']
        self.privateKey = curve25519.Private(secret=keySecret)
        self.publicKey = self.privateKey.get_public()
        logging.info('ClientId %s' % self.clientId)
        logging.info('Exiting Initlocalparms')

        if self.sessionExists:
            if not self.isLocalStorage:
                self.setConnInfoParams(base64.b64decode(self.data["secret"]))
            else:
                secretBundle = json.loads(self.data['WASecretBundle'])
                self.encKey = base64.b64decode(secretBundle['encKey'])
                self.macKey = base64.b64decode(secretBundle['macKey'])
        self.subscribeStarted = False
Beispiel #22
0
def test_curve25519_pubkey(r):
    sec = bytes(bytearray(r.randbytes(32)))
    pub = curve25519.Private(sec).get_public()
    res = r.randbytes(32)
    lib.curve25519_scalarmult_basepoint(res, sec)
    assert bytearray(res) == pub.public
Beispiel #23
0
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.Private()
        # derive the corresponding public key for later embedding
        ephem_pub = ephem.get_public()
        # combine the ECDH keys to generate the seed
        seed = ephem.get_shared_key(master_pub)

    prng = AESPRNG(seed)
    ephem_pub = ephem_pub.serialize()

    # 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")
Beispiel #24
0
 def __init__(self, secret=None):
     self._private = curve25519.Private(secret)
Beispiel #25
0
 def init_keys(self):
     self.initialized = False
     self.initial_key = { 'initial_key': True }
     self.send = { 'alice': curve25519.Private() }
     self.receive = { 'alice': curve25519.Private(), 'receiver': True }
Beispiel #26
0
    def pairVerifyStep1(self, tlvData):
        publicKey = tlvData['public_key']['data']

        accessoryLTSK = ed25519.SigningKey(self.longTermKey, encoding='hex')
        # accessoryLTPK = accessoryLTSK.get_verifying_key()

        accessoryPairingID = HapHandler.getId()

        iosDevicePublicKey = curve25519.Public(''.join(
            [chr(x) for x in publicKey]))

        # Step 1
        private = curve25519.Private()
        public = private.get_public()
        publicSerialized = public.serialize()

        # Step 2
        shared = private.get_shared_key(iosDevicePublicKey,
                                        hashfunc=lambda x: x)

        # Step 3
        accessoryPairingInfo = publicSerialized + accessoryPairingID + iosDevicePublicKey.serialize(
        )

        # Step 4
        accessorySignature = accessoryLTSK.sign(accessoryPairingInfo)

        # Step 5
        response = []
        response.append({
            'type': 'identifier',
            'length': len(accessoryPairingID),
            'data': accessoryPairingID
        })
        response.append({
            'type': 'signature',
            'length': len(accessorySignature),
            'data': accessorySignature
        })
        subTLV = pack(response)  # tlv

        # Step 6
        inputKey = shared
        salt = 'Pair-Verify-Encrypt-Salt'
        info = 'Pair-Verify-Encrypt-Info'

        key = Hkdf(salt, inputKey, hash=hashlib.sha512)
        sessionKey = key.expand(info, length=32)

        key = Hkdf('Control-Salt', shared, hash=hashlib.sha512)
        writeKey = key.expand('Control-Write-Encryption-Key', length=32)

        key = Hkdf('Control-Salt', shared, hash=hashlib.sha512)
        readKey = key.expand('Control-Read-Encryption-Key', length=32)

        self.sessionStorage = {
            'clientPublicKey': iosDevicePublicKey.serialize(),
            'secretKey': private.serialize(),
            'publicKey': publicSerialized,
            'sharedSec': shared,
            'hkdfPairEncKey': sessionKey,
            'writeKey': writeKey,
            'readKey': readKey
        }

        # Step 7
        ciphertext, mac = HapHandler.encryptAndSeal(sessionKey, 'PV-Msg02',
                                                    [ord(x) for x in subTLV])

        self.sendTLVResponse([
            {
                'type': 'state',
                'length': 1,
                'data': 2
            },
            {
                'type': 'public_key',
                'length': len(publicSerialized),
                'data': publicSerialized
            },
            {
                'type': 'encrypted_data',
                'length': len(ciphertext + mac),
                'data': ciphertext + mac
            },
        ])
Beispiel #27
0
            print 'Bob ephemeral public:   ' + key['bob'].serialize().encode('hex')
        if 'message_key' in key:
            print 'Shared key:             ' + key['message_key'].encode('hex')
        if 'chaff_key' in key:
            print 'Chaff key:              ' + key['chaff_key'].encode('hex')
        if 'exchange_key' in key:
            print 'Exchange shared key:    ' + key['exchange_key'].encode('hex')
        if 'exchange_chaff_key' in key:
            print 'Exchange chaff key:     ' + key['exchange_chaff_key'].encode('hex')
        if 'counter' in key:
            print 'Counter:                %d' % key['counter']

        print ''

if __name__ == "__main__":
    alice_key = curve25519.Private()
    bob_key = curve25519.Private()

    alice = Chats(alice_key, bob_key.get_public(), 400, 8, debug=False)
    bob = Chats(bob_key, alice_key.get_public(), 400, 8, debug=False)

    ct = alice.encrypt_initial_keyx()
    msg = bob.decrypt_msg(ct)
    alice.decrypt_msg(msg['keyx'])

    print '\nAlice -> Bob initial: '
    ct = alice.encrypt_msg('ayy lmaoayy lmao')
    msg = bob.decrypt_msg(ct)
    if msg['keyx']: alice.decrypt_msg(msg['keyx'])
    print 'Plaintext: %s' % msg['msg']