Esempio n. 1
0
def test_okp_key_construction(crv):
    key = OKPKey(crv=crv, x=os.urandom(32), d=os.urandom(32), optional_params={'ALG': 'EDDSA'})

    assert _is_valid_okp_key(key)

    serialized = key.encode()
    _ = CoseKey.decode(serialized)
def test_set_curve_in_key():
    with pytest.raises(CoseException) as excinfo:
        key = OKPKey(crv='Ed25519', d=os.urandom(32))

    assert "Unknown COSE header or key attribute" in str(excinfo)

    key = OKPKey(crv='ED25519', d=os.urandom(32))
    assert key.crv == Ed25519
Esempio n. 3
0
def setup_dh_key(selected_cipher: int, private_bytes: bytes):
    if CipherSuite.from_id(selected_cipher).dh_curve in [X448, X25519]:
        return OKPKey(d=private_bytes, crv=CipherSuite.from_id(selected_cipher).dh_curve)
    elif CipherSuite.from_id(selected_cipher).dh_curve in [P256]:
        return EC2Key(d=private_bytes, crv=CipherSuite.from_id(selected_cipher).sign_curve)
    else:
        raise ValueError("Illegal DH keys.")
Esempio n. 4
0
def test_fail_on_illegal_kty(crv, kty):
    params = {KpKty: kty}

    with pytest.raises(CoseIllegalKeyType) as excinfo:
        _ = OKPKey(crv=crv, x=os.urandom(32), d=os.urandom(32), optional_params=params)

    assert "Illegal key type in OKP COSE Key" in str(excinfo.value)
Esempio n. 5
0
    def remote_pubkey(self) -> RPK:
        """ Returns the remote ephemeral public key. """

        if self.cipher_suite.dh_curve in [X448, X25519]:
            return OKPKey(x=self.g_y, crv=self.cipher_suite.dh_curve)
        else:
            return EC2Key(x=self.g_y, crv=self.cipher_suite.dh_curve)
Esempio n. 6
0
def test_responder_message2(responder, test_vectors):
    responder.msg_1 = MessageOne.decode(test_vectors['S']['message_1'])

    hash_func = CipherSuite.from_id(
        responder.msg_1.selected_cipher).hash.hash_cls
    crv = CipherSuite.from_id(responder.msg_1.selected_cipher).dh_curve

    assert responder.shared_secret(
        responder.ephemeral_key, OKPKey(x=responder.g_x,
                                        crv=crv)) == test_vectors['S']['g_xy']
    assert responder._prk2e == test_vectors['S']['prk_2e']
    assert responder._prk3e2m == test_vectors['S']['prk_3e2m']
    assert responder.data_2 == test_vectors['S']['data_2']
    assert responder._th2_input == test_vectors['S']['input_th_2']
    assert responder.cred_id == cbor2.loads(test_vectors['R']['cred_id'])
    assert responder.transcript(
        hash_func, responder._th2_input) == test_vectors['S']['th_2']
    assert responder._hkdf2(
        16, 'K_2m', prk=responder._prk3e2m) == test_vectors['S']['k_2m']
    assert responder._hkdf2(
        13, 'IV_2m', prk=responder._prk3e2m) == test_vectors['S']['iv_2m']
    assert responder._mac(responder._hkdf2, 'K_2m', 16, 'IV_2m', 13,
                          responder._th2_input, responder._prk3e2m,
                          responder.aad2_cb) == test_vectors['S']['mac_2']
    assert responder.signature_or_mac2(
        test_vectors['S']['mac_2']) == test_vectors['S']['signature_2']
    assert responder._p_2e == test_vectors['S']['p_2e']
    assert responder._hkdf2(
        len(responder._p_2e), 'KEYSTREAM_2',
        prk=responder._prk2e) == test_vectors['S']['keystream_2']
    assert responder.ciphertext_2 == test_vectors['S']['ciphertext_2']

    assert responder.create_message_two(
        test_vectors['S']['message_1']) == test_vectors['S']['message_2']
