Merge pull request #103 from zcash/arbitrary-key-derivation
Test vectors for ZIP 32 arbitrary key derivation
This commit is contained in:
commit
53cc8e25ea
|
@ -41,6 +41,7 @@ f4jumble_long = "zcash_test_vectors.f4jumble:long_test_vectors"
|
|||
unified_address = "zcash_test_vectors.unified_address:main"
|
||||
unified_full_viewing_keys = "zcash_test_vectors.unified_full_viewing_keys:main"
|
||||
unified_incoming_viewing_keys = "zcash_test_vectors.unified_incoming_viewing_keys:main"
|
||||
zip_0032_arbitrary = "zcash_test_vectors.zip_0032:arbitrary_key_derivation_tvs"
|
||||
zip_0143 = "zcash_test_vectors.zip_0143:main"
|
||||
zip_0243 = "zcash_test_vectors.zip_0243:main"
|
||||
zip_0244 = "zcash_test_vectors.zip_0244:main"
|
||||
|
|
|
@ -45,6 +45,7 @@ case "$2" in
|
|||
unified_address
|
||||
unified_full_viewing_keys
|
||||
unified_incoming_viewing_keys
|
||||
zip_0032_arbitrary
|
||||
zip_0143
|
||||
zip_0243
|
||||
zip_0244
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[
|
||||
["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0032_arbitrary.py"],
|
||||
["sk, c"],
|
||||
["e9da8806409dc3c3ebd1fc2a71c879c13dd7aa93ede803bf1a83414b9d3b158a", "65a748f2905f7a8aab9f3d02f1b26c3d65c82994ce59a086d4c651d8a81cec51"],
|
||||
["e8409aaa832cc2378f2badeb77150562153742fee876dcf4783a6ccd119da66a", "cc084922a0ead2da5338bd82200a1946bc8585b8d9ee416df6a09a71ab0e5b58"],
|
||||
["464f90a364cff805fee93a85b72f4894ce4e1358dcdc1e61a3d430301c60910e", "f9d2544a5528ae6bd9f036f42f9f05d83dff507aeb2a8141af11d9f167e221ae"],
|
||||
["fc4b6e93b0e42f7a762ca0c6522ccd1045cab506b372452af7306c87389ab62c", "e89bf2ed73f5e0887542e36793fac82c508ab5d99198578227b241fbac198429"]
|
||||
]
|
|
@ -0,0 +1,40 @@
|
|||
struct TestVector {
|
||||
sk: [u8; 32],
|
||||
c: [u8; 32],
|
||||
};
|
||||
|
||||
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0032_arbitrary.py
|
||||
let test_vectors = vec![
|
||||
TestVector {
|
||||
sk: [
|
||||
0xe9, 0xda, 0x88, 0x06, 0x40, 0x9d, 0xc3, 0xc3, 0xeb, 0xd1, 0xfc, 0x2a, 0x71, 0xc8, 0x79, 0xc1, 0x3d, 0xd7, 0xaa, 0x93, 0xed, 0xe8, 0x03, 0xbf, 0x1a, 0x83, 0x41, 0x4b, 0x9d, 0x3b, 0x15, 0x8a
|
||||
],
|
||||
c: [
|
||||
0x65, 0xa7, 0x48, 0xf2, 0x90, 0x5f, 0x7a, 0x8a, 0xab, 0x9f, 0x3d, 0x02, 0xf1, 0xb2, 0x6c, 0x3d, 0x65, 0xc8, 0x29, 0x94, 0xce, 0x59, 0xa0, 0x86, 0xd4, 0xc6, 0x51, 0xd8, 0xa8, 0x1c, 0xec, 0x51
|
||||
],
|
||||
},
|
||||
TestVector {
|
||||
sk: [
|
||||
0xe8, 0x40, 0x9a, 0xaa, 0x83, 0x2c, 0xc2, 0x37, 0x8f, 0x2b, 0xad, 0xeb, 0x77, 0x15, 0x05, 0x62, 0x15, 0x37, 0x42, 0xfe, 0xe8, 0x76, 0xdc, 0xf4, 0x78, 0x3a, 0x6c, 0xcd, 0x11, 0x9d, 0xa6, 0x6a
|
||||
],
|
||||
c: [
|
||||
0xcc, 0x08, 0x49, 0x22, 0xa0, 0xea, 0xd2, 0xda, 0x53, 0x38, 0xbd, 0x82, 0x20, 0x0a, 0x19, 0x46, 0xbc, 0x85, 0x85, 0xb8, 0xd9, 0xee, 0x41, 0x6d, 0xf6, 0xa0, 0x9a, 0x71, 0xab, 0x0e, 0x5b, 0x58
|
||||
],
|
||||
},
|
||||
TestVector {
|
||||
sk: [
|
||||
0x46, 0x4f, 0x90, 0xa3, 0x64, 0xcf, 0xf8, 0x05, 0xfe, 0xe9, 0x3a, 0x85, 0xb7, 0x2f, 0x48, 0x94, 0xce, 0x4e, 0x13, 0x58, 0xdc, 0xdc, 0x1e, 0x61, 0xa3, 0xd4, 0x30, 0x30, 0x1c, 0x60, 0x91, 0x0e
|
||||
],
|
||||
c: [
|
||||
0xf9, 0xd2, 0x54, 0x4a, 0x55, 0x28, 0xae, 0x6b, 0xd9, 0xf0, 0x36, 0xf4, 0x2f, 0x9f, 0x05, 0xd8, 0x3d, 0xff, 0x50, 0x7a, 0xeb, 0x2a, 0x81, 0x41, 0xaf, 0x11, 0xd9, 0xf1, 0x67, 0xe2, 0x21, 0xae
|
||||
],
|
||||
},
|
||||
TestVector {
|
||||
sk: [
|
||||
0xfc, 0x4b, 0x6e, 0x93, 0xb0, 0xe4, 0x2f, 0x7a, 0x76, 0x2c, 0xa0, 0xc6, 0x52, 0x2c, 0xcd, 0x10, 0x45, 0xca, 0xb5, 0x06, 0xb3, 0x72, 0x45, 0x2a, 0xf7, 0x30, 0x6c, 0x87, 0x38, 0x9a, 0xb6, 0x2c
|
||||
],
|
||||
c: [
|
||||
0xe8, 0x9b, 0xf2, 0xed, 0x73, 0xf5, 0xe0, 0x88, 0x75, 0x42, 0xe3, 0x67, 0x93, 0xfa, 0xc8, 0x2c, 0x50, 0x8a, 0xb5, 0xd9, 0x91, 0x98, 0x57, 0x82, 0x27, 0xb2, 0x41, 0xfb, 0xac, 0x19, 0x84, 0x29
|
||||
],
|
||||
},
|
||||
];
|
|
@ -0,0 +1,8 @@
|
|||
[
|
||||
["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0032_arbitrary.py"],
|
||||
["sk, c"],
|
||||
["8a153b9d4b41831abf03e8ed93aad73dc179c8712afcd1ebc3c39d400688dae9", "51ec1ca8d851c6d486a059ce9429c8653d6cb2f1023d9fab8a7a5f90f248a765"],
|
||||
["6aa69d11cd6c3a78f4dc76e8fe42371562051577ebad2b8f37c22c83aa9a40e8", "585b0eab719aa0f66d41eed9b88585bc46190a2082bd3853dad2eaa0224908cc"],
|
||||
["0e91601c3030d4a3611edcdc58134ece94482fb7853ae9fe05f8cf64a3904f46", "ae21e267f1d911af41812aeb7a50ff3dd8059f2ff436f0d96bae28554a54d2f9"],
|
||||
["2cb69a38876c30f72a4572b306b5ca4510cd2c52c6a02c767a2fe4b0936e4bfc", "298419acfb41b22782579891d9b58a502cc8fa9367e3427588e0f573edf29be8"]
|
||||
]
|
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/env python3
|
||||
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
|
||||
|
||||
from hashlib import blake2b
|
||||
|
||||
from ..ff1 import ff1_aes256_encrypt
|
||||
from ..sapling.key_components import prf_expand
|
||||
from ..zip_0032 import CKDh, HardenedOnlyContext, MKGh
|
||||
|
||||
from .generators import NULLIFIER_K_BASE, SPENDING_KEY_BASE, group_hash
|
||||
from .pallas import Fp, Scalar, Point
|
||||
|
@ -55,26 +54,20 @@ class SpendingKey(object):
|
|||
|
||||
|
||||
class ExtendedSpendingKey(SpendingKey):
|
||||
Orchard = HardenedOnlyContext(b'ZcashIP32Orchard', b'\x81')
|
||||
|
||||
def __init__(self, chaincode, data):
|
||||
SpendingKey.__init__(self, data)
|
||||
self.chaincode = chaincode
|
||||
|
||||
@classmethod
|
||||
def master(cls, S):
|
||||
digest = blake2b(person=b'ZcashIP32Orchard')
|
||||
digest.update(S)
|
||||
I = digest.digest()
|
||||
I_L = I[:32]
|
||||
I_R = I[32:]
|
||||
return cls(I_R, I_L)
|
||||
(sk, chaincode) = MKGh(cls.Orchard, S)
|
||||
return cls(chaincode, sk)
|
||||
|
||||
def child(self, i):
|
||||
assert 0x80000000 <= i and i <= 0xFFFFFFFF
|
||||
|
||||
I = prf_expand(self.chaincode, b'\x81' + self.data + i2leosp(32, i))
|
||||
I_L = I[:32]
|
||||
I_R = I[32:]
|
||||
return self.__class__(I_R, I_L)
|
||||
(sk_i, c_i) = CKDh(self.Orchard, self.data, self.chaincode, i)
|
||||
return self.__class__(c_i, sk_i)
|
||||
|
||||
|
||||
class FullViewingKey(object):
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
from hashlib import blake2b
|
||||
|
||||
from .sapling.key_components import prf_expand
|
||||
from .utils import i2leosp
|
||||
|
||||
from .hd_common import hardened
|
||||
from .output import render_args, render_tv
|
||||
|
||||
class HardenedOnlyContext(object):
|
||||
def __init__(self, MKGDomain, CKDDomain):
|
||||
assert type(MKGDomain) == bytes
|
||||
assert len(MKGDomain) == 16
|
||||
assert type(CKDDomain) == bytes
|
||||
assert len(CKDDomain) == 1
|
||||
|
||||
self.MKGDomain = MKGDomain
|
||||
self.CKDDomain = CKDDomain
|
||||
|
||||
def MKGh(Context, IKM):
|
||||
assert type(Context) == HardenedOnlyContext
|
||||
|
||||
digest = blake2b(person=Context.MKGDomain)
|
||||
digest.update(IKM)
|
||||
I = digest.digest()
|
||||
I_L = I[:32]
|
||||
I_R = I[32:]
|
||||
return (I_L, I_R)
|
||||
|
||||
def CKDh(Context, sk_par, c_par, i):
|
||||
assert type(Context) == HardenedOnlyContext
|
||||
assert 0x80000000 <= i and i <= 0xFFFFFFFF
|
||||
|
||||
I = prf_expand(c_par, Context.CKDDomain + sk_par + i2leosp(32, i))
|
||||
I_L = I[:32]
|
||||
I_R = I[32:]
|
||||
return (I_L, I_R)
|
||||
|
||||
class ArbitraryKey(object):
|
||||
Arbitrary = HardenedOnlyContext(b'ZcashArbitraryKD', b'\xAB')
|
||||
|
||||
def __init__(self, sk, chaincode):
|
||||
self.sk = sk
|
||||
self.chaincode = chaincode
|
||||
|
||||
@classmethod
|
||||
def master(cls, ContextString, S):
|
||||
length_ContextString = len(ContextString)
|
||||
length_S = len(S)
|
||||
|
||||
assert length_ContextString <= 252
|
||||
assert 32 <= length_S <= 252
|
||||
|
||||
(sk, chaincode) = MKGh(
|
||||
cls.Arbitrary,
|
||||
bytes([length_ContextString]) + ContextString + bytes([length_S]) + S,
|
||||
)
|
||||
return cls(sk, chaincode)
|
||||
|
||||
def child(self, i):
|
||||
(sk_i, c_i) = CKDh(self.Arbitrary, self.sk, self.chaincode, i)
|
||||
return self.__class__(sk_i, c_i)
|
||||
|
||||
|
||||
def arbitrary_key_derivation_tvs():
|
||||
args = render_args()
|
||||
|
||||
context_string = b'Zcash test vectors'
|
||||
seed = bytes(range(32))
|
||||
m = ArbitraryKey.master(context_string, seed)
|
||||
m_1h = m.child(hardened(1))
|
||||
m_1h_2h = m_1h.child(hardened(2))
|
||||
m_1h_2h_3h = m_1h_2h.child(hardened(3))
|
||||
|
||||
keys = [m, m_1h, m_1h_2h, m_1h_2h_3h]
|
||||
|
||||
test_vectors = [
|
||||
{
|
||||
'sk' : k.sk,
|
||||
'c' : k.chaincode
|
||||
}
|
||||
for k in keys
|
||||
]
|
||||
|
||||
render_tv(
|
||||
args,
|
||||
'zip_0032_arbitrary',
|
||||
(
|
||||
('sk', '[u8; 32]'),
|
||||
('c', '[u8; 32]'),
|
||||
),
|
||||
test_vectors,
|
||||
)
|
Loading…
Reference in New Issue