1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 14:58:09 +00:00

modtrezorcrypto: add generate_secret methods to curves

This commit is contained in:
Pavol Rusnak 2016-10-24 12:08:12 +02:00
parent 3c5c685b8c
commit 9c921c073f
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
8 changed files with 113 additions and 6 deletions

View File

@ -9,6 +9,8 @@
#include "trezor-crypto/curve25519-donna/curve25519-donna.h" #include "trezor-crypto/curve25519-donna/curve25519-donna.h"
#include "rand.h"
typedef struct _mp_obj_Curve25519_t { typedef struct _mp_obj_Curve25519_t {
mp_obj_base_t base; mp_obj_base_t base;
} mp_obj_Curve25519_t; } mp_obj_Curve25519_t;
@ -20,6 +22,22 @@ STATIC mp_obj_t mod_TrezorCrypto_Curve25519_make_new(const mp_obj_type_t *type,
return MP_OBJ_FROM_PTR(o); return MP_OBJ_FROM_PTR(o);
} }
/// def trezor.crypto.curve.curve25519.generate_secret() -> bytes:
/// '''
/// Generate secret key.
/// '''
STATIC mp_obj_t mod_TrezorCrypto_Curve25519_generate_secret(mp_obj_t self) {
vstr_t vstr;
vstr_init_len(&vstr, 32);
random_buffer((uint8_t *)vstr.buf, 32);
// taken from https://cr.yp.to/ecdh.html
vstr.buf[0] &= 248;
vstr.buf[31] &= 127;
vstr.buf[31] |= 64;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Curve25519_generate_secret_obj, mod_TrezorCrypto_Curve25519_generate_secret);
/// def trezor.crypto.curve.curve25519.publickey(secret_key: bytes) -> bytes: /// def trezor.crypto.curve.curve25519.publickey(secret_key: bytes) -> bytes:
/// ''' /// '''
/// Computes public key from secret key. /// Computes public key from secret key.
@ -60,6 +78,7 @@ STATIC mp_obj_t mod_TrezorCrypto_Curve25519_multiply(mp_obj_t self, mp_obj_t sec
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Curve25519_multiply_obj, mod_TrezorCrypto_Curve25519_multiply); STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Curve25519_multiply_obj, mod_TrezorCrypto_Curve25519_multiply);
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Curve25519_locals_dict_table[] = { STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Curve25519_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_TrezorCrypto_Curve25519_generate_secret_obj) },
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Curve25519_publickey_obj) }, { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Curve25519_publickey_obj) },
{ MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_TrezorCrypto_Curve25519_multiply_obj) }, { MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_TrezorCrypto_Curve25519_multiply_obj) },
}; };

View File

@ -9,6 +9,8 @@
#include "trezor-crypto/ed25519-donna/ed25519.h" #include "trezor-crypto/ed25519-donna/ed25519.h"
#include "rand.h"
typedef struct _mp_obj_Ed25519_t { typedef struct _mp_obj_Ed25519_t {
mp_obj_base_t base; mp_obj_base_t base;
} mp_obj_Ed25519_t; } mp_obj_Ed25519_t;
@ -20,6 +22,22 @@ STATIC mp_obj_t mod_TrezorCrypto_Ed25519_make_new(const mp_obj_type_t *type, siz
return MP_OBJ_FROM_PTR(o); return MP_OBJ_FROM_PTR(o);
} }
/// def trezor.crypto.curve.ed25519.generate_secret() -> bytes:
/// '''
/// Generate secret key.
/// '''
STATIC mp_obj_t mod_TrezorCrypto_Ed25519_generate_secret(mp_obj_t self) {
vstr_t vstr;
vstr_init_len(&vstr, 32);
random_buffer((uint8_t *)vstr.buf, 32);
// taken from https://cr.yp.to/ecdh.html
vstr.buf[0] &= 248;
vstr.buf[31] &= 127;
vstr.buf[31] |= 64;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Ed25519_generate_secret_obj, mod_TrezorCrypto_Ed25519_generate_secret);
/// def trezor.crypto.curve.ed25519.publickey(secret_key: bytes) -> bytes: /// def trezor.crypto.curve.ed25519.publickey(secret_key: bytes) -> bytes:
/// ''' /// '''
/// Computes public key from secret key. /// Computes public key from secret key.
@ -84,6 +102,7 @@ STATIC mp_obj_t mod_TrezorCrypto_Ed25519_verify(size_t n_args, const mp_obj_t *a
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_TrezorCrypto_Ed25519_verify_obj, 4, 4, mod_TrezorCrypto_Ed25519_verify); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_TrezorCrypto_Ed25519_verify_obj, 4, 4, mod_TrezorCrypto_Ed25519_verify);
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Ed25519_locals_dict_table[] = { STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Ed25519_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_generate_secret_obj) },
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_publickey_obj) }, { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_publickey_obj) },
{ MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_sign_obj) }, { MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_sign_obj) },
{ MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_verify_obj) }, { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_verify_obj) },