Esempio n. 7
0
def test_okp_key_generation_encoding_decoding(crv):
    trails = 256

    for i in range(trails):
        okp_test = OKPKey.generate_key(crv=crv)
        okp_encoded = okp_test.encode()
        okp_decoded = CoseKey.decode(okp_encoded)
        assert _is_valid_okp_key(okp_decoded)
Esempio n. 8
0
    def local_pubkey(self) -> RPK:
        """ Returns the local ephemeral public key. """

        if self.cipher_suite.dh_curve in [X448, X25519]:
            return OKPKey(x=self.g_x, crv=self.cipher_suite.dh_curve)
        else:
            # TODO:
            pass
Esempio n. 9
0
    def remote_pubkey(self) -> RPK:
        """ Returns the remote ephemeral public key. """

        if self.cipher_suite.dh_curve in [X448, X25519]:
            return OKPKey(x=self.g_x, crv=self.cipher_suite.dh_curve)
        else:
            # TODO: implement NIST curves
            pass
Esempio n. 10
0
    def local_pubkey(self) -> RPK:
        """ Returns the local ephemeral public key. """

        # Is this a good criterion? (Possibly there doesn't need to be a
        # distinction; self.cipher_suite.dh_curve.keyclass(...) could do)
        if self.cipher_suite.dh_curve in [X448, X25519]:
            return OKPKey(x=self.g_y, crv=self.cipher_suite.dh_curve)
        else:
            return EC2Key(x=self.g_y, crv=self.cipher_suite.dh_curve)
Esempio n. 11
0
def setup_sign_key(selected_cipher: int, private_bytes: bytes):
    if CipherSuite.from_id(selected_cipher).sign_curve in [Ed448, Ed25519]:
        return OKPKey(d=private_bytes,
                      crv=CipherSuite.from_id(selected_cipher).sign_curve,
                      optional_params={KpAlg: CipherSuite.from_id(selected_cipher).sign_alg})
    elif CipherSuite.from_id(selected_cipher).sign_alg == Es256:
        return EC2Key(d=private_bytes, alg=Es256, crv=CipherSuite.from_id(selected_cipher).sign_curve)
    else:
        raise ValueError("Illegal COSE curve.")
Esempio n. 12
0
def test_key_ops_setter_getter():
    key = OKPKey.generate_key('ED25519')
    key.key_ops = [SignOp]

    assert SignOp in key.key_ops

    with pytest.raises(CoseIllegalKeyOps) as excinfo:
        key.key_ops = [MacVerifyOp]

    assert "Invalid COSE key operation" in str(excinfo)
Esempio n. 13
0
    def __init__(self, cred_idr, cred, auth_key):
        super().__init__()
        # test with static connection identifier and static ephemeral key

        self.ephemeral_key = OKPKey(
            crv=X25519,
            x=unhexlify("71a3d599c21da18902a1aea810b2b6382ccd8d5f9bf0195281754c5ebcaf301e"),
            d=unhexlify("fd8cd877c9ea386e6af34ff7e606c4b64ca831c8ba33134fd4cd7167cabaecda"))

        self.cred_idr = cred_idr
        self.cred = cred
        self.auth_key = auth_key
        self.supported = [CipherSuite0, CipherSuite1]

        self.resp = self.create_responder()
Esempio n. 14
0
    def _generate_ephemeral_key(self) -> None:
        """
        Generate a new ephemeral key if the key was not already set.

        :return: None
        """

        if self.ephemeral_key is not None:
            return

        chosen_suite = CipherSuite.from_id(self.cipher_suite)

        if chosen_suite.dh_curve in [X25519, X448]:
            self.ephemeral_key = OKPKey.generate_key(crv=chosen_suite.dh_curve)
        else:
            self.ephemeral_key = EC2Key.generate_key(crv=chosen_suite.dh_curve)
