mirror of
https://gitlab.com/pulsechaincom/staking-deposit-cli.git
synced 2024-12-23 11:57:19 +00:00
Merge pull request #41 from ethereum/carl_eip2333_blsv2
Update tests for new EIP2333 (bls v2 compliant HKDF_mod_r)
This commit is contained in:
commit
7ffe1edacd
@ -37,8 +37,14 @@ def _parent_SK_to_lamport_PK(*, parent_SK: int, index: int) -> bytes:
|
|||||||
return compressed_PK
|
return compressed_PK
|
||||||
|
|
||||||
|
|
||||||
def _HKDF_mod_r(*, IKM: bytes) -> int:
|
def _HKDF_mod_r(*, IKM: bytes, key_info: bytes=b'') -> int:
|
||||||
okm = HKDF(salt=b'BLS-SIG-KEYGEN-SALT-', IKM=IKM, L=48)
|
L = 48 # `ceil((3 * ceil(log2(r))) / 16)`, where `r` is the order of the BLS 12-381 curve
|
||||||
|
okm = HKDF(
|
||||||
|
salt=b'BLS-SIG-KEYGEN-SALT-',
|
||||||
|
IKM=IKM + b'\x00', # add postfix `I2OSP(0, 1)`
|
||||||
|
L=L,
|
||||||
|
info=key_info + L.to_bytes(2, 'big'),
|
||||||
|
)
|
||||||
return int.from_bytes(okm, byteorder='big') % bls_curve_order
|
return int.from_bytes(okm, byteorder='big') % bls_curve_order
|
||||||
|
|
||||||
|
|
||||||
@ -49,5 +55,5 @@ def derive_child_SK(*, parent_SK: int, index: int) -> int:
|
|||||||
|
|
||||||
|
|
||||||
def derive_master_SK(seed: bytes) -> int:
|
def derive_master_SK(seed: bytes) -> int:
|
||||||
assert(len(seed) >= 16)
|
assert(len(seed) >= 32)
|
||||||
return _HKDF_mod_r(IKM=seed)
|
return _HKDF_mod_r(IKM=seed)
|
||||||
|
@ -32,8 +32,8 @@ def PBKDF2(*, password: str, salt: bytes, dklen: int, c: int, prf: str) -> bytes
|
|||||||
return res if isinstance(res, bytes) else res[0] # PyCryptodome can return Tuple[bytes]
|
return res if isinstance(res, bytes) else res[0] # PyCryptodome can return Tuple[bytes]
|
||||||
|
|
||||||
|
|
||||||
def HKDF(*, salt: bytes, IKM: bytes, L: int) -> bytes:
|
def HKDF(*, salt: bytes, IKM: bytes, L: int, info: bytes=b'') -> bytes:
|
||||||
res = _HKDF(master=IKM, key_len=L, salt=salt, hashmod=_sha256)
|
res = _HKDF(master=IKM, key_len=L, salt=salt, hashmod=_sha256, context=info)
|
||||||
return res if isinstance(res, bytes) else res[0] # PyCryptodome can return Tuple[bytes]
|
return res if isinstance(res, bytes) else res[0] # PyCryptodome can return Tuple[bytes]
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,18 +8,22 @@ from eth2deposit.key_handling.key_derivation.tree import (
|
|||||||
_HKDF_mod_r,
|
_HKDF_mod_r,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from eth2deposit.key_handling.key_derivation.path import (
|
||||||
|
mnemonic_and_path_to_key,
|
||||||
|
)
|
||||||
|
|
||||||
test_vector_filefolder = os.path.join(os.getcwd(), 'tests', 'test_key_handling', 'test_key_derivation',
|
test_vector_filefolder = os.path.join(os.getcwd(), 'tests', 'test_key_handling', 'test_key_derivation',
|
||||||
'test_vectors', 'tree_kdf_intermediate.json')
|
'test_vectors', 'tree_kdf_intermediate.json')
|
||||||
with open(test_vector_filefolder, 'r') as f:
|
with open(test_vector_filefolder, 'r') as f:
|
||||||
test_vector = json.load(f)
|
test_vector = json.load(f)
|
||||||
|
|
||||||
|
|
||||||
def test_flip_bits_256():
|
def test_flip_bits_256() -> None:
|
||||||
test_vector_int = int(test_vector['seed'][:64], 16) # 64 comes from string chars containing .5 bytes
|
test_vector_int = int(test_vector['seed'][:64], 16) # 64 comes from string chars containing .5 bytes
|
||||||
assert test_vector_int & _flip_bits_256(test_vector_int) == 0
|
assert test_vector_int & _flip_bits_256(test_vector_int) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_IKM_to_lamport_SK():
|
def test_IKM_to_lamport_SK() -> None:
|
||||||
test_vector_lamport_0 = [bytes.fromhex(x) for x in test_vector['lamport_0']]
|
test_vector_lamport_0 = [bytes.fromhex(x) for x in test_vector['lamport_0']]
|
||||||
test_vector_lamport_1 = [bytes.fromhex(x) for x in test_vector['lamport_1']]
|
test_vector_lamport_1 = [bytes.fromhex(x) for x in test_vector['lamport_1']]
|
||||||
salt = test_vector['child_index'].to_bytes(4, 'big')
|
salt = test_vector['child_index'].to_bytes(4, 'big')
|
||||||
@ -31,15 +35,23 @@ def test_IKM_to_lamport_SK():
|
|||||||
assert test_vector_lamport_1 == lamport_1
|
assert test_vector_lamport_1 == lamport_1
|
||||||
|
|
||||||
|
|
||||||
def test_parent_SK_to_lamport_PK():
|
def test_parent_SK_to_lamport_PK() -> None:
|
||||||
parent_SK = test_vector['master_SK']
|
parent_SK = test_vector['master_SK']
|
||||||
index = test_vector['child_index']
|
index = test_vector['child_index']
|
||||||
lamport_PK = bytes.fromhex(test_vector['compressed_lamport_PK'])
|
lamport_PK = bytes.fromhex(test_vector['compressed_lamport_PK'])
|
||||||
assert lamport_PK == _parent_SK_to_lamport_PK(parent_SK=parent_SK, index=index)
|
assert lamport_PK == _parent_SK_to_lamport_PK(parent_SK=parent_SK, index=index)
|
||||||
|
|
||||||
|
|
||||||
def test_HKDF_mod_r():
|
def test_HKDF_mod_r() -> None:
|
||||||
test_0 = (bytes.fromhex(test_vector['seed']), test_vector['master_SK'])
|
test_0 = (bytes.fromhex(test_vector['seed']), test_vector['master_SK'])
|
||||||
test_1 = (bytes.fromhex(test_vector['compressed_lamport_PK']), test_vector['child_SK'])
|
test_1 = (bytes.fromhex(test_vector['compressed_lamport_PK']), test_vector['child_SK'])
|
||||||
for test in (test_0, test_1):
|
for test in (test_0, test_1):
|
||||||
assert _HKDF_mod_r(IKM=test[0]) == test[1]
|
assert _HKDF_mod_r(IKM=test[0]) == test[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_mnemonic_and_path_to_key() -> None:
|
||||||
|
mnemonic = test_vector['mnemonic']
|
||||||
|
password = test_vector['password']
|
||||||
|
path = test_vector['path']
|
||||||
|
key = test_vector['child_SK']
|
||||||
|
assert mnemonic_and_path_to_key(mnemonic=mnemonic, path=path, password=password) == key
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
from py_ecc.bls import G2ProofOfPossession as bls
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
from eth2deposit.key_handling.key_derivation.tree import (
|
from eth2deposit.key_handling.key_derivation.tree import (
|
||||||
|
_HKDF_mod_r,
|
||||||
derive_child_SK,
|
derive_child_SK,
|
||||||
derive_master_SK,
|
derive_master_SK,
|
||||||
)
|
)
|
||||||
@ -14,14 +17,46 @@ with open(test_vector_filefolder, 'r') as f:
|
|||||||
test_vectors = json.load(f)['kdf_tests']
|
test_vectors = json.load(f)['kdf_tests']
|
||||||
|
|
||||||
|
|
||||||
def test_derive_master_SK():
|
@pytest.mark.parametrize(
|
||||||
for test in test_vectors:
|
'test',
|
||||||
seed = bytes.fromhex(test['seed'])
|
test_vectors
|
||||||
master_SK = test['master_SK']
|
)
|
||||||
assert derive_master_SK(seed=seed) == master_SK
|
def test_hkdf_mod_r(test) -> None:
|
||||||
|
seed = bytes.fromhex(test['seed'])
|
||||||
|
assert bls.KeyGen(seed) == _HKDF_mod_r(IKM=seed)
|
||||||
|
|
||||||
|
|
||||||
def test_derive_child_SK():
|
@pytest.mark.parametrize(
|
||||||
|
'seed',
|
||||||
|
[b'\x00' * 32]
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'key_info',
|
||||||
|
[b'\x00' * 32, b'\x01\x23\x45\x67\x89\xAB\xBC\xDE\xFF', b'\xFF' * 16]
|
||||||
|
)
|
||||||
|
def test_hkdf_mod_r_key_info(seed: bytes, key_info: bytes) -> None:
|
||||||
|
assert bls.KeyGen(seed, key_info) == _HKDF_mod_r(IKM=seed, key_info=key_info)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'test',
|
||||||
|
test_vectors
|
||||||
|
)
|
||||||
|
def test_derive_master_SK(test) -> None:
|
||||||
|
seed = bytes.fromhex(test['seed'])
|
||||||
|
master_SK = test['master_SK']
|
||||||
|
assert derive_master_SK(seed=seed) == master_SK
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'test',
|
||||||
|
test_vectors
|
||||||
|
)
|
||||||
|
def test_derive_child_SK(test) -> None:
|
||||||
|
parent_SK = test['master_SK']
|
||||||
|
index = test['child_index']
|
||||||
|
child_SK = test['child_SK']
|
||||||
|
assert derive_child_SK(parent_SK=parent_SK, index=index) == child_SK
|
||||||
for test in test_vectors:
|
for test in test_vectors:
|
||||||
parent_SK = test['master_SK']
|
parent_SK = test['master_SK']
|
||||||
index = test['child_index']
|
index = test['child_index']
|
||||||
|
@ -2,27 +2,27 @@
|
|||||||
"kdf_tests": [
|
"kdf_tests": [
|
||||||
{
|
{
|
||||||
"seed": "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04",
|
"seed": "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04",
|
||||||
"master_SK": 12513733877922233913083619867448865075222526338446857121953625441395088009793,
|
"master_SK": 5399117110774477986698372024995405256382522670366369834617409486544348441851,
|
||||||
"child_index": 0,
|
"child_index": 0,
|
||||||
"child_SK": 7419543105316279183937430842449358701327973165530407166294956473095303972104
|
"child_SK": 11812940737387919040225825939013910852517748782307378293770044673328955938106
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"seed": "3141592653589793238462643383279502884197169399375105820974944592",
|
"seed": "3141592653589793238462643383279502884197169399375105820974944592",
|
||||||
"master_SK": 46029459550803682895343812821003080589696405386150182061394330539196052371668,
|
"master_SK": 36167147331491996618072159372207345412841461318189449162487002442599770291484,
|
||||||
"child_index": 3141592653,
|
"child_index": 3141592653,
|
||||||
"child_SK": 43469287647733616183478983885105537266268532274998688773496918571876759327260
|
"child_SK": 41787458189896526028601807066547832426569899195138584349427756863968330588237
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"seed": "0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC00",
|
"seed": "0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC00",
|
||||||
"master_SK": 45379166311535261329029945990467475187325618028073620882733843918126031931161,
|
"master_SK": 13904094584487173309420026178174172335998687531503061311232927109397516192843,
|
||||||
"child_index": 4294967295,
|
"child_index": 4294967295,
|
||||||
"child_SK": 46475244006136701976831062271444482037125148379128114617927607151318277762946
|
"child_SK": 12482522899285304316694838079579801944734479969002030150864436005368716366140
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"seed": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
|
"seed": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
|
||||||
"master_SK": 31740500954810567003972734830331791822878290325762596213711963944729383643688,
|
"master_SK": 44010626067374404458092393860968061149521094673473131545188652121635313364506,
|
||||||
"child_index": 42,
|
"child_index": 42,
|
||||||
"child_SK": 51041472511529980987749393477251359993058329222191894694692317000136653813011
|
"child_SK": 4011524214304750350566588165922015929937602165683407445189263506512578573606
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user