def test_der_encode_decode_long_seq(self): for length in (1, 127, 128, 129, 255, 256, 257): raw_int = bytes((i & 0xfe) + 1 for i in range(length)) for leading_zeros in range(3): encoded = der.encode_seq((b"\x00" * leading_zeros + raw_int,)) decoded = der.decode_seq(encoded) self.assertEqual(decoded, [raw_int]) for zeroes in range(3): encoded = der.encode_seq((b"\x00" * zeroes,)) decoded = der.decode_seq(encoded) self.assertEqual(decoded, [b"\x00"])
def msg_authenticate_sign(challenge: bytes, app_id: bytes, privkey: bytes) -> bytes: flags = bytes([_AUTH_FLAG_TUP]) # get next counter ctr = storage.next_u2f_counter() ctrbuf = ustruct.pack(">L", ctr) # hash input data together with counter dig = hashlib.sha256() dig.update(app_id) # uint8_t appId[32]; dig.update(flags) # uint8_t flags; dig.update(ctrbuf) # uint8_t ctr[4]; dig.update(challenge) # uint8_t chal[32]; dig = dig.digest() # sign the digest and convert to der sig = nist256p1.sign(privkey, dig, False) sig = der.encode_seq((sig[1:33], sig[33:])) # pack to a response buf, resp = make_struct(resp_cmd_authenticate(len(sig))) resp.flags = flags[0] resp.ctr = ctr utils.memcpy(resp.sig, 0, sig, 0, len(sig)) resp.status = _SW_NO_ERROR return buf
def test_der_encode_seq(self): for s, d in self.vectors_seq: s = (unhexlify(i) for i in s) d = unhexlify(d) d2 = der.encode_seq(s) self.assertEqual(d, d2)
def test_der_encode_seq(self): for s, d in self.vectors_seq: s = tuple(unhexlify(i) for i in s) d = unhexlify(d) d2 = der.encode_seq(s) self.assertEqual(d2, d) s = [i.lstrip(b"\x00") for i in s] s2 = der.decode_seq(d) self.assertEqual(s2, s)
def bogus_signature(self) -> bytes: if (self.algorithm, self.curve) == ( common.COSE_ALG_ES256, common.COSE_CURVE_P256, ): return der.encode_seq((b"\x0a" * 32, b"\x0a" * 32)) elif (self.algorithm, self.curve) == ( common.COSE_ALG_EDDSA, common.COSE_CURVE_ED25519, ): return b"\x0a" * 64 raise TypeError
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 ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes: sig = secp256k1.sign(node.private_key(), digest) sigder = der.encode_seq((sig[1:33], sig[33:65])) return sigder
def ecdsa_sign(private_key: bytes, digest: bytes) -> bytes: """Signs and encodes signature into DER format""" signature = secp256k1.sign(private_key, digest) sig_der = der.encode_seq((signature[1:33], signature[33:65])) return sig_der
def _u2f_sign(self, data: Iterable[bytes]) -> bytes: dig = hashlib.sha256() for segment in data: dig.update(segment) sig = nist256p1.sign(self._private_key(), dig.digest(), False) return der.encode_seq((sig[1:33], sig[33:]))
def bogus_signature(self) -> bytes: return der.encode_seq((b"\x0a" * 32, b"\x0a" * 32))