Esempio n. 15
0
def test_initiator_message3(initiator, test_vectors):
    initiator.msg_1 = MessageOne.decode(test_vectors['S']['message_1'])
    initiator.msg_2 = MessageTwo.decode(test_vectors['S']['message_2'])

    crv = CipherSuite.from_id(initiator._selected_cipher).dh_curve
    hash_func = CipherSuite.from_id(initiator._selected_cipher).hash.hash_cls

    assert initiator.data_2 == test_vectors['S']['data_2']
    assert initiator._th2_input == test_vectors['S']['input_th_2']
    assert initiator._prk2e == test_vectors['S']['prk_2e']
    assert initiator._prk3e2m == test_vectors['S']['prk_3e2m']
    assert initiator.transcript(hash_func, initiator._th2_input) == test_vectors['S']['th_2']

    assert initiator._decrypt(initiator.msg_2.ciphertext) == test_vectors['S']['p_2e']

    assert initiator.shared_secret(initiator.ephemeral_key, OKPKey(x=initiator.g_y, crv=crv)) == test_vectors['S'][
        'g_xy']
    assert initiator.data_3 == test_vectors['S']['data_3']
    assert initiator._th3_input == test_vectors['S']['input_th_3']
    assert initiator.transcript(hash_func, initiator._th3_input) == test_vectors['S']['th_3']
    assert initiator.cred_id == cbor2.loads(test_vectors['I']['cred_id'])
    assert initiator._prk4x3m == test_vectors['S']['prk_4x3m']
    assert initiator._hkdf3(16, 'K_3m', initiator._prk4x3m) == test_vectors['S']['k_3m']
    assert initiator._hkdf3(13, 'IV_3m', initiator._prk4x3m) == test_vectors['S']['iv_3m']
    assert initiator._mac(
        initiator.cred_idi,
        initiator.cred,
        initiator._hkdf3,
        'K_3m',
        16,
        'IV_3m',
        13,
        initiator._th3_input,
        initiator._prk4x3m,
        initiator.aad2_cb) == test_vectors['S']['mac_3']
    assert initiator.signature_or_mac3(test_vectors['S']['mac_3']) == test_vectors['S']['signature_3']
    assert initiator._p_3ae == test_vectors['S']['p_3ae']
    assert initiator._hkdf3(16, 'K_3ae', initiator._prk3e2m) == test_vectors['S']['k_3ae']
    assert initiator._hkdf3(13, 'IV_3ae', initiator._prk3e2m) == test_vectors['S']['iv_3ae']
    assert initiator.ciphertext_3 == test_vectors['S']['ciphertext_3']

    if initiator.remote_authkey is None:
        warnings.warn(NoRemoteKey())
        return
    assert initiator.create_message_three(test_vectors['S']['message_2']) == test_vectors['S']['message_3']
Esempio n. 16
0
def ephemeral_responder_key(test_vectors):
    return OKPKey(
        x=test_vectors['R']['g_y'],
        d=test_vectors['R']['y'],
        crv=CipherSuite.from_id(test_vectors['I']['selected']).dh_curve)
