def test_publickey(self):
     for sk, pk in self.vectors:
         sk = hex(sk)[2:]
         if len(sk) < 64:
             sk = '0' * (64 - len(sk)) + sk
         pk = pk.lower()
         pk65 = hexlify(nist256p1.publickey(unhexlify(sk), False)).decode(
             'ascii')  # uncompressed
         self.assertEqual(str(pk65), '04' + pk)
         pk33 = hexlify(nist256p1.publickey(unhexlify(sk))).decode('ascii')
         if pk[-1] in '02468ace':
             self.assertEqual(pk33, '02' + pk[:64])
         else:
             self.assertEqual(pk33, '03' + pk[:64])
 def test_sign_verify_random(self):
     for _ in range(100):
         sk = nist256p1.generate_secret()
         pk = nist256p1.publickey(sk)
         dig = random.bytes(32)
         sig = nist256p1.sign(sk, dig)
         self.assertTrue(nist256p1.verify(pk, sig, dig))
         self.assertTrue(nist256p1.verify(pk, sig[1:], dig))
 def test_verify_recover(self):
     for compressed in [False, True]:
         for _ in range(100):
             sk = nist256p1.generate_secret()
             pk = nist256p1.publickey(sk, compressed)
             dig = random.bytes(32)
             sig = nist256p1.sign(sk, dig, compressed)
             pk2 = nist256p1.verify_recover(sig, dig)
             self.assertEqual(pk, pk2)
Esempio n. 4
0
    def test_fido2_credential_decode(self):
        mnemonic_secret = b"all all all all all all all all all all all all"
        mnemonic.get_secret = lambda: mnemonic_secret
        storage.is_initialized = lambda: True

        cred_id = (
            b"f1d0020013e65c865634ad8abddf7a66df56ae7d8c3afd356f76426801508b2e"
            b"579bcb3496fe6396a6002e3cd6d80f6359dfa9961e24c544bfc2f26acec1b8d8"
            b"78ba56727e1f6a7b5176c607552aea63a5abe5d826d69fab3063edfa0201d9a5"
            b"1013d69eddb2eff37acdd5963f"
        )

        rp_id = "example.com"
        rp_id_hash = sha256(rp_id).digest()

        user_id = (
            b"3082019330820138a0030201023082019330820138a003020102308201933082"
        )

        user_name = "*****@*****.**"

        creation_time = 2

        public_key = (
            b"0451f0d4c307bc737c90ac605c6279f7d01e451798aa7b74df550fdb43a7760c"
            b"7c02b5107fef42094d00f52a9b1e90afb90e1b9decbf15a6f13d4f882de857e2"
            b"f4"
        )

        cred_random = (
            b"36a9b5d71c13ed54594474b54073af1fb03ea91cd056588909dae43ae2f35dbf"
        )

        # Load credential.
        cred = Fido2Credential.from_cred_id(unhexlify(cred_id), rp_id_hash)
        self.assertIsNotNone(cred)

        # Check credential data.
        self.assertEqual(hexlify(cred.id), cred_id)
        self.assertEqual(cred.rp_id, rp_id)
        self.assertEqual(cred.rp_id_hash, rp_id_hash)
        self.assertEqual(hexlify(cred.user_id), user_id)
        self.assertEqual(cred.user_name, user_name)
        self.assertEqual(cred.creation_time, creation_time)
        self.assertTrue(cred.hmac_secret)
        self.assertIsNone(cred.rp_name)
        self.assertIsNone(cred.user_display_name)

        # Check credential keys.
        self.assertEqual(hexlify(cred.hmac_secret_key()), cred_random)

        cred_public_key = nist256p1.publickey(cred.private_key(), False)
        self.assertEqual(hexlify(cred_public_key), public_key)