View File

@ -21,6 +21,24 @@ STATIC mp_obj_t mod_TrezorCrypto_Nist256p1_make_new(const mp_obj_type_t *type, s
return MP_OBJ_FROM_PTR(o); return MP_OBJ_FROM_PTR(o);
} }
/// def trezor.crypto.curve.nist256p1.generate_secret() -> bytes:
/// '''
/// Generate secret key.
/// '''
STATIC mp_obj_t mod_TrezorCrypto_Nist256p1_generate_secret(mp_obj_t self) {
vstr_t vstr;
vstr_init_len(&vstr, 32);
for (;;) {
random_buffer((uint8_t *)vstr.buf, 32);
// check whether secret > 0 && secret < curve_order
if (0 == memcmp(vstr.buf, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) continue;
if (0 <= memcmp(vstr.buf, "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32)) continue;
break;
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Nist256p1_generate_secret_obj, mod_TrezorCrypto_Nist256p1_generate_secret);
/// def trezor.crypto.curve.nist256p1.publickey(secret_key: bytes, compressed: bool=True) -> bytes: /// def trezor.crypto.curve.nist256p1.publickey(secret_key: bytes, compressed: bool=True) -> bytes:
/// ''' /// '''
/// Computes public key from secret key. /// Computes public key from secret key.
@ -117,6 +135,7 @@ STATIC mp_obj_t mod_TrezorCrypto_Nist256p1_multiply(mp_obj_t self, mp_obj_t secr
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Nist256p1_multiply_obj, mod_TrezorCrypto_Nist256p1_multiply); STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Nist256p1_multiply_obj, mod_TrezorCrypto_Nist256p1_multiply);
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Nist256p1_locals_dict_table[] = { STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Nist256p1_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_generate_secret_obj) },
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_publickey_obj) }, { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_publickey_obj) },
{ MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_sign_obj) }, { MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_sign_obj) },
{ MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_verify_obj) }, { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_verify_obj) },

View File

@ -21,6 +21,24 @@ STATIC mp_obj_t mod_TrezorCrypto_Secp256k1_make_new(const mp_obj_type_t *type, s
return MP_OBJ_FROM_PTR(o); return MP_OBJ_FROM_PTR(o);
} }
/// def trezor.crypto.curve.secp256k1.generate_secret() -> bytes:
/// '''
/// Generate secret key.
/// '''
STATIC mp_obj_t mod_TrezorCrypto_Secp256k1_generate_secret(mp_obj_t self) {
vstr_t vstr;
vstr_init_len(&vstr, 32);
for (;;) {
random_buffer((uint8_t *)vstr.buf, 32);
// check whether secret > 0 && secret < curve_order
if (0 == memcmp(vstr.buf, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) continue;
if (0 <= memcmp(vstr.buf, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41", 32)) continue;
break;
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Secp256k1_generate_secret_obj, mod_TrezorCrypto_Secp256k1_generate_secret);
/// def trezor.crypto.curve.secp256k1.publickey(secret_key: bytes, compressed: bool=True) -> bytes: /// def trezor.crypto.curve.secp256k1.publickey(secret_key: bytes, compressed: bool=True) -> bytes:
/// ''' /// '''
/// Computes public key from secret key. /// Computes public key from secret key.
@ -117,6 +135,7 @@ STATIC mp_obj_t mod_TrezorCrypto_Secp256k1_multiply(mp_obj_t self, mp_obj_t secr
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Secp256k1_multiply_obj, mod_TrezorCrypto_Secp256k1_multiply); STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_TrezorCrypto_Secp256k1_multiply_obj, mod_TrezorCrypto_Secp256k1_multiply);
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Secp256k1_locals_dict_table[] = { STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Secp256k1_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_generate_secret_obj) },
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_publickey_obj) }, { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_publickey_obj) },
{ MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_sign_obj) }, { MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_sign_obj) },
{ MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_verify_obj) }, { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_verify_obj) },

View File

