From d8534b5ee6032ca9396139899fe46521339f3747 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Mon, 12 Oct 2020 16:33:13 +0200 Subject: [PATCH] perf(core/extmod): replace HMAC Python implementation with C We keep Python implementation of HMAC for Monero in core/src/apps/monero/xmr/crypto/__init__.py --- .../modtrezorcrypto/modtrezorcrypto-hmac.h | 159 ++++++++++++++++++ .../extmod/modtrezorcrypto/modtrezorcrypto.c | 2 + .../mocks/generated/trezorcrypto/__init__.pyi | 29 ++++ core/src/apps/bitcoin/ownership.py | 2 +- core/src/apps/common/seed.py | 6 +- core/src/apps/misc/cipher_key_value.py | 3 +- core/src/apps/monero/xmr/crypto/__init__.py | 26 ++- core/src/apps/webauthn/credential.py | 4 +- core/src/apps/webauthn/fido2.py | 6 +- core/src/storage/sd_salt.py | 3 +- core/src/trezor/crypto/__init__.py | 1 + core/src/trezor/crypto/hmac.py | 53 ------ core/src/trezor/crypto/slip39.py | 6 +- core/tests/test_trezor.crypto.hmac.py | 36 ++-- 14 files changed, 243 insertions(+), 93 deletions(-) create mode 100644 core/embed/extmod/modtrezorcrypto/modtrezorcrypto-hmac.h delete mode 100644 core/src/trezor/crypto/hmac.py diff --git a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-hmac.h b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-hmac.h new file mode 100644 index 0000000000..598505080a --- /dev/null +++ b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-hmac.h @@ -0,0 +1,159 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "py/objstr.h" + +#include "hmac.h" +#include "memzero.h" + +#define SHA256 256 +#define SHA512 512 + +/// package: trezorcrypto.__init__ + +/// class hmac: +/// """ +/// HMAC context. +/// """ +/// SHA256: int +/// SHA512: int +typedef struct _mp_obj_Hmac_t { + mp_obj_base_t base; + union { + HMAC_SHA256_CTX ctx256; + HMAC_SHA512_CTX ctx512; + }; + uint32_t hashtype; +} mp_obj_Hmac_t; + +STATIC mp_obj_t mod_trezorcrypto_Hmac_update(mp_obj_t self, mp_obj_t data); + +/// def __init__( +/// self, +/// hashtype: int, +/// key: bytes, +/// message: bytes = None +/// ) -> None: +/// """ +/// Create a HMAC context. +/// """ +STATIC mp_obj_t mod_trezorcrypto_Hmac_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, 2, 3, false); + mp_obj_Hmac_t *o = m_new_obj_with_finaliser(mp_obj_Hmac_t); + o->base.type = type; + + mp_buffer_info_t key = {0}; + mp_get_buffer_raise(args[1], &key, MP_BUFFER_READ); + + if (key.len == 0) { + key.buf = ""; + } + + o->hashtype = trezor_obj_get_uint(args[0]); + if (o->hashtype == SHA256) { + hmac_sha256_Init(&(o->ctx256), key.buf, key.len); + } else if (o->hashtype == SHA512) { + hmac_sha512_Init(&(o->ctx512), key.buf, key.len); + } else { + mp_raise_ValueError("Invalid hashtype"); + } + // constructor called with message as third parameter + if (n_args > 2) { + mod_trezorcrypto_Hmac_update(MP_OBJ_FROM_PTR(o), args[2]); + } + return MP_OBJ_FROM_PTR(o); +} + +/// def update(self, message: bytes) -> None: +/// """ +/// Update a HMAC context. +/// """ +STATIC mp_obj_t mod_trezorcrypto_Hmac_update(mp_obj_t self, mp_obj_t message) { + mp_obj_Hmac_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg = {0}; + mp_get_buffer_raise(message, &msg, MP_BUFFER_READ); + if (o->hashtype == SHA256) { + hmac_sha256_Update(&(o->ctx256), msg.buf, msg.len); + } else if (o->hashtype == SHA512) { + hmac_sha512_Update(&(o->ctx512), msg.buf, msg.len); + } else { + mp_raise_ValueError("Invalid hashtype"); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Hmac_update_obj, + mod_trezorcrypto_Hmac_update); + +/// def digest(self) -> bytes: +/// """ +/// Return the digest of processed data so far. +/// """ +STATIC mp_obj_t mod_trezorcrypto_Hmac_digest(mp_obj_t self) { + mp_obj_Hmac_t *o = MP_OBJ_TO_PTR(self); + vstr_t mac = {0}; + if (o->hashtype == SHA256) { + HMAC_SHA256_CTX ctx = {0}; + memcpy(&ctx, &(o->ctx256), sizeof(HMAC_SHA256_CTX)); + vstr_init_len(&mac, SHA256_DIGEST_LENGTH); + hmac_sha256_Final(&ctx, (uint8_t *)mac.buf); + memzero(&ctx, sizeof(HMAC_SHA256_CTX)); + } else if (o->hashtype == SHA512) { + HMAC_SHA512_CTX ctx = {0}; + memcpy(&ctx, &(o->ctx512), sizeof(HMAC_SHA512_CTX)); + vstr_init_len(&mac, SHA512_DIGEST_LENGTH); + hmac_sha512_Final(&ctx, (uint8_t *)mac.buf); + memzero(&ctx, sizeof(HMAC_SHA512_CTX)); + } else { + mp_raise_ValueError("Invalid hashtype"); + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &mac); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Hmac_digest_obj, + mod_trezorcrypto_Hmac_digest); + +STATIC mp_obj_t mod_trezorcrypto_Hmac___del__(mp_obj_t self) { + mp_obj_Hmac_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx256), sizeof(HMAC_SHA256_CTX)); + memzero(&(o->ctx512), sizeof(HMAC_SHA512_CTX)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Hmac___del___obj, + mod_trezorcrypto_Hmac___del__); + +STATIC const mp_rom_map_elem_t mod_trezorcrypto_Hmac_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Hmac_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Hmac_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Hmac___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_SHA256), MP_ROM_INT(SHA256)}, + {MP_ROM_QSTR(MP_QSTR_SHA512), MP_ROM_INT(SHA512)}, +}; +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Hmac_locals_dict, + mod_trezorcrypto_Hmac_locals_dict_table); + +STATIC const mp_obj_type_t mod_trezorcrypto_Hmac_type = { + {&mp_type_type}, + .name = MP_QSTR_Hmac, + .make_new = mod_trezorcrypto_Hmac_make_new, + .locals_dict = (void *)&mod_trezorcrypto_Hmac_locals_dict, +}; diff --git a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 37b09f1f7c..7e46d9408a 100644 --- a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -36,6 +36,7 @@ #include "modtrezorcrypto-curve25519.h" #include "modtrezorcrypto-ed25519.h" #include "modtrezorcrypto-groestl.h" +#include "modtrezorcrypto-hmac.h" #include "modtrezorcrypto-nist256p1.h" #include "modtrezorcrypto-pbkdf2.h" #include "modtrezorcrypto-random.h" @@ -77,6 +78,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module)}, {MP_ROM_QSTR(MP_QSTR_groestl512), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)}, + {MP_ROM_QSTR(MP_QSTR_hmac), MP_ROM_PTR(&mod_trezorcrypto_Hmac_type)}, #if !BITCOIN_ONLY {MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)}, #endif diff --git a/core/mocks/generated/trezorcrypto/__init__.pyi b/core/mocks/generated/trezorcrypto/__init__.pyi index 3a847e7d0e..68e270628a 100644 --- a/core/mocks/generated/trezorcrypto/__init__.pyi +++ b/core/mocks/generated/trezorcrypto/__init__.pyi @@ -173,6 +173,35 @@ class groestl512: """ +# extmod/modtrezorcrypto/modtrezorcrypto-hmac.h +class hmac: + """ + HMAC context. + """ + SHA256: int + SHA512: int + + def __init__( + self, + hashtype: int, + key: bytes, + message: bytes = None + ) -> None: + """ + Create a HMAC context. + """ + + def update(self, message: bytes) -> None: + """ + Update a HMAC context. + """ + + def digest(self) -> bytes: + """ + Return the digest of processed data so far. + """ + + # extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h class pbkdf2: """ diff --git a/core/src/apps/bitcoin/ownership.py b/core/src/apps/bitcoin/ownership.py index 8b60628af9..c00873ba09 100644 --- a/core/src/apps/bitcoin/ownership.py +++ b/core/src/apps/bitcoin/ownership.py @@ -111,4 +111,4 @@ def get_identifier(script_pubkey: bytes, keychain: Keychain) -> bytes: node = keychain.derive_slip21(_OWNERSHIP_ID_KEY_PATH) # id = HMAC-SHA256(key = k, msg = scriptPubKey) - return hmac.Hmac(node.key(), script_pubkey, hashlib.sha256).digest() + return hmac(hmac.SHA256, node.key(), script_pubkey).digest() diff --git a/core/src/apps/common/seed.py b/core/src/apps/common/seed.py index debcb02f86..3d161e0bcb 100644 --- a/core/src/apps/common/seed.py +++ b/core/src/apps/common/seed.py @@ -1,6 +1,6 @@ from storage import cache, device from trezor import wire -from trezor.crypto import bip32, hashlib, hmac +from trezor.crypto import bip32, hmac from . import mnemonic from .passphrase import get as get_passphrase @@ -15,7 +15,7 @@ class Slip21Node: if data is not None: self.data = data elif seed is not None: - self.data = hmac.new(b"Symmetric key seed", seed, hashlib.sha512).digest() + self.data = hmac(hmac.SHA512, b"Symmetric key seed", seed).digest() else: raise ValueError # neither seed nor data specified @@ -24,7 +24,7 @@ class Slip21Node: def derive_path(self, path: Slip21Path) -> None: for label in path: - h = hmac.new(self.data[0:32], b"\x00", hashlib.sha512) + h = hmac(hmac.SHA512, self.data[0:32], b"\x00") h.update(label) self.data = h.digest() diff --git a/core/src/apps/misc/cipher_key_value.py b/core/src/apps/misc/cipher_key_value.py index 83c5d26737..cd564907b2 100644 --- a/core/src/apps/misc/cipher_key_value.py +++ b/core/src/apps/misc/cipher_key_value.py @@ -1,6 +1,5 @@ from trezor import wire from trezor.crypto import aes, hmac -from trezor.crypto.hashlib import sha512 from trezor.messages.CipheredKeyValue import CipheredKeyValue from trezor.ui.text import Text @@ -34,7 +33,7 @@ def compute_cipher_key_value(msg, seckey: bytes) -> bytes: data = msg.key data += "E1" if msg.ask_on_encrypt else "E0" data += "D1" if msg.ask_on_decrypt else "D0" - data = hmac.new(seckey, data, sha512).digest() + data = hmac(hmac.SHA512, seckey, data).digest() key = data[:32] if msg.iv and len(msg.iv) == 16: iv = msg.iv diff --git a/core/src/apps/monero/xmr/crypto/__init__.py b/core/src/apps/monero/xmr/crypto/__init__.py index deb341cea4..0bff3e8207 100644 --- a/core/src/apps/monero/xmr/crypto/__init__.py +++ b/core/src/apps/monero/xmr/crypto/__init__.py @@ -7,7 +7,7 @@ # https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-00#section-4 # https://github.com/monero-project/research-lab -from trezor.crypto import hmac, monero as tcry, random +from trezor.crypto import monero as tcry, random from trezor.crypto.hashlib import sha3_256 if False: @@ -37,9 +37,27 @@ def keccak_2hash(inp, buff=None): return buff -def compute_hmac(key, msg=None): - h = hmac.new(key, msg=msg, digestmod=keccak_factory) - return h.digest() +def compute_hmac(key, msg): + digestmod = keccak_factory + inner = digestmod() + block_size = inner.block_size + if len(key) > block_size: + key = digestmod(key).digest() + key_block = bytearray(block_size) + for i in range(block_size): + key_block[i] = 0x36 + for i in range(len(key)): + key_block[i] ^= key[i] + inner.update(key_block) + inner.update(msg) + outer = digestmod() + for i in range(block_size): + key_block[i] = 0x5C + for i in range(len(key)): + key_block[i] ^= key[i] + outer.update(key_block) + outer.update(inner.digest()) + return outer.digest() # diff --git a/core/src/apps/webauthn/credential.py b/core/src/apps/webauthn/credential.py index b0ba17ca8d..5834255aca 100644 --- a/core/src/apps/webauthn/credential.py +++ b/core/src/apps/webauthn/credential.py @@ -394,7 +394,7 @@ class U2fCredential(Credential): keypath = ustruct.pack("<8L", *path) # second half of keyhandle is a hmac of rp_id_hash and keypath - mac = hmac.Hmac(self.node.private_key(), self.rp_id_hash, hashlib.sha256) + mac = hmac(hmac.SHA256, self.node.private_key(), self.rp_id_hash) mac.update(keypath) self.id = keypath + mac.digest() @@ -453,7 +453,7 @@ class U2fCredential(Credential): node = seed.derive_node_without_passphrase(nodepath, "nist256p1") # second half of keyhandle is a hmac of rp_id_hash and keypath - mac = hmac.Hmac(node.private_key(), rp_id_hash, hashlib.sha256) + mac = hmac(hmac.SHA256, node.private_key(), rp_id_hash) mac.update(keypath) # verify the hmac diff --git a/core/src/apps/webauthn/fido2.py b/core/src/apps/webauthn/fido2.py index 1bce261133..58b9f20175 100644 --- a/core/src/apps/webauthn/fido2.py +++ b/core/src/apps/webauthn/fido2.py @@ -1796,7 +1796,7 @@ def cbor_get_assertion_hmac_secret( shared_secret = hashlib.sha256(ecdh_result[1:33]).digest() # Check the authentication tag and decrypt the salt. - tag = hmac.Hmac(shared_secret, salt_enc, hashlib.sha256).digest()[:16] + tag = hmac(hmac.SHA256, shared_secret, salt_enc).digest()[:16] if not utils.consteq(tag, salt_auth): raise CborError(_ERR_EXTENSION_FIRST) salt = aes(aes.CBC, shared_secret).decrypt(salt_enc) @@ -1808,9 +1808,9 @@ def cbor_get_assertion_hmac_secret( return None # Compute the hmac-secret output. - output = hmac.Hmac(cred_random, salt[:32], hashlib.sha256).digest() + output = hmac(hmac.SHA256, cred_random, salt[:32]).digest() if len(salt) == 64: - output += hmac.Hmac(cred_random, salt[32:], hashlib.sha256).digest() + output += hmac(hmac.SHA256, cred_random, salt[32:]).digest() # Encrypt the hmac-secret output. return aes(aes.CBC, shared_secret).encrypt(output) diff --git a/core/src/storage/sd_salt.py b/core/src/storage/sd_salt.py index 54daf2b268..234c5e2104 100644 --- a/core/src/storage/sd_salt.py +++ b/core/src/storage/sd_salt.py @@ -3,7 +3,6 @@ from micropython import const import storage.device from trezor import fatfs from trezor.crypto import hmac -from trezor.crypto.hashlib import sha256 from trezor.sdcard import with_filesystem from trezor.utils import consteq @@ -26,7 +25,7 @@ def is_enabled() -> bool: def compute_auth_tag(salt: bytes, auth_key: bytes) -> bytes: - digest = hmac.new(auth_key, salt, sha256).digest() + digest = hmac(hmac.SHA256, auth_key, salt).digest() return digest[:SD_SALT_AUTH_TAG_LEN_BYTES] diff --git a/core/src/trezor/crypto/__init__.py b/core/src/trezor/crypto/__init__.py index 1735400760..957346f24f 100644 --- a/core/src/trezor/crypto/__init__.py +++ b/core/src/trezor/crypto/__init__.py @@ -4,6 +4,7 @@ from trezorcrypto import ( # noqa: F401 bip39, chacha20poly1305, crc, + hmac, pbkdf2, random, ) diff --git a/core/src/trezor/crypto/hmac.py b/core/src/trezor/crypto/hmac.py deleted file mode 100644 index 69e2322ad9..0000000000 --- a/core/src/trezor/crypto/hmac.py +++ /dev/null @@ -1,53 +0,0 @@ -if False: - from typing import Protocol, Type - - class HashContext(Protocol): - - digest_size = -1 # type: int - block_size = -1 # type: int - - def __init__(self, data: bytes = None) -> None: - ... - - def update(self, data: bytes) -> None: - ... - - def digest(self) -> bytes: - ... - - -class Hmac: - def __init__(self, key: bytes, msg: bytes, digestmod: Type[HashContext]): - self.digestmod = digestmod - self.inner = digestmod() - self.digest_size = self.inner.digest_size - self.block_size = self.inner.block_size - - if len(key) > self.block_size: - key = digestmod(key).digest() - self.key = key + bytes(self.block_size - len(key)) - self.inner.update(bytes((x ^ 0x36) for x in self.key)) - if msg is not None: - self.update(msg) - - def update(self, msg: bytes) -> None: - """ - Update the context with data. - """ - self.inner.update(msg) - - def digest(self) -> bytes: - """ - Returns the digest of processed data. - """ - outer = self.digestmod() - outer.update(bytes((x ^ 0x5C) for x in self.key)) - outer.update(self.inner.digest()) - return outer.digest() - - -def new(key: bytes, msg: bytes, digestmod: Type[HashContext]) -> Hmac: - """ - Creates a HMAC context object. - """ - return Hmac(key, msg, digestmod) diff --git a/core/src/trezor/crypto/slip39.py b/core/src/trezor/crypto/slip39.py index ddf7a51883..3970211354 100644 --- a/core/src/trezor/crypto/slip39.py +++ b/core/src/trezor/crypto/slip39.py @@ -33,7 +33,7 @@ See https://github.com/satoshilabs/slips/blob/master/slip-0039.md. from micropython import const from trezorcrypto import shamir, slip39 -from trezor.crypto import hashlib, hmac, pbkdf2, random +from trezor.crypto import hmac, pbkdf2, random from trezor.errors import MnemonicError if False: @@ -479,9 +479,7 @@ def _get_salt(identifier: int) -> bytes: def _create_digest(random_data: bytes, shared_secret: bytes) -> bytes: - return hmac.new(random_data, shared_secret, hashlib.sha256).digest()[ - :_DIGEST_LENGTH_BYTES - ] + return hmac(hmac.SHA256, random_data, shared_secret).digest()[:_DIGEST_LENGTH_BYTES] def _split_secret( diff --git a/core/tests/test_trezor.crypto.hmac.py b/core/tests/test_trezor.crypto.hmac.py index d827d7d37f..aaacfdc6c6 100644 --- a/core/tests/test_trezor.crypto.hmac.py +++ b/core/tests/test_trezor.crypto.hmac.py @@ -1,7 +1,5 @@ from common import * -from trezor.crypto import hashlib - from trezor.crypto import hmac @@ -14,65 +12,65 @@ class TestCryptoHmac(unittest.TestCase): # case 1 key = b'\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b' msg = b'Hi There' - self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7')) - self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854')) + self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7')) + self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854')) # case 2 key = b'Jefe' msg = b'what do ya want for nothing?' - self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843')) - self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737')) + self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843')) + self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737')) # case 3 key = b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa' msg = b'\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd' - self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe')) - self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb')) + self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe')) + self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb')) # case 4 key = b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19' msg = b'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' - self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b')) - self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd')) + self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b')) + self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd')) # case 6 key = bytes([0xAA] * 131) msg = b'Test Using Larger Than Block-Size Key - Hash Key First' - self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54')) - self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598')) + self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54')) + self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598')) # case 7 key = bytes([0xAA] * 131) msg = b'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.' - self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2')) - self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58')) + self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2')) + self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58')) def test_update(self): # case 3 key = b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa' - x = hmac.new(key, b'', hashlib.sha256) + x = hmac(hmac.SHA256, key) for i in range(50): x.update(b'\xdd') self.assertEqual(x.digest(), unhexlify('773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe')) - x = hmac.new(key, b'', hashlib.sha512) + x = hmac(hmac.SHA512, key) for i in range(50): x.update(b'\xdd') self.assertEqual(x.digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb')) # case 4 key = b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19' - x = hmac.new(key, b'', hashlib.sha256) + x = hmac(hmac.SHA256, key) for i in range(50): x.update(b'\xcd') self.assertEqual(x.digest(), unhexlify('82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b')) - x = hmac.new(key, b'', hashlib.sha512) + x = hmac(hmac.SHA512, key) for i in range(50): x.update(b'\xcd') self.assertEqual(x.digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd')) def test_digest_multi(self): - x = hmac.new(b'', b'', hashlib.sha256) + x = hmac(hmac.SHA256, b'') d0 = x.digest() d1 = x.digest() d2 = x.digest()