Esempio n. 17
0
async def main():
    parser = argparse.ArgumentParser()

    # 51.75.194.248
    parser.add_argument("ip", help="IP address of EDHOC responder", type=str)
    parser.add_argument("--epk",
                        help="Use a preset ephemeral key",
                        action="store_true")

    args = parser.parse_args()

    context = await Context.create_client_context()

    supported = [CipherSuite0]

    if args.epk:
        ephemeral_key = OKPKey(
            crv=X25519,
            x=unhexlify(
                "898ff79a02067a16ea1eccb90fa52246f5aa4dd6ec076bba0259d904b7ec8b0c"
            ),
            d=unhexlify(
                "8f781a095372f85b6d9f6109ae422611734d7dbfa0069a2df2935bb2e053bf35"
            ))
    else:
        ephemeral_key = None

    init = Initiator(corr=Correlation.CORR_1,
                     method=Method.SIGN_SIGN,
                     conn_idi=unhexlify(b''),
                     cred_idi=cred_id_initiator,
                     auth_key=initiator_authkey,
                     cred=initiator_cert,
                     remote_cred_cb=get_peer_cred,
                     supported_ciphers=supported,
                     selected_cipher=CipherSuite0,
                     ephemeral_key=ephemeral_key)

    msg_1 = init.create_message_one()
    # assert msg_1 == unhexlify(b"01005820898ff79a02067a16ea1eccb90fa52246f5aa4dd6ec076bba0259d904b7ec8b0c40")

    request = Message(code=Code.POST,
                      payload=msg_1,
                      uri=f"coap://[{args.ip}]/.well-known/edhoc")

    logging.info("POST (%s)  %s", init.edhoc_state, request.payload)
    response = await context.request(request).response

    logging.info("CHANGED (%s)  %s", init.edhoc_state, response.payload)
    msg_3 = init.create_message_three(response.payload)
    # assert msg_3 == unhexlify(_msg_3)

    logging.info("POST (%s)  %s", init.edhoc_state, request.payload)
    request = Message(code=Code.POST,
                      payload=msg_3,
                      uri=f"coap://[{args.ip}]/.well-known/edhoc")
    response = await context.request(request).response

    conn_idi, conn_idr, aead, hashf = init.finalize()

    logging.info('EDHOC key exchange successfully completed:')
    logging.info(f" - connection IDr: {conn_idr}")
    logging.info(f" - connection IDi: {conn_idi}")
    logging.info(f" - aead algorithm: {aead}")
    logging.info(f" - hash algorithm: {hashf}")

    logging.info(
        f" - OSCORE secret : {init.exporter('OSCORE Master Secret', 16)}")
    logging.info(
        f" - OSCORE salt   : {init.exporter('OSCORE Master Salt', 8)}")
Esempio n. 18
0
    def test(self):
        print('\nTest: ' + __name__ + '.' + type(self).__name__)
        private_key = OKPKey(
            crv=curves.Ed25519,
            x=binascii.unhexlify('64f38ea84b153c7be87349f78261ca46e90f1613a3ceb2ae02c010193631e07d'),
            d=binascii.unhexlify('6820977a9be08d676dac7ee19e1595d0552894ee2d71feb1d7b1d2a9f31754fd'),
            optional_params={
                keyparam.KpKid: b'ExampleEd25519',
                keyparam.KpKeyOps: [keyops.SignOp, keyops.VerifyOp],
            }
        )
        print('Private Key: {}'.format(encode_diagnostic(cbor2.loads(private_key.encode()))))

        # Primary block
        prim_dec = self._get_primary_item()
        prim_enc = cbor2.dumps(prim_dec)
        print('Primary Block: {}'.format(encode_diagnostic(prim_dec)))
        print('Encoded: {}'.format(encode_diagnostic(prim_enc)))

        # Security target block
        target_dec = self._get_target_item()
        target_enc = cbor2.dumps(target_dec)
        content_plaintext = target_dec[4]
        print('Target Block: {}'.format(encode_diagnostic(target_dec)))
        print('Plaintext: {}'.format(encode_diagnostic(content_plaintext)))

        # Combined AAD
        ext_aad_dec = self._get_aad_item()
        ext_aad_enc = cbor2.dumps(ext_aad_dec)
        print('External AAD: {}'.format(encode_diagnostic(ext_aad_dec)))
        print('Encoded: {}'.format(encode_diagnostic(ext_aad_enc)))

        msg_obj = Sign1Message(
            phdr={
                headers.Algorithm: algorithms.EdDSA,
            },
            uhdr={
                headers.KID: private_key.kid,
            },
            payload=content_plaintext,
            # Non-encoded parameters
            external_aad=ext_aad_enc,
        )
        msg_obj.key = private_key

        # COSE internal structure
        cose_struct_enc = msg_obj._sig_structure
        cose_struct_dec = cbor2.loads(cose_struct_enc)
        print('COSE Structure: {}'.format(encode_diagnostic(cose_struct_dec)))
        print('Encoded: {}'.format(encode_diagnostic(cose_struct_enc)))

        # Encoded message
        message_enc = msg_obj.encode(tag=False)
        message_dec = cbor2.loads(message_enc)
        # Detach the payload
        content_signature = message_dec[2]
        message_dec[2] = None
        self._print_message(message_dec, recipient_idx=4)
        message_enc = cbor2.dumps(message_dec)

        # ASB structure
        asb_dec = self._get_asb_item([
            msg_obj.cbor_tag,
            message_enc
        ])
        asb_enc = self._get_asb_enc(asb_dec)
        print('ASB: {}'.format(encode_diagnostic(asb_dec)))
        print('Encoded: {}'.format(encode_diagnostic(asb_enc)))

        bpsec_dec = self._get_bpsec_item(
            block_type=BlockType.BIB,
            asb_dec=asb_dec,
        )
        bpsec_enc = cbor2.dumps(bpsec_dec)
        print('BPSec block: {}'.format(encode_diagnostic(bpsec_dec)))
        print('Encoded: {}'.format(encode_diagnostic(bpsec_enc)))

        # Change from detached payload
        message_dec[2] = content_signature
        decode_obj = Sign1Message.from_cose_obj(message_dec)
        decode_obj.external_aad = ext_aad_enc
        decode_obj.key = private_key

        verify_valid = decode_obj.verify_signature()
        self.assertTrue(verify_valid)
        print('Loopback verify:', verify_valid)

        bundle = self._assemble_bundle([prim_enc, bpsec_enc, target_enc])
        print('Total bundle: {}'.format(encode_diagnostic(bundle)))
