1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 07:28:10 +00:00

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
This commit is contained in:
Pavol Rusnak 2020-10-12 16:33:13 +02:00 committed by GitHub
parent 2101ff8904
commit d8534b5ee6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 243 additions and 93 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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,
};

View File

@ -36,6 +36,7 @@
#include "modtrezorcrypto-curve25519.h" #include "modtrezorcrypto-curve25519.h"
#include "modtrezorcrypto-ed25519.h" #include "modtrezorcrypto-ed25519.h"
#include "modtrezorcrypto-groestl.h" #include "modtrezorcrypto-groestl.h"
#include "modtrezorcrypto-hmac.h"
#include "modtrezorcrypto-nist256p1.h" #include "modtrezorcrypto-nist256p1.h"
#include "modtrezorcrypto-pbkdf2.h" #include "modtrezorcrypto-pbkdf2.h"
#include "modtrezorcrypto-random.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_PTR(&mod_trezorcrypto_nist256p1_module)},
{MP_ROM_QSTR(MP_QSTR_groestl512), {MP_ROM_QSTR(MP_QSTR_groestl512),
MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)}, MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)},
{MP_ROM_QSTR(MP_QSTR_hmac), MP_ROM_PTR(&mod_trezorcrypto_Hmac_type)},
#if !BITCOIN_ONLY #if !BITCOIN_ONLY
{MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)}, {MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)},
#endif #endif

View File

@ -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 # extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h
class pbkdf2: class pbkdf2:
""" """

View File

@ -111,4 +111,4 @@ def get_identifier(script_pubkey: bytes, keychain: Keychain) -> bytes:
node = keychain.derive_slip21(_OWNERSHIP_ID_KEY_PATH) node = keychain.derive_slip21(_OWNERSHIP_ID_KEY_PATH)
# id = HMAC-SHA256(key = k, msg = scriptPubKey) # 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()

View File

@ -1,6 +1,6 @@
from storage import cache, device from storage import cache, device
from trezor import wire from trezor import wire
from trezor.crypto import bip32, hashlib, hmac from trezor.crypto import bip32, hmac
from . import mnemonic from . import mnemonic
from .passphrase import get as get_passphrase from .passphrase import get as get_passphrase
@ -15,7 +15,7 @@ class Slip21Node:
if data is not None: if data is not None:
self.data = data self.data = data
elif seed is not None: 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: else:
raise ValueError # neither seed nor data specified raise ValueError # neither seed nor data specified
@ -24,7 +24,7 @@ class Slip21Node:
def derive_path(self, path: Slip21Path) -> None: def derive_path(self, path: Slip21Path) -> None:
for label in path: 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) h.update(label)
self.data = h.digest() self.data = h.digest()

View File

@ -1,6 +1,5 @@
from trezor import wire from trezor import wire
from trezor.crypto import aes, hmac from trezor.crypto import aes, hmac
from trezor.crypto.hashlib import sha512
from trezor.messages.CipheredKeyValue import CipheredKeyValue from trezor.messages.CipheredKeyValue import CipheredKeyValue
from trezor.ui.text import Text from trezor.ui.text import Text
@ -34,7 +33,7 @@ def compute_cipher_key_value(msg, seckey: bytes) -> bytes:
data = msg.key data = msg.key
data += "E1" if msg.ask_on_encrypt else "E0" data += "E1" if msg.ask_on_encrypt else "E0"
data += "D1" if msg.ask_on_decrypt else "D0" 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] key = data[:32]
if msg.iv and len(msg.iv) == 16: if msg.iv and len(msg.iv) == 16:
iv = msg.iv iv = msg.iv

View File

@ -7,7 +7,7 @@
# https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-00#section-4 # https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-00#section-4
# https://github.com/monero-project/research-lab # 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 from trezor.crypto.hashlib import sha3_256
if False: if False:
@ -37,9 +37,27 @@ def keccak_2hash(inp, buff=None):
return buff return buff
def compute_hmac(key, msg=None): def compute_hmac(key, msg):
h = hmac.new(key, msg=msg, digestmod=keccak_factory) digestmod = keccak_factory
return h.digest() 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()
# #

View File

@ -394,7 +394,7 @@ class U2fCredential(Credential):
keypath = ustruct.pack("<8L", *path) keypath = ustruct.pack("<8L", *path)
# second half of keyhandle is a hmac of rp_id_hash and keypath # 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) mac.update(keypath)
self.id = keypath + mac.digest() self.id = keypath + mac.digest()
@ -453,7 +453,7 @@ class U2fCredential(Credential):
node = seed.derive_node_without_passphrase(nodepath, "nist256p1") node = seed.derive_node_without_passphrase(nodepath, "nist256p1")
# second half of keyhandle is a hmac of rp_id_hash and keypath # 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) mac.update(keypath)
# verify the hmac # verify the hmac

View File

