Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test vectors for ZIP 32 arbitrary key derivation #103

Merged
merged 2 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions regenerate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions test-vectors/json/zip_0032_arbitrary.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
["From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0032_arbitrary.py"],
["sk, c"],
Copy link
Contributor

@daira daira Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the other test vectors I think we normally include the input (in this case the context, and the account id in the case of account-specific key derivation), not just the output. For example see test-vectors/rust/f4jumble.rs or test-vectors/rust/orchard_group_hash.rs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test vectors follow how the existing ZIP 32 test vectors work for Sapling and Orchard.

["e9da8806409dc3c3ebd1fc2a71c879c13dd7aa93ede803bf1a83414b9d3b158a", "65a748f2905f7a8aab9f3d02f1b26c3d65c82994ce59a086d4c651d8a81cec51"],
["e8409aaa832cc2378f2badeb77150562153742fee876dcf4783a6ccd119da66a", "cc084922a0ead2da5338bd82200a1946bc8585b8d9ee416df6a09a71ab0e5b58"],
["464f90a364cff805fee93a85b72f4894ce4e1358dcdc1e61a3d430301c60910e", "f9d2544a5528ae6bd9f036f42f9f05d83dff507aeb2a8141af11d9f167e221ae"],
["fc4b6e93b0e42f7a762ca0c6522ccd1045cab506b372452af7306c87389ab62c", "e89bf2ed73f5e0887542e36793fac82c508ab5d99198578227b241fbac198429"]
]
40 changes: 40 additions & 0 deletions test-vectors/rust/zip_0032_arbitrary.rs
Original file line number Diff line number Diff line change
@@ -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
],
},
];
8 changes: 8 additions & 0 deletions test-vectors/zcash/zip_0032_arbitrary.json
Original file line number Diff line number Diff line change
@@ -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"]
]
21 changes: 7 additions & 14 deletions zcash_test_vectors/orchard/key_components.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -55,26 +54,20 @@ def __init__(self, data):


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):
Expand Down
92 changes: 92 additions & 0 deletions zcash_test_vectors/zip_0032.py
Original file line number Diff line number Diff line change
@@ -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