diff --git a/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h b/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h index 54dde28322..2cfa2f6b49 100644 --- a/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h +++ b/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h @@ -77,12 +77,12 @@ STATIC mp_obj_t mod_TrezorCrypto_Nist256p1_sign(mp_obj_t self, mp_obj_t secret_k mp_raise_ValueError("Invalid length of digest"); } vstr_t vstr; - vstr_init_len(&vstr, 64); + vstr_init_len(&vstr, 65); uint8_t pby; - if (0 != ecdsa_sign_digest(&nist256p1, (const uint8_t *)sk.buf, (const uint8_t *)dig.buf, (uint8_t *)vstr.buf, &pby, NULL)) { // TODO: is_canonical + if (0 != ecdsa_sign_digest(&nist256p1, (const uint8_t *)sk.buf, (const uint8_t *)dig.buf, (uint8_t *)vstr.buf + 1, &pby, NULL)) { // TODO: is_canonical mp_raise_ValueError("Signing failed"); } - (void)pby; + vstr.buf[0] = 27 + pby + 4; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Nist256p1_sign_obj, mod_TrezorCrypto_Nist256p1_sign); @@ -100,13 +100,14 @@ STATIC mp_obj_t mod_TrezorCrypto_Nist256p1_verify(size_t n_args, const mp_obj_t if (pk.len != 33 && pk.len != 65) { mp_raise_ValueError("Invalid length of public key"); } - if (sig.len != 64) { + if (sig.len != 64 && sig.len != 65) { mp_raise_ValueError("Invalid length of signature"); } + int offset = sig.len - 64; if (dig.len != 32) { mp_raise_ValueError("Invalid length of digest"); } - return mp_obj_new_bool(0 == ecdsa_verify_digest(&nist256p1, (const uint8_t *)pk.buf, (const uint8_t *)sig.buf, (const uint8_t *)dig.buf)); + return mp_obj_new_bool(0 == ecdsa_verify_digest(&nist256p1, (const uint8_t *)pk.buf, (const uint8_t *)sig.buf + offset, (const uint8_t *)dig.buf)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_TrezorCrypto_Nist256p1_verify_obj, 4, 4, mod_TrezorCrypto_Nist256p1_verify); diff --git a/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h b/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h index 9830a8f16d..45d98e12fe 100644 --- a/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h +++ b/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h @@ -77,12 +77,12 @@ STATIC mp_obj_t mod_TrezorCrypto_Secp256k1_sign(mp_obj_t self, mp_obj_t secret_k mp_raise_ValueError("Invalid length of digest"); } vstr_t vstr; - vstr_init_len(&vstr, 64); + vstr_init_len(&vstr, 65); uint8_t pby; - if (0 != ecdsa_sign_digest(&secp256k1, (const uint8_t *)sk.buf, (const uint8_t *)dig.buf, (uint8_t *)vstr.buf, &pby, NULL)) { // TODO: is_canonical + if (0 != ecdsa_sign_digest(&secp256k1, (const uint8_t *)sk.buf, (const uint8_t *)dig.buf, (uint8_t *)vstr.buf + 1, &pby, NULL)) { // TODO: is_canonical mp_raise_ValueError("Signing failed"); } - (void)pby; + vstr.buf[0] = 27 + pby + 4; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Secp256k1_sign_obj, mod_TrezorCrypto_Secp256k1_sign); @@ -100,13 +100,14 @@ STATIC mp_obj_t mod_TrezorCrypto_Secp256k1_verify(size_t n_args, const mp_obj_t if (pk.len != 33 && pk.len != 65) { mp_raise_ValueError("Invalid length of public key"); } - if (sig.len != 64) { + if (sig.len != 64 && sig.len != 65) { mp_raise_ValueError("Invalid length of signature"); } + int offset = sig.len - 64; if (dig.len != 32) { mp_raise_ValueError("Invalid length of digest"); } - return mp_obj_new_bool(0 == ecdsa_verify_digest(&secp256k1, (const uint8_t *)pk.buf, (const uint8_t *)sig.buf, (const uint8_t *)dig.buf)); + return mp_obj_new_bool(0 == ecdsa_verify_digest(&secp256k1, (const uint8_t *)pk.buf, (const uint8_t *)sig.buf + offset, (const uint8_t *)dig.buf)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_TrezorCrypto_Secp256k1_verify_obj, 4, 4, mod_TrezorCrypto_Secp256k1_verify); diff --git a/src/apps/common/signtx.py b/src/apps/common/signtx.py index cbb14cad8a..444b09d33f 100644 --- a/src/apps/common/signtx.py +++ b/src/apps/common/signtx.py @@ -328,7 +328,7 @@ def ecdsa_hash_pubkey(pubkey: bytes) -> bytes: def ecdsa_sign(node, digest: bytes) -> bytes: sig = secp256k1.sign(node.private_key(), digest) - sigder = der.encode_seq((sig[:32], sig[32:])) + sigder = der.encode_seq((sig[1:33], sig[33:65])) return sigder diff --git a/tests/test_trezor.crypto.curve.nist256p1.py b/tests/test_trezor.crypto.curve.nist256p1.py index 818202b4c7..e72cbd8917 100644 --- a/tests/test_trezor.crypto.curve.nist256p1.py +++ b/tests/test_trezor.crypto.curve.nist256p1.py @@ -90,14 +90,17 @@ class TestCryptoNist256p1(unittest.TestCase): 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)) def test_sign_verify_random(self): for _ in range(100): @@ -106,6 +109,7 @@ class TestCryptoNist256p1(unittest.TestCase): dig = random.bytes(32) sig = nist256p1.sign(sk, dig) self.assertTrue(nist256p1.verify(pk, sig, dig)) + self.assertTrue(nist256p1.verify(pk, sig[1:], dig)) if __name__ == '__main__': unittest.main()