Add orchard_key_components.py.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2021-05-06 15:58:38 +01:00 committed by therealyingtong
parent 99e7184038
commit 8ce3cfb8d9
1 changed files with 144 additions and 0 deletions

144
orchard_key_components.py Normal file
View File

@ -0,0 +1,144 @@
#!/usr/bin/env python3
import sys; assert sys.version_info[0] >= 3, "Python 3 required."
from pyblake2 import blake2b, blake2s
from orchard_generators import SPENDING_KEY_BASE, group_hash
from orchard_pallas import Fp, Scalar, Point
from orchard_merkle_tree import MERKLE_DEPTH
from orchard_commitments import commit_ivk, note_commit
from utils import leos2bsp, leos2ip, i2leosp
from tv_output import render_args, render_tv
#
# Utilities
#
def to_scalar(buf):
return Scalar(leos2ip(buf))
def to_base(buf):
return Fp(leos2ip(buf))
#
# PRFs and hashes
#
def prf_expand(sk, t):
digest = blake2b(person=b'Zcash_ExpandSeed')
digest.update(sk)
digest.update(t)
return digest.digest()
def diversify_hash(d):
P = group_hash(b'z.cash:Orchard-gd', d)
if P == Point.identity():
P = group_hash(b'z.cash:Orchard-gd', b'')
return P
#
# Key components
#
class SpendingKey:
def __init__(self, data):
self.data = data
self.ask = to_scalar(prf_expand(self.data, b'\x06'))
self.nk = to_base(prf_expand(self.data, b'\x07'))
self.rivk = to_scalar(prf_expand(self.data, b'\x08'))
if self.ask == Scalar.ZERO:
raise ValueError("invalid spending key")
self.akP = SPENDING_KEY_BASE * self.ask
if bytes(self.akP)[-1] & 0x80 != 0:
self.ask = -self.ask
self.ak = self.akP.extract()
if commit_ivk(self.rivk, self.ak, self.nk) is None:
raise ValueError("invalid spending key")
class FullViewingKey(object):
def __init__(self, sk):
(self.rivk, self.ak, self.nk) = (sk.rivk, sk.ak, sk.nk)
K = i2leosp(256, self.rivk.s)
R = prf_expand(K, b'\x82' + i2leosp(256, self.ak.s) + i2leosp(256, self.nk.s))
self.dk = R[:32]
self.ovk = R[32:]
def ivk(self):
return commit_ivk(self.rivk, self.ak, self.nk)
def ovk(self):
return prf_expand(self.data, b'\x02')[:32]
def default_d(self):
return i2leosp(88, 1337)
def default_pkd(self):
return diversify_hash(self.default_d()) * self.ivk()
def main():
args = render_args()
test_vectors = []
for i in range(0, 10):
sys.stdout.write(".")
sys.stdout.flush()
sk = SpendingKey(bytes([i] * 32))
fvk = FullViewingKey(sk)
note_v = (2548793025584392057432895043257984320*i) % 2**64
note_r = Scalar(8890123457840276890326754358439057438290574382905).exp(i+1)
note_rho = Fp(342358729643275392567239275209835729829*i)
note_psi = Fp(432592604358294371936572103719358723958*i)
note_cm = note_commit(
note_r,
leos2bsp(bytes(diversify_hash(fvk.default_d()))),
leos2bsp(bytes(fvk.default_pkd())),
note_v,
note_rho,
note_psi)
note_nf = b"0"*32 #note_nullifier(fvk.nk(), note_cm)
test_vectors.append({
'sk': sk.data,
'ask': bytes(sk.ask),
'ovk': fvk.ovk,
'rivk': bytes(fvk.rivk),
'ak': bytes(fvk.ak),
'nk': bytes(fvk.nk),
'ivk': bytes(fvk.ivk()),
'default_d': fvk.default_d(),
'default_pk_d': bytes(fvk.default_pkd()),
'note_v': note_v,
'note_r': bytes(note_r),
'note_cmx': bytes(note_cm.extract()),
'note_nf': note_nf,
})
render_tv(
args,
'orchard_key_components',
(
('sk', '[u8; 32]'),
('ask', '[u8; 32]'),
('ovk', '[u8; 32]'),
('rivk', '[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_cmx', '[u8; 32]'),
('note_nf', '[u8; 32]'),
),
test_vectors,
)
if __name__ == '__main__':
main()