Esempio n. 5
0
def msg_register_sign(challenge: bytes, app_id: bytes) -> bytes:

    from apps.common import seed

    # derivation path is m/U2F'/r'/r'/r'/r'/r'/r'/r'/r'
    keypath = [0x80000000 | random.uniform(0xf0000000) for _ in range(0, 8)]
    nodepath = [_U2F_KEY_PATH] + keypath

    # prepare signing key from random path, compute decompressed public key
    node = seed.get_root_without_passphrase('nist256p1')
    node.derive_path(nodepath)
    pubkey = nist256p1.publickey(node.private_key(), False)

    # first half of keyhandle is keypath
    keybuf = ustruct.pack('>8L', *keypath)

    # second half of keyhandle is a hmac of app_id and keypath
    keybase = hmac.Hmac(node.private_key(), app_id, hashlib.sha256)
    keybase.update(keybuf)
    keybase = keybase.digest()

    # hash the request data together with keyhandle and pubkey
    dig = hashlib.sha256()
    dig.update(b'\x00')  # uint8_t reserved;
    dig.update(app_id)  # uint8_t appId[32];
    dig.update(challenge)  # uint8_t chal[32];
    dig.update(keybuf)  # uint8_t keyHandle[64];
    dig.update(keybase)
    dig.update(pubkey)  # uint8_t pubKey[65];
    dig = dig.digest()

    # sign the digest and convert to der
    sig = nist256p1.sign(_U2F_ATT_PRIV_KEY, dig, False)
    sig = der.encode_seq((sig[1:33], sig[33:]))

    # pack to a response
    buf, resp = make_struct(
        resp_cmd_register(
            len(keybuf) + len(keybase), len(_U2F_ATT_CERT), len(sig)))
    resp.registerId = _U2F_REGISTER_ID
    utils.memcpy(resp.pubKey, 0, pubkey, 0, len(pubkey))
    resp.keyHandleLen = len(keybuf) + len(keybase)
    utils.memcpy(resp.keyHandle, 0, keybuf, 0, len(keybuf))
    utils.memcpy(resp.keyHandle, len(keybuf), keybase, 0, len(keybase))
    utils.memcpy(resp.cert, 0, _U2F_ATT_CERT, 0, len(_U2F_ATT_CERT))
    utils.memcpy(resp.sig, 0, sig, 0, len(sig))
    resp.status = _SW_NO_ERROR

    return buf
    def test_sign_verify_min_max(self):
        sk = nist256p1.generate_secret()
        pk = nist256p1.publickey(sk)

        dig = bytes([1] + [0] * 31)
        sig = nist256p1.sign(sk, dig)
        self.assertTrue(nist256p1.verify(pk, sig, dig))
        self.assertTrue(nist256p1.verify(pk, sig[1:], dig))

        dig = bytes([0] * 31 + [1])
        sig = nist256p1.sign(sk, dig)
        self.assertTrue(nist256p1.verify(pk, sig, dig))
        self.assertTrue(nist256p1.verify(pk, sig[1:], dig))

        dig = bytes([0xFF] * 32)
        sig = nist256p1.sign(sk, dig)
        self.assertTrue(nist256p1.verify(pk, sig, dig))
        self.assertTrue(nist256p1.verify(pk, sig[1:], dig))
Esempio n. 7
0
 def public_key(self) -> bytes:
     if self.curve == common.COSE_CURVE_P256:
         pubkey = nist256p1.publickey(self._private_key(), False)
         return cbor.encode({
             common.COSE_KEY_ALG: self.algorithm,
             common.COSE_KEY_KTY: common.COSE_KEYTYPE_EC2,
             common.COSE_KEY_CRV: self.curve,
             common.COSE_KEY_X: pubkey[1:33],
             common.COSE_KEY_Y: pubkey[33:],
         })
     elif self.curve == common.COSE_CURVE_ED25519:
         pubkey = ed25519.publickey(self._private_key())
         return cbor.encode({
             common.COSE_KEY_ALG: self.algorithm,
             common.COSE_KEY_KTY: common.COSE_KEYTYPE_OKP,
             common.COSE_KEY_CRV: self.curve,
             common.COSE_KEY_X: pubkey,
         })
     raise TypeError
Esempio n. 8
0
 def public_key(self) -> bytes:
     return nist256p1.publickey(self._private_key(), False)