Add orchard_key_components.py.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
parent
99e7184038
commit
8ce3cfb8d9
|
@ -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()
|
Loading…
Reference in New Issue