Esempio n. 19
0
def test_fail_on_missing_key_values(crv):
    with pytest.raises(CoseInvalidKey) as excinfo:
        _ = OKPKey(crv=crv)

    assert "Either the public values or the private value must be specified" in str(excinfo.value)
Esempio n. 20
0
def test_okp_key_generation(crv):
    key = OKPKey.generate_key(crv)

    assert _is_valid_okp_key(key)
Esempio n. 21
0
def test_key_generation_with_optional_parameters():
    key = OKPKey.generate_key(crv='ED25519', optional_params={'KpKid': 4})
Esempio n. 22
0
def ephemeral_initiator_key(test_vectors):
    return OKPKey(
        x=test_vectors['I']['g_x'],
        d=test_vectors['I']['x'],
        crv=CipherSuite.from_id(test_vectors['I']['selected']).dh_curve)
Esempio n. 23
0
with open("responder-cert.pem", "rb") as f:
    c = b"".join(f.readlines())

responder_cert = x509.load_pem_x509_certificate(c)

cert_hash = X5T.from_certificate(Sha256Trunc64, responder_cert.tbs_certificate_bytes).encode()
cred_id_responder = {headers.X5t: cert_hash}

with open("responder-authkey.pem", "rb") as f:
    k = b"".join(f.readlines())

key = load_pem_private_key(k, password=None)

responder_authkey = OKPKey(crv=Ed25519,
                           d=key.private_bytes(serialization.Encoding.Raw,
                                               serialization.PrivateFormat.Raw,
                                               serialization.NoEncryption()),
                           x=key.public_key().public_bytes(serialization.Encoding.Raw,
                                                           serialization.PublicFormat.Raw))


class EdhocResponder(resource.Resource):

    def __init__(self, cred_idr, cred, auth_key):
        super().__init__()
        # test with static connection identifier and static ephemeral key

        self.ephemeral_key = OKPKey(
            crv=X25519,
            x=unhexlify("71a3d599c21da18902a1aea810b2b6382ccd8d5f9bf0195281754c5ebcaf301e"),
            d=unhexlify("fd8cd877c9ea386e6af34ff7e606c4b64ca831c8ba33134fd4cd7167cabaecda"))