@ -1796,7 +1796,7 @@ def cbor_get_assertion_hmac_secret(
shared_secret = hashlib.sha256(ecdh_result[1:33]).digest() shared_secret = hashlib.sha256(ecdh_result[1:33]).digest()
# Check the authentication tag and decrypt the salt. # 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): if not utils.consteq(tag, salt_auth):
raise CborError(_ERR_EXTENSION_FIRST) raise CborError(_ERR_EXTENSION_FIRST)
salt = aes(aes.CBC, shared_secret).decrypt(salt_enc) salt = aes(aes.CBC, shared_secret).decrypt(salt_enc)
@ -1808,9 +1808,9 @@ def cbor_get_assertion_hmac_secret(
return None return None
# Compute the hmac-secret output. # 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: 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. # Encrypt the hmac-secret output.
return aes(aes.CBC, shared_secret).encrypt(output) return aes(aes.CBC, shared_secret).encrypt(output)

View File

@ -3,7 +3,6 @@ from micropython import const
import storage.device import storage.device
from trezor import fatfs from trezor import fatfs
from trezor.crypto import hmac from trezor.crypto import hmac
from trezor.crypto.hashlib import sha256
from trezor.sdcard import with_filesystem from trezor.sdcard import with_filesystem
from trezor.utils import consteq from trezor.utils import consteq
@ -26,7 +25,7 @@ def is_enabled() -> bool:
def compute_auth_tag(salt: bytes, auth_key: bytes) -> bytes: 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] return digest[:SD_SALT_AUTH_TAG_LEN_BYTES]

View File

@ -4,6 +4,7 @@ from trezorcrypto import ( # noqa: F401
bip39, bip39,
chacha20poly1305, chacha20poly1305,
crc, crc,
hmac,
pbkdf2, pbkdf2,
random, random,
) )

View File

@ -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)

View File

@ -33,7 +33,7 @@ See https://github.com/satoshilabs/slips/blob/master/slip-0039.md.
from micropython import const from micropython import const
from trezorcrypto import shamir, slip39 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 from trezor.errors import MnemonicError
if False: if False:
@ -479,9 +479,7 @@ def _get_salt(identifier: int) -> bytes:
def _create_digest(random_data: bytes, shared_secret: bytes) -> bytes: def _create_digest(random_data: bytes, shared_secret: bytes) -> bytes:
return hmac.new(random_data, shared_secret, hashlib.sha256).digest()[ return hmac(hmac.SHA256, random_data, shared_secret).digest()[:_DIGEST_LENGTH_BYTES]
:_DIGEST_LENGTH_BYTES
]
def _split_secret( def _split_secret(

View File

@ -1,7 +1,5 @@
from common import * from common import *
from trezor.crypto import hashlib
from trezor.crypto import hmac from trezor.crypto import hmac
@ -14,65 +12,65 @@ class TestCryptoHmac(unittest.TestCase):
# case 1 # case 1
key = b'\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b' 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' msg = b'Hi There'
self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7')) self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7'))
self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854')) self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854'))
# case 2 # case 2
key = b'Jefe' key = b'Jefe'
msg = b'what do ya want for nothing?' msg = b'what do ya want for nothing?'
self.assertEqual(hmac.new(key, msg, hashlib.sha256).digest(), unhexlify('5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843')) self.assertEqual(hmac(hmac.SHA256, key, msg).digest(), unhexlify('5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843'))
self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737')) self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'))
# case 3 # case 3
key = b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa' 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' 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(hmac.SHA256, key, msg).digest(), unhexlify('773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe'))
self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb')) self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb'))
# case 4 # 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' 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' 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(hmac.SHA256, key, msg).digest(), unhexlify('82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b'))
self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd')) self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd'))
# case 6 # case 6
key = bytes([0xAA] * 131) key = bytes([0xAA] * 131)
msg = b'Test Using Larger Than Block-Size Key - Hash Key First' 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(hmac.SHA256, key, msg).digest(), unhexlify('60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54'))
self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598')) self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598'))
# case 7 # case 7
key = bytes([0xAA] * 131) 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.' 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(hmac.SHA256, key, msg).digest(), unhexlify('9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2'))
self.assertEqual(hmac.new(key, msg, hashlib.sha512).digest(), unhexlify('e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58')) self.assertEqual(hmac(hmac.SHA512, key, msg).digest(), unhexlify('e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58'))
def test_update(self): def test_update(self):
# case 3 # case 3
key = b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa' 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): for i in range(50):
x.update(b'\xdd') x.update(b'\xdd')
self.assertEqual(x.digest(), unhexlify('773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe')) self.assertEqual(x.digest(), unhexlify('773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe'))
x = hmac.new(key, b'', hashlib.sha512) x = hmac(hmac.SHA512, key)
for i in range(50): for i in range(50):
x.update(b'\xdd') x.update(b'\xdd')
self.assertEqual(x.digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb')) self.assertEqual(x.digest(), unhexlify('fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb'))
# case 4 # 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' 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): for i in range(50):
x.update(b'\xcd') x.update(b'\xcd')
self.assertEqual(x.digest(), unhexlify('82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b')) self.assertEqual(x.digest(), unhexlify('82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b'))
x = hmac.new(key, b'', hashlib.sha512) x = hmac(hmac.SHA512, key)
for i in range(50): for i in range(50):
x.update(b'\xcd') x.update(b'\xcd')
self.assertEqual(x.digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd')) self.assertEqual(x.digest(), unhexlify('b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd'))
def test_digest_multi(self): def test_digest_multi(self):
x = hmac.new(b'', b'', hashlib.sha256) x = hmac(hmac.SHA256, b'')
d0 = x.digest() d0 = x.digest()
d1 = x.digest() d1 = x.digest()
d2 = x.digest() d2 = x.digest()