zcash-test-vectors/sapling_key_components.py

166 lines
4.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
from binascii import hexlify
from pyblake2 import blake2b, blake2s
2018-05-17 16:57:11 -07:00
from sapling_generators import PROVING_KEY_BASE, SPENDING_KEY_BASE, group_hash
from sapling_jubjub import Fr
from sapling_notes import note_commit
from sapling_utils import chunk, leos2bsp
#
# PRFs and hashes
#
def prf_expand(sk, t):
digest = blake2b(person=b'Zcash_ExpandSeed')
digest.update(sk)
digest.update(t)
return digest.digest()
def crh_ivk(ak, nk):
digest = blake2s(person=b'Zcashivk')
digest.update(ak)
digest.update(nk)
ivk = digest.digest()
ivk = ivk[:31] + bytes([ivk[31] & 0b00000111])
return ivk
#
# Key components
#
def cached(f):
def wrapper(self):
if not hasattr(self, '_cached'):
self._cached = {}
if not self._cached.get(f):
self._cached[f] = f(self)
return self._cached[f]
return wrapper
class SpendingKey(object):
def __init__(self, data):
self.data = data
@cached
def ask(self):
return Fr.from_bytes(prf_expand(self.data, b'\0'))
@cached
def nsk(self):
return Fr.from_bytes(prf_expand(self.data, b'\1'))
@cached
def ovk(self):
return prf_expand(self.data, b'\2')[:32]
@cached
def ak(self):
return SPENDING_KEY_BASE * self.ask()
@cached
def nk(self):
return PROVING_KEY_BASE * self.nsk()
@cached
def ivk(self):
return Fr.from_bytes(crh_ivk(bytes(self.ak()), bytes(self.nk())))
@cached
def default_d(self):
i = 0
while True:
d = prf_expand(self.data, bytes([3, i]))[:11]
if group_hash(b'Zcash_gd', d):
return d
i += 1
2018-05-17 23:00:45 -07:00
assert i < 256
@cached
def default_pkd(self):
return group_hash(b'Zcash_gd', self.default_d()) * self.ivk()
def main():
print('''
struct TestVector {
sk: [u8; 32],
ask: [u8; 32],
nsk: [u8; 32],
ovk: [u8; 32],
ak: [u8; 32],
nk: [u8; 32],
ivk: [u8; 32],
default_d: [u8; 11],
default_pk_d: [u8; 32],
note_v: u64,
note_r: [u8; 32],
note_cm: [u8; 32],
};
let test_vectors = vec![''')
for i in range(0, 10):
sk = SpendingKey(bytes([i] * 32))
note_v = (2548793025584392057432895043257984320*i) % 2**64
note_r = Fr(8890123457840276890326754358439057438290574382905).exp(i+1)
note_cm = note_commit(
note_r,
leos2bsp(bytes(group_hash(b'Zcash_gd', sk.default_d()))),
leos2bsp(bytes(sk.default_pkd())),
note_v)
print(''' TestVector {
sk: [
%s
],
ask: [
%s
],
nsk: [
%s
],
ovk: [
%s
],
ak: [
%s
],
nk: [
%s
],
ivk: [
%s
],
default_d: [
%s
],
default_pk_d: [
%s
],
note_v: %s,
note_r: [
%s
],
note_cm: [
%s
],
},''' % (
2018-05-17 23:00:45 -07:00
chunk(hexlify(sk.data)),
chunk(hexlify(bytes(sk.ask()))),
chunk(hexlify(bytes(sk.nsk()))),
chunk(hexlify(sk.ovk())),
chunk(hexlify(bytes(sk.ak()))),
chunk(hexlify(bytes(sk.nk()))),
chunk(hexlify(bytes(sk.ivk()))),
chunk(hexlify(sk.default_d())),
chunk(hexlify(bytes(sk.default_pkd()))),
note_v,
chunk(hexlify(bytes(note_r))),
chunk(hexlify(bytes(note_cm.u))),
2018-05-17 23:00:45 -07:00
))
print(' ];')
if __name__ == '__main__':
main()