@ -5,7 +5,6 @@ import unittest
from ubinascii import unhexlify from ubinascii import unhexlify
from trezor.crypto.curve import curve25519 from trezor.crypto.curve import curve25519
from trezor.crypto import random
class TestCryptoCurve25519(unittest.TestCase): class TestCryptoCurve25519(unittest.TestCase):
@ -13,6 +12,12 @@ class TestCryptoCurve25519(unittest.TestCase):
('38c9d9b17911de26ed812f5cc19c0029e8d016bcbc6078bc9db2af33f1761e4a', '311b6248af8dabec5cc81eac5bf229925f6d218a12e0547fb1856e015cc76f5d', 'a93dbdb23e5c99da743e203bd391af79f2b83fb8d0fd6ec813371c71f08f2d4d'), ('38c9d9b17911de26ed812f5cc19c0029e8d016bcbc6078bc9db2af33f1761e4a', '311b6248af8dabec5cc81eac5bf229925f6d218a12e0547fb1856e015cc76f5d', 'a93dbdb23e5c99da743e203bd391af79f2b83fb8d0fd6ec813371c71f08f2d4d'),
] ]
def test_generate_secret(self):
for _ in range(100):
sk = curve25519.generate_secret()
self.assertTrue(len(sk) == 32)
self.assertTrue(sk[0] & 7 == 0 and sk[31] & 128 == 0 and sk[31] & 64 == 64)
def test_multiply(self): def test_multiply(self):
for sk, pk, session in self.vectors: for sk, pk, session in self.vectors:
session2 = curve25519.multiply(unhexlify(sk), unhexlify(pk)) session2 = curve25519.multiply(unhexlify(sk), unhexlify(pk))
@ -20,11 +25,8 @@ class TestCryptoCurve25519(unittest.TestCase):
def test_multiply_random(self): def test_multiply_random(self):
for _ in range(100): for _ in range(100):
sk1 = bytearray(random.bytes(32)) sk1 = curve25519.generate_secret()
sk2 = bytearray(random.bytes(32)) sk2 = curve25519.generate_secret()
# taken from https://cr.yp.to/ecdh.html
sk1[0] &= 248 ; sk1[31] &= 127 ; sk1[31] |= 64
sk2[0] &= 248 ; sk2[31] &= 127 ; sk2[31] |= 64
pk1 = curve25519.publickey(sk1) pk1 = curve25519.publickey(sk1)
pk2 = curve25519.publickey(sk2) pk2 = curve25519.publickey(sk2)
session1 = curve25519.multiply(sk1, pk2) session1 = curve25519.multiply(sk1, pk2)

View File

@ -5,6 +5,7 @@ import unittest
from ubinascii import unhexlify from ubinascii import unhexlify
from trezor.crypto.curve import ed25519 from trezor.crypto.curve import ed25519
from trezor.crypto import random
class TestCryptoEd25519(unittest.TestCase): class TestCryptoEd25519(unittest.TestCase):
@ -36,5 +37,19 @@ class TestCryptoEd25519(unittest.TestCase):
self.assertTrue(ed25519.verify(unhexlify(pk), unhexlify(sig), unhexlify(pk))) self.assertTrue(ed25519.verify(unhexlify(pk), unhexlify(sig), unhexlify(pk)))
pass pass
def test_generate_secret(self):
for _ in range(100):
sk = ed25519.generate_secret()
self.assertTrue(len(sk) == 32)
self.assertTrue(sk[0] & 7 == 0 and sk[31] & 128 == 0 and sk[31] & 64 == 64)
def test_random(self):
for l in range(1, 300):
sk = ed25519.generate_secret()
pk = ed25519.publickey(sk)
msg = random.bytes(l)
sig = ed25519.sign(sk, msg)
self.assertTrue(ed25519.verify(pk, sig, msg))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -64,6 +64,13 @@ class TestCryptoNist256p1(unittest.TestCase):
(115792089210356248762697446949407573529996955224135760342422259061068512044368, '6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A'), (115792089210356248762697446949407573529996955224135760342422259061068512044368, '6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A'),
] ]
def test_generate_secret(self):
for _ in range(100):
sk = nist256p1.generate_secret()
self.assertTrue(len(sk) == 32)
self.assertTrue(sk != b'\x00' * 32)
self.assertTrue(sk < b'\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51')
def test_publickey(self): def test_publickey(self):
for sk, pk in self.vectors: for sk, pk in self.vectors:
sk = hex(sk)[2:] sk = hex(sk)[2:]

View File

@ -57,6 +57,13 @@ class TestCryptoSecp256k1(unittest.TestCase):
(115792089237316195423570985008687907852837564279074904382605163141518161494336, '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777'), (115792089237316195423570985008687907852837564279074904382605163141518161494336, '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777'),
] ]
def test_generate_secret(self):
for _ in range(100):
sk = secp256k1.generate_secret()
self.assertTrue(len(sk) == 32)
self.assertTrue(sk != b'\x00' * 32)
self.assertTrue(sk < b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41')
def test_publickey(self): def test_publickey(self):
for sk, pk in self.vectors: for sk, pk in self.vectors:
sk = hex(sk)[2:] sk = hex(sk)[2:]