1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-26 16:18:22 +00:00

core/slip39: Remove math module dependency.

This commit is contained in:
Andrew Kozlik 2019-04-29 12:23:10 +02:00
parent 48a98efc58
commit 479396b56f

View File

@ -18,8 +18,6 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# #
import math
from trezor.crypto import hashlib, hmac, pbkdf2, random from trezor.crypto import hashlib, hmac, pbkdf2, random
from trezor.crypto.slip39_wordlist import wordlist from trezor.crypto.slip39_wordlist import wordlist
from trezorcrypto import shamir from trezorcrypto import shamir
@ -33,6 +31,14 @@ class MnemonicError(Exception):
pass pass
def bits_to_bytes(n):
return (n + 7) // 8
def bits_to_words(n):
return (n + RADIX_BITS - 1) // RADIX_BITS
RADIX_BITS = 10 RADIX_BITS = 10
"""The length of the radix in bits.""" """The length of the radix in bits."""
@ -45,7 +51,7 @@ ID_LENGTH_BITS = 15
ITERATION_EXP_LENGTH_BITS = 5 ITERATION_EXP_LENGTH_BITS = 5
"""The length of the iteration exponent in bits.""" """The length of the iteration exponent in bits."""
ID_EXP_LENGTH_WORDS = (ID_LENGTH_BITS + ITERATION_EXP_LENGTH_BITS) // RADIX_BITS ID_EXP_LENGTH_WORDS = bits_to_words(ID_LENGTH_BITS + ITERATION_EXP_LENGTH_BITS)
"""The length of the random identifier and iteration exponent in words.""" """The length of the random identifier and iteration exponent in words."""
MAX_SHARE_COUNT = 16 MAX_SHARE_COUNT = 16
@ -66,10 +72,10 @@ METADATA_LENGTH_WORDS = ID_EXP_LENGTH_WORDS + 2 + CHECKSUM_LENGTH_WORDS
MIN_STRENGTH_BITS = 128 MIN_STRENGTH_BITS = 128
"""The minimum allowed entropy of the master secret.""" """The minimum allowed entropy of the master secret."""
MIN_MNEMONIC_LENGTH_WORDS = METADATA_LENGTH_WORDS + math.ceil(MIN_STRENGTH_BITS / 10) MIN_MNEMONIC_LENGTH_WORDS = METADATA_LENGTH_WORDS + bits_to_words(MIN_STRENGTH_BITS)
"""The minimum allowed length of the mnemonic in words.""" """The minimum allowed length of the mnemonic in words."""
MIN_ITERATION_COUNT = 10000 BASE_ITERATION_COUNT = 10000
"""The minimum number of iterations to use in PBKDF2.""" """The minimum number of iterations to use in PBKDF2."""
ROUND_COUNT = 4 ROUND_COUNT = 4
@ -162,13 +168,13 @@ def _round_function(i, passphrase, e, salt, r):
pbkdf2.HMAC_SHA256, pbkdf2.HMAC_SHA256,
bytes([i]) + passphrase, bytes([i]) + passphrase,
salt + r, salt + r,
(MIN_ITERATION_COUNT << e) // ROUND_COUNT, (BASE_ITERATION_COUNT << e) // ROUND_COUNT,
).key()[: len(r)] ).key()[: len(r)]
def _get_salt(identifier): def _get_salt(identifier):
return CUSTOMIZATION_STRING + identifier.to_bytes( return CUSTOMIZATION_STRING + identifier.to_bytes(
math.ceil(ID_LENGTH_BITS / 8), "big" bits_to_bytes(ID_LENGTH_BITS), "big"
) )
@ -284,7 +290,7 @@ def encode_mnemonic(
""" """
# Convert the share value from bytes to wordlist indices. # Convert the share value from bytes to wordlist indices.
value_word_count = math.ceil(len(value) * 8 / RADIX_BITS) value_word_count = bits_to_words(len(value) * 8)
value_int = int.from_bytes(value, "big") value_int = int.from_bytes(value, "big")
share_data = ( share_data = (
@ -315,7 +321,7 @@ def decode_mnemonic(mnemonic):
) )
) )
padding_len = (10 * (len(mnemonic_data) - METADATA_LENGTH_WORDS)) % 16 padding_len = (RADIX_BITS * (len(mnemonic_data) - METADATA_LENGTH_WORDS)) % 16
if padding_len > 8: if padding_len > 8:
raise MnemonicError("Invalid mnemonic length.") raise MnemonicError("Invalid mnemonic length.")
@ -344,9 +350,9 @@ def decode_mnemonic(mnemonic):
) )
) )
value_byte_count = (10 * len(value_data) - padding_len) // 8 value_byte_count = bits_to_bytes(RADIX_BITS * len(value_data) - padding_len)
value_int = _int_from_indices(value_data) value_int = _int_from_indices(value_data)
if value_data[0] >= 1 << (10 - padding_len): if value_data[0] >= 1 << (RADIX_BITS - padding_len):
raise MnemonicError( raise MnemonicError(
'Invalid mnemonic padding for "{} ...".'.format( 'Invalid mnemonic padding for "{} ...".'.format(
" ".join(mnemonic.split()[: ID_EXP_LENGTH_WORDS + 2]) " ".join(mnemonic.split()[: ID_EXP_LENGTH_WORDS + 2])
@ -422,7 +428,7 @@ def _decode_mnemonics(mnemonics):
def _generate_random_identifier(): def _generate_random_identifier():
"""Returns a randomly generated integer in the range 0, ... , 2**ID_LENGTH_BITS - 1.""" """Returns a randomly generated integer in the range 0, ... , 2**ID_LENGTH_BITS - 1."""
identifier = int.from_bytes(random.bytes(math.ceil(ID_LENGTH_BITS / 8)), "big") identifier = int.from_bytes(random.bytes(bits_to_bytes(ID_LENGTH_BITS)), "big")
return identifier & ((1 << ID_LENGTH_BITS) - 1) return identifier & ((1 << ID_LENGTH_BITS) - 1)
@ -450,7 +456,7 @@ def generate_mnemonics(
if len(master_secret) * 8 < MIN_STRENGTH_BITS: if len(master_secret) * 8 < MIN_STRENGTH_BITS:
raise ValueError( raise ValueError(
"The length of the master secret ({} bytes) must be at least {} bytes.".format( "The length of the master secret ({} bytes) must be at least {} bytes.".format(
len(master_secret), math.ceil(MIN_STRENGTH_BITS / 8) len(master_secret), bits_to_bytes(MIN_STRENGTH_BITS)
) )
) )