new pbkdf2 api with update

This commit is contained in:
Pavol Rusnak 2016-05-01 02:03:31 +02:00
parent e1d9e96f15
commit b7b57ae53e
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
7 changed files with 192 additions and 64 deletions

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) Pavol Rusnak, SatoshiLabs
*
* Licensed under Microsoft Reference Source License (Ms-RSL)
* see LICENSE.md file for details
*/
#include "py/objstr.h"
#include "trezor-crypto/pbkdf2.h"
// class Pbkdf2(object):
typedef struct _mp_obj_Pbkdf2_t {
mp_obj_base_t base;
union {
PBKDF2_HMAC_SHA256_CTX ctx256;
PBKDF2_HMAC_SHA512_CTX ctx512;
};
int prf;
} mp_obj_Pbkdf2_t;
STATIC mp_obj_t mod_TrezorCrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t data);
// def Pbkdf2.__init__(self, prf: str, password: bytes, salt: bytes, iterations: int=None)
STATIC mp_obj_t mod_TrezorCrypto_Pbkdf2_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 3, 4, false);
mp_obj_Pbkdf2_t *o = m_new_obj(mp_obj_Pbkdf2_t);
o->base.type = type;
mp_buffer_info_t prf;
mp_get_buffer_raise(args[0], &prf, MP_BUFFER_READ);
mp_buffer_info_t password;
mp_get_buffer_raise(args[1], &password, MP_BUFFER_READ);
mp_buffer_info_t salt;
mp_get_buffer_raise(args[2], &salt, MP_BUFFER_READ);
o->prf = 0;
if (prf.len == 11 && memcmp(prf.buf, "hmac-sha256", prf.len) == 0) {
pbkdf2_hmac_sha256_Init(&(o->ctx256), password.buf, password.len, salt.buf, salt.len);
o->prf = 256;
} else
if (prf.len == 11 && memcmp(prf.buf, "hmac-sha512", prf.len) == 0) {
pbkdf2_hmac_sha512_Init(&(o->ctx512), password.buf, password.len, salt.buf, salt.len);
o->prf = 512;
} else
if (o->prf == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid PRF"));
}
// constructor called with iterations as fourth parameter
if (n_args > 3) {
mod_TrezorCrypto_Pbkdf2_update(MP_OBJ_FROM_PTR(o), args[3]);
}
return MP_OBJ_FROM_PTR(o);
}
// def Pbkdf2.update(self, iterations: int) -> None
STATIC mp_obj_t mod_TrezorCrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t iterations) {
mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self);
uint32_t iter = mp_obj_get_int(iterations);
if (o->prf == 256) {
pbkdf2_hmac_sha256_Update(&(o->ctx256), iter);
}
if (o->prf == 512) {
pbkdf2_hmac_sha512_Update(&(o->ctx512), iter);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Pbkdf2_update_obj, mod_TrezorCrypto_Pbkdf2_update);
// def Pbkdf2.key(self) -> bytes
STATIC mp_obj_t mod_TrezorCrypto_Pbkdf2_key(mp_obj_t self) {
mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self);
vstr_t vstr;
if (o->prf == 256) {
vstr_init_len(&vstr, SHA256_DIGEST_LENGTH);
memcpy(vstr.buf, o->ctx256.f, SHA256_DIGEST_LENGTH);
}
if (o->prf == 512) {
vstr_init_len(&vstr, SHA512_DIGEST_LENGTH);
memcpy(vstr.buf, o->ctx512.f, SHA512_DIGEST_LENGTH);
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Pbkdf2_key_obj, mod_TrezorCrypto_Pbkdf2_key);
// def Pbkdf2.__del__(self) -> None
STATIC mp_obj_t mod_TrezorCrypto_Pbkdf2___del__(mp_obj_t self) {
mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self);
memset(&(o->ctx256), 0, sizeof(PBKDF2_HMAC_SHA256_CTX));
memset(&(o->ctx512), 0, sizeof(PBKDF2_HMAC_SHA512_CTX));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Pbkdf2___del___obj, mod_TrezorCrypto_Pbkdf2___del__);
// Pbkdf2 stuff
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Pbkdf2_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_TrezorCrypto_Pbkdf2_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_key), MP_ROM_PTR(&mod_TrezorCrypto_Pbkdf2_key_obj) },
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_TrezorCrypto_Pbkdf2___del___obj) },
};
STATIC MP_DEFINE_CONST_DICT(mod_TrezorCrypto_Pbkdf2_locals_dict, mod_TrezorCrypto_Pbkdf2_locals_dict_table);
STATIC const mp_obj_type_t mod_TrezorCrypto_Pbkdf2_type = {
{ &mp_type_type },
.name = MP_QSTR_Pbkdf2,
.make_new = mod_TrezorCrypto_Pbkdf2_make_new,
.locals_dict = (void*)&mod_TrezorCrypto_Pbkdf2_locals_dict,
};

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) Pavol Rusnak, SatoshiLabs
*
* Licensed under Microsoft Reference Source License (Ms-RSL)
* see LICENSE.md file for details
*/
#include "py/objstr.h"
#include "trezor-crypto/pbkdf2.h"
// def pbkdf2_hmac(hash_name: str, password: bytes, salt: bytes, iterations: int, dklen:int=None) -> bytes
STATIC mp_obj_t mod_TrezorCrypto_pbkdf2_hmac(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t hash_name;
mp_get_buffer_raise(args[0], &hash_name, MP_BUFFER_READ);
mp_buffer_info_t password;
mp_get_buffer_raise(args[1], &password, MP_BUFFER_READ);
mp_buffer_info_t salt;
mp_get_buffer_raise(args[2], &salt, MP_BUFFER_READ);
mp_int_t iterations = mp_obj_get_int(args[3]);
mp_int_t dklen = (n_args > 4) ? mp_obj_get_int(args[4]) : 0;
int digestsize = 0;
if (hash_name.len == 6 && memcmp(hash_name.buf, "sha256", hash_name.len) == 0) {
digestsize = 32;
} else
if (hash_name.len == 6 && memcmp(hash_name.buf, "sha512", hash_name.len) == 0) {
digestsize = 64;
}
if (digestsize == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid hash_name"));
}
if (dklen == 0) {
dklen = digestsize;
}
vstr_t vstr;
vstr_init_len(&vstr, dklen);
if (digestsize == 32) {
pbkdf2_hmac_sha256(password.buf, password.len, salt.buf, salt.len, iterations, (uint8_t *)vstr.buf, dklen, NULL);
}
if (digestsize == 64) {
pbkdf2_hmac_sha512(password.buf, password.len, salt.buf, salt.len, iterations, (uint8_t *)vstr.buf, dklen, NULL);
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_TrezorCrypto_pbkdf2_hmac_obj, 4, 5, mod_TrezorCrypto_pbkdf2_hmac);

View File

@ -16,7 +16,7 @@
#if MICROPY_PY_TREZORCRYPTO
#include "modtrezorcrypto-ed25519.h"
#include "modtrezorcrypto-pbkdf2_hmac.h"
#include "modtrezorcrypto-pbkdf2.h"
#include "modtrezorcrypto-ripemd160.h"
#include "modtrezorcrypto-nist256p1.h"
#include "modtrezorcrypto-secp256k1.h"
@ -31,13 +31,13 @@ STATIC const mp_rom_map_elem_t mp_module_TrezorCrypto_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_TrezorCrypto) },
{ MP_ROM_QSTR(MP_QSTR_Ed25519), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_type) },
{ MP_ROM_QSTR(MP_QSTR_Nist256p1), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_type) },
{ MP_ROM_QSTR(MP_QSTR_Pbkdf2), MP_ROM_PTR(&mod_TrezorCrypto_Pbkdf2_type) },
{ MP_ROM_QSTR(MP_QSTR_Ripemd160), MP_ROM_PTR(&mod_TrezorCrypto_Ripemd160_type) },
{ MP_ROM_QSTR(MP_QSTR_Secp256k1), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_type) },
{ MP_ROM_QSTR(MP_QSTR_Sha256), MP_ROM_PTR(&mod_TrezorCrypto_Sha256_type) },
{ MP_ROM_QSTR(MP_QSTR_Sha512), MP_ROM_PTR(&mod_TrezorCrypto_Sha512_type) },
{ MP_ROM_QSTR(MP_QSTR_Sha3_256), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_256_type) },
{ MP_ROM_QSTR(MP_QSTR_Sha3_512), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_512_type) },
{ MP_ROM_QSTR(MP_QSTR_pbkdf2_hmac), MP_ROM_PTR(&mod_TrezorCrypto_pbkdf2_hmac_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_TrezorCrypto_globals, mp_module_TrezorCrypto_globals_table);

View File

@ -4,40 +4,105 @@ sys.path.append('../lib')
import unittest
from ubinascii import unhexlify
from trezor.crypto import hashlib
from trezor.crypto import hmac
from trezor.crypto import pbkdf2
class TestCryptoPbkdf2(unittest.TestCase):
# vectors from https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
def test_hmac_sha256(self):
def test_pbkdf2_hmac_sha256(self):
P = b'password'
S = b'salt'
dk = hashlib.pbkdf2_hmac('sha256', P, S, 1)
dk = pbkdf2('hmac-sha256', P, S, 1).key()
self.assertEqual(dk, unhexlify('120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b'))
dk = hashlib.pbkdf2_hmac('sha256', P, S, 2)
dk = pbkdf2('hmac-sha256', P, S, 2).key()
self.assertEqual(dk, unhexlify('ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43'))
dk = hashlib.pbkdf2_hmac('sha256', P, S, 4096)
dk = pbkdf2('hmac-sha256', P, S, 4096).key()
self.assertEqual(dk, unhexlify('c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a'))
P = b'passwordPASSWORDpassword'
S = b'saltSALTsaltSALTsaltSALTsaltSALTsalt'
dk = hashlib.pbkdf2_hmac('sha256', P, S, 4096, 40)
self.assertEqual(dk, unhexlify('348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9'))
dk = pbkdf2('hmac-sha256', P, S, 4096).key()
self.assertEqual(dk, unhexlify('348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1'))
# vectors from https://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors
def test_hmac_sha512(self):
def test_pbkdf2_hmac_sha256_update(self):
P = b'password'
S = b'salt'
dk = hashlib.pbkdf2_hmac('sha512', P, S, 1)
p = pbkdf2('hmac-sha256', P, S)
p.update(1)
dk = p.key()
self.assertEqual(dk, unhexlify('120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b'))
p = pbkdf2('hmac-sha256', P, S)
p.update(1)
p.update(1)
dk = p.key()
self.assertEqual(dk, unhexlify('ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43'))
p = pbkdf2('hmac-sha256', P, S)
for i in range(32):
p.update(128)
dk = p.key()
self.assertEqual(dk, unhexlify('c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a'))
P = b'passwordPASSWORDpassword'
S = b'saltSALTsaltSALTsaltSALTsaltSALTsalt'
p = pbkdf2('hmac-sha256', P, S)
for i in range(64):
p.update(64)
dk = p.key()
self.assertEqual(dk, unhexlify('348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1'))
# vectors from https://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors
def test_pbkdf2_hmac_sha512(self):
P = b'password'
S = b'salt'
dk = pbkdf2('hmac-sha512', P, S, 1).key()
self.assertEqual(dk, unhexlify('867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce'))
dk = hashlib.pbkdf2_hmac('sha512', P, S, 2)
dk = pbkdf2('hmac-sha512', P, S, 2).key()
self.assertEqual(dk, unhexlify('e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e'))
dk = hashlib.pbkdf2_hmac('sha512', P, S, 4096)
dk = pbkdf2('hmac-sha512', P, S, 4096).key()
self.assertEqual(dk, unhexlify('d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5'))
P = b'passwordPASSWORDpassword'
S = b'saltSALTsaltSALTsaltSALTsaltSALTsalt'
dk = hashlib.pbkdf2_hmac('sha512', P, S, 4096)
dk = pbkdf2('hmac-sha512', P, S, 4096).key()
self.assertEqual(dk, unhexlify('8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8'))
def test_pbkdf2_hmac_sha512_update(self):
P = b'password'
S = b'salt'
p = pbkdf2('hmac-sha512', P, S)
p.update(1)
dk = p.key()
self.assertEqual(dk, unhexlify('867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce'))
p = pbkdf2('hmac-sha512', P, S)
p.update(1)
p.update(1)
dk = p.key()
self.assertEqual(dk, unhexlify('e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e'))
p = pbkdf2('hmac-sha512', P, S)
for i in range(32):
p.update(128)
dk = p.key()
self.assertEqual(dk, unhexlify('d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5'))
P = b'passwordPASSWORDpassword'
S = b'saltSALTsaltSALTsaltSALTsaltSALTsalt'
p = pbkdf2('hmac-sha512', P, S)
for i in range(64):
p.update(64)
dk = p.key()
self.assertEqual(dk, unhexlify('8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8'))
def test_key_multi(self):
P = b'password'
S = b'salt'
p = pbkdf2('hmac-sha256', P, S, 16)
k0 = p.key()
k1 = p.key()
k2 = p.key()
self.assertEqual(k0, k1)
self.assertEqual(k0, k2)
p = pbkdf2('hmac-sha512', P, S, 16)
k0 = p.key()
k1 = p.key()
k2 = p.key()
self.assertEqual(k0, k1)
self.assertEqual(k0, k2)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1 @@
from TrezorCrypto import Pbkdf2 as pbkdf2

View File

@ -3,4 +3,3 @@ from TrezorCrypto import Sha256 as sha256
from TrezorCrypto import Sha512 as sha512
from TrezorCrypto import Sha3_256 as sha3_256
from TrezorCrypto import Sha3_512 as sha3_512
from TrezorCrypto import pbkdf2_hmac

@ -1 +1 @@
Subproject commit b8ec5567ba701c77379f2111774456eb18b98790
Subproject commit 242a5de275d36e2df6792c921a9cd7d8c8e8933b