1623 lines
75 KiB
Rust
1623 lines
75 KiB
Rust
//! Implementation of [ZIP 32] for hierarchical deterministic key management.
|
|
//!
|
|
//! [ZIP 32]: https://zips.z.cash/zip-0032
|
|
|
|
use aes::Aes256;
|
|
use blake2b_simd::Params as Blake2bParams;
|
|
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
|
|
use fpe::ff1::{BinaryNumeralString, FF1};
|
|
use std::convert::TryInto;
|
|
use std::ops::AddAssign;
|
|
use subtle::{Choice, ConditionallySelectable};
|
|
|
|
use crate::{
|
|
constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
|
|
sapling::{Diversifier, PaymentAddress, ViewingKey},
|
|
};
|
|
use std::io::{self, Read, Write};
|
|
|
|
use crate::{
|
|
keys::{prf_expand, prf_expand_vec, OutgoingViewingKey},
|
|
sapling::keys::{ExpandedSpendingKey, FullViewingKey},
|
|
};
|
|
|
|
pub const ZIP32_SAPLING_MASTER_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Sapling";
|
|
pub const ZIP32_SAPLING_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashSaplingFVFP";
|
|
pub const ZIP32_SAPLING_INT_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingInt";
|
|
|
|
/// A type-safe wrapper for account identifiers.
|
|
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct AccountId(u32);
|
|
|
|
impl From<u32> for AccountId {
|
|
fn from(id: u32) -> Self {
|
|
Self(id)
|
|
}
|
|
}
|
|
|
|
impl From<AccountId> for u32 {
|
|
fn from(id: AccountId) -> Self {
|
|
id.0
|
|
}
|
|
}
|
|
|
|
impl ConditionallySelectable for AccountId {
|
|
fn conditional_select(a0: &Self, a1: &Self, c: Choice) -> Self {
|
|
AccountId(u32::conditional_select(&a0.0, &a1.0, c))
|
|
}
|
|
}
|
|
|
|
// Common helper functions
|
|
|
|
fn derive_child_ovk(parent: &OutgoingViewingKey, i_l: &[u8]) -> OutgoingViewingKey {
|
|
let mut ovk = [0u8; 32];
|
|
ovk.copy_from_slice(&prf_expand_vec(i_l, &[&[0x15], &parent.0]).as_bytes()[..32]);
|
|
OutgoingViewingKey(ovk)
|
|
}
|
|
|
|
// ZIP 32 structures
|
|
|
|
/// A Sapling full viewing key fingerprint
|
|
struct FvkFingerprint([u8; 32]);
|
|
|
|
impl From<&FullViewingKey> for FvkFingerprint {
|
|
fn from(fvk: &FullViewingKey) -> Self {
|
|
let mut h = Blake2bParams::new()
|
|
.hash_length(32)
|
|
.personal(ZIP32_SAPLING_FVFP_PERSONALIZATION)
|
|
.to_state();
|
|
h.update(&fvk.to_bytes());
|
|
let mut fvfp = [0u8; 32];
|
|
fvfp.copy_from_slice(h.finalize().as_bytes());
|
|
FvkFingerprint(fvfp)
|
|
}
|
|
}
|
|
|
|
/// A Sapling full viewing key tag
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
struct FvkTag([u8; 4]);
|
|
|
|
impl FvkFingerprint {
|
|
fn tag(&self) -> FvkTag {
|
|
let mut tag = [0u8; 4];
|
|
tag.copy_from_slice(&self.0[..4]);
|
|
FvkTag(tag)
|
|
}
|
|
}
|
|
|
|
impl FvkTag {
|
|
fn master() -> Self {
|
|
FvkTag([0u8; 4])
|
|
}
|
|
}
|
|
|
|
/// A child index for a derived key
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum ChildIndex {
|
|
NonHardened(u32),
|
|
Hardened(u32), // Hardened(n) == n + (1 << 31) == n' in path notation
|
|
}
|
|
|
|
impl ChildIndex {
|
|
pub fn from_index(i: u32) -> Self {
|
|
match i {
|
|
n if n >= (1 << 31) => ChildIndex::Hardened(n - (1 << 31)),
|
|
n => ChildIndex::NonHardened(n),
|
|
}
|
|
}
|
|
|
|
fn master() -> Self {
|
|
ChildIndex::from_index(0)
|
|
}
|
|
|
|
fn value(&self) -> u32 {
|
|
match *self {
|
|
ChildIndex::Hardened(i) => i + (1 << 31),
|
|
ChildIndex::NonHardened(i) => i,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A BIP-32 chain code
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub struct ChainCode([u8; 32]);
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub struct DiversifierIndex(pub [u8; 11]);
|
|
|
|
impl Default for DiversifierIndex {
|
|
fn default() -> Self {
|
|
DiversifierIndex::new()
|
|
}
|
|
}
|
|
|
|
impl DiversifierIndex {
|
|
pub fn new() -> Self {
|
|
DiversifierIndex([0; 11])
|
|
}
|
|
|
|
pub fn increment(&mut self) -> Result<(), ()> {
|
|
for k in 0..11 {
|
|
self.0[k] = self.0[k].wrapping_add(1);
|
|
if self.0[k] != 0 {
|
|
// No overflow
|
|
return Ok(());
|
|
}
|
|
}
|
|
// Overflow
|
|
Err(())
|
|
}
|
|
}
|
|
|
|
/// A key used to derive diversifiers for a particular child key
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub struct DiversifierKey(pub [u8; 32]);
|
|
|
|
impl DiversifierKey {
|
|
pub fn master(sk_m: &[u8]) -> Self {
|
|
let mut dk_m = [0u8; 32];
|
|
dk_m.copy_from_slice(&prf_expand(sk_m, &[0x10]).as_bytes()[..32]);
|
|
DiversifierKey(dk_m)
|
|
}
|
|
|
|
fn derive_child(&self, i_l: &[u8]) -> Self {
|
|
let mut dk = [0u8; 32];
|
|
dk.copy_from_slice(&prf_expand_vec(i_l, &[&[0x16], &self.0]).as_bytes()[..32]);
|
|
DiversifierKey(dk)
|
|
}
|
|
|
|
fn try_diversifier_internal(ff: &FF1<Aes256>, j: DiversifierIndex) -> Option<Diversifier> {
|
|
// Generate d_j
|
|
let enc = ff
|
|
.encrypt(&[], &BinaryNumeralString::from_bytes_le(&j.0[..]))
|
|
.unwrap();
|
|
let mut d_j = [0; 11];
|
|
d_j.copy_from_slice(&enc.to_bytes_le());
|
|
let diversifier = Diversifier(d_j);
|
|
|
|
// validate that the generated diversifier maps to a jubjub subgroup point.
|
|
diversifier.g_d().map(|_| diversifier)
|
|
}
|
|
|
|
/// Attempts to produce a diversifier at the given index. Returns None
|
|
/// if the index does not produce a valid diversifier.
|
|
pub fn diversifier(&self, j: DiversifierIndex) -> Option<Diversifier> {
|
|
let ff = FF1::<Aes256>::new(&self.0, 2).unwrap();
|
|
Self::try_diversifier_internal(&ff, j)
|
|
}
|
|
|
|
/// Returns the diversifier index to which this key maps the given diversifier.
|
|
///
|
|
/// This method cannot be used to verify whether the diversifier was originally
|
|
/// generated with this diversifier key, because all valid diversifiers can be
|
|
/// produced by all diversifier keys.
|
|
pub fn diversifier_index(&self, d: &Diversifier) -> DiversifierIndex {
|
|
let ff = FF1::<Aes256>::new(&self.0, 2).unwrap();
|
|
let dec = ff
|
|
.decrypt(&[], &BinaryNumeralString::from_bytes_le(&d.0[..]))
|
|
.unwrap();
|
|
let mut j = DiversifierIndex::new();
|
|
j.0.copy_from_slice(&dec.to_bytes_le());
|
|
j
|
|
}
|
|
|
|
/// Returns the first index starting from j that generates a valid
|
|
/// diversifier, along with the corresponding diversifier. Returns
|
|
/// `None` if the diversifier space contains no valid diversifiers
|
|
/// at or above the specified diversifier index.
|
|
pub fn find_diversifier(
|
|
&self,
|
|
mut j: DiversifierIndex,
|
|
) -> Option<(DiversifierIndex, Diversifier)> {
|
|
let ff = FF1::<Aes256>::new(&self.0, 2).unwrap();
|
|
loop {
|
|
match Self::try_diversifier_internal(&ff, j) {
|
|
Some(d_j) => return Some((j, d_j)),
|
|
None => {
|
|
if j.increment().is_err() {
|
|
return None;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Attempt to produce a payment address given the specified diversifier
|
|
/// index, and return None if the specified index does not produce a valid
|
|
/// diversifier.
|
|
pub fn sapling_address(
|
|
fvk: &FullViewingKey,
|
|
dk: &DiversifierKey,
|
|
j: DiversifierIndex,
|
|
) -> Option<PaymentAddress> {
|
|
dk.diversifier(j)
|
|
.and_then(|d_j| fvk.vk.to_payment_address(d_j))
|
|
}
|
|
|
|
/// Search the diversifier space starting at diversifier index `j` for
|
|
/// one which will produce a valid diversifier, and return the payment address
|
|
/// constructed using that diversifier along with the index at which the
|
|
/// valid diversifier was found.
|
|
pub fn sapling_find_address(
|
|
fvk: &FullViewingKey,
|
|
dk: &DiversifierKey,
|
|
j: DiversifierIndex,
|
|
) -> Option<(DiversifierIndex, PaymentAddress)> {
|
|
let (j, d_j) = dk.find_diversifier(j)?;
|
|
fvk.vk.to_payment_address(d_j).map(|addr| (j, addr))
|
|
}
|
|
|
|
/// Returns the payment address corresponding to the smallest valid diversifier
|
|
/// index, along with that index.
|
|
pub fn sapling_default_address(
|
|
fvk: &FullViewingKey,
|
|
dk: &DiversifierKey,
|
|
) -> (DiversifierIndex, PaymentAddress) {
|
|
// This unwrap is safe, if you have to search the 2^88 space of
|
|
// diversifiers it'll never return anyway.
|
|
sapling_find_address(fvk, dk, DiversifierIndex::new()).unwrap()
|
|
}
|
|
|
|
/// Returns the internal full viewing key and diversifier key
|
|
/// for the provided external FVK = (ak, nk, ovk) and dk encoded
|
|
/// in a [Unified FVK].
|
|
///
|
|
/// [Unified FVK]: https://zips.z.cash/zip-0316#encoding-of-unified-full-incoming-viewing-keys
|
|
pub fn sapling_derive_internal_fvk(
|
|
fvk: &FullViewingKey,
|
|
dk: &DiversifierKey,
|
|
) -> (FullViewingKey, DiversifierKey) {
|
|
let i = {
|
|
let mut h = Blake2bParams::new()
|
|
.hash_length(32)
|
|
.personal(crate::zip32::ZIP32_SAPLING_INT_PERSONALIZATION)
|
|
.to_state();
|
|
h.update(&fvk.to_bytes());
|
|
h.update(&dk.0);
|
|
h.finalize()
|
|
};
|
|
let i_nsk = jubjub::Fr::from_bytes_wide(prf_expand(i.as_bytes(), &[0x17]).as_array());
|
|
let r = prf_expand(i.as_bytes(), &[0x18]);
|
|
let r = r.as_bytes();
|
|
// PROOF_GENERATION_KEY_GENERATOR = \mathcal{H}^Sapling
|
|
let nk_internal = PROOF_GENERATION_KEY_GENERATOR * i_nsk + fvk.vk.nk;
|
|
let dk_internal = DiversifierKey(r[..32].try_into().unwrap());
|
|
let ovk_internal = OutgoingViewingKey(r[32..].try_into().unwrap());
|
|
|
|
(
|
|
FullViewingKey {
|
|
vk: ViewingKey {
|
|
ak: fvk.vk.ak,
|
|
nk: nk_internal,
|
|
},
|
|
ovk: ovk_internal,
|
|
},
|
|
dk_internal,
|
|
)
|
|
}
|
|
|
|
/// A Sapling extended spending key
|
|
#[derive(Clone)]
|
|
pub struct ExtendedSpendingKey {
|
|
depth: u8,
|
|
parent_fvk_tag: FvkTag,
|
|
child_index: ChildIndex,
|
|
chain_code: ChainCode,
|
|
pub expsk: ExpandedSpendingKey,
|
|
dk: DiversifierKey,
|
|
}
|
|
|
|
// A Sapling extended full viewing key
|
|
#[derive(Clone)]
|
|
pub struct ExtendedFullViewingKey {
|
|
depth: u8,
|
|
parent_fvk_tag: FvkTag,
|
|
child_index: ChildIndex,
|
|
chain_code: ChainCode,
|
|
pub fvk: FullViewingKey,
|
|
pub(crate) dk: DiversifierKey,
|
|
}
|
|
|
|
impl std::cmp::PartialEq for ExtendedSpendingKey {
|
|
fn eq(&self, rhs: &ExtendedSpendingKey) -> bool {
|
|
self.depth == rhs.depth
|
|
&& self.parent_fvk_tag == rhs.parent_fvk_tag
|
|
&& self.child_index == rhs.child_index
|
|
&& self.chain_code == rhs.chain_code
|
|
&& self.expsk.ask == rhs.expsk.ask
|
|
&& self.expsk.nsk == rhs.expsk.nsk
|
|
&& self.expsk.ovk == rhs.expsk.ovk
|
|
&& self.dk == rhs.dk
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for ExtendedSpendingKey {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
|
write!(
|
|
f,
|
|
"ExtendedSpendingKey(d = {}, tag_p = {:?}, i = {:?})",
|
|
self.depth, self.parent_fvk_tag, self.child_index
|
|
)
|
|
}
|
|
}
|
|
|
|
impl std::cmp::PartialEq for ExtendedFullViewingKey {
|
|
fn eq(&self, rhs: &ExtendedFullViewingKey) -> bool {
|
|
self.depth == rhs.depth
|
|
&& self.parent_fvk_tag == rhs.parent_fvk_tag
|
|
&& self.child_index == rhs.child_index
|
|
&& self.chain_code == rhs.chain_code
|
|
&& self.fvk.vk.ak == rhs.fvk.vk.ak
|
|
&& self.fvk.vk.nk == rhs.fvk.vk.nk
|
|
&& self.fvk.ovk == rhs.fvk.ovk
|
|
&& self.dk == rhs.dk
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for ExtendedFullViewingKey {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
|
write!(
|
|
f,
|
|
"ExtendedFullViewingKey(d = {}, tag_p = {:?}, i = {:?})",
|
|
self.depth, self.parent_fvk_tag, self.child_index
|
|
)
|
|
}
|
|
}
|
|
|
|
impl ExtendedSpendingKey {
|
|
pub fn master(seed: &[u8]) -> Self {
|
|
let i = Blake2bParams::new()
|
|
.hash_length(64)
|
|
.personal(ZIP32_SAPLING_MASTER_PERSONALIZATION)
|
|
.hash(seed);
|
|
|
|
let sk_m = &i.as_bytes()[..32];
|
|
let mut c_m = [0u8; 32];
|
|
c_m.copy_from_slice(&i.as_bytes()[32..]);
|
|
|
|
ExtendedSpendingKey {
|
|
depth: 0,
|
|
parent_fvk_tag: FvkTag::master(),
|
|
child_index: ChildIndex::master(),
|
|
chain_code: ChainCode(c_m),
|
|
expsk: ExpandedSpendingKey::from_spending_key(sk_m),
|
|
dk: DiversifierKey::master(sk_m),
|
|
}
|
|
}
|
|
|
|
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
|
let depth = reader.read_u8()?;
|
|
let mut tag = [0; 4];
|
|
reader.read_exact(&mut tag)?;
|
|
let i = reader.read_u32::<LittleEndian>()?;
|
|
let mut c = [0; 32];
|
|
reader.read_exact(&mut c)?;
|
|
let expsk = ExpandedSpendingKey::read(&mut reader)?;
|
|
let mut dk = [0; 32];
|
|
reader.read_exact(&mut dk)?;
|
|
|
|
Ok(ExtendedSpendingKey {
|
|
depth,
|
|
parent_fvk_tag: FvkTag(tag),
|
|
child_index: ChildIndex::from_index(i),
|
|
chain_code: ChainCode(c),
|
|
expsk,
|
|
dk: DiversifierKey(dk),
|
|
})
|
|
}
|
|
|
|
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
|
writer.write_u8(self.depth)?;
|
|
writer.write_all(&self.parent_fvk_tag.0)?;
|
|
writer.write_u32::<LittleEndian>(self.child_index.value())?;
|
|
writer.write_all(&self.chain_code.0)?;
|
|
writer.write_all(&self.expsk.to_bytes())?;
|
|
writer.write_all(&self.dk.0)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Returns the child key corresponding to the path derived from the master key
|
|
pub fn from_path(master: &ExtendedSpendingKey, path: &[ChildIndex]) -> Self {
|
|
let mut xsk = master.clone();
|
|
for &i in path.iter() {
|
|
xsk = xsk.derive_child(i);
|
|
}
|
|
xsk
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn derive_child(&self, i: ChildIndex) -> Self {
|
|
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
|
let tmp = match i {
|
|
ChildIndex::Hardened(i) => {
|
|
let mut le_i = [0; 4];
|
|
LittleEndian::write_u32(&mut le_i, i + (1 << 31));
|
|
prf_expand_vec(
|
|
&self.chain_code.0,
|
|
&[&[0x11], &self.expsk.to_bytes(), &self.dk.0, &le_i],
|
|
)
|
|
}
|
|
ChildIndex::NonHardened(i) => {
|
|
let mut le_i = [0; 4];
|
|
LittleEndian::write_u32(&mut le_i, i);
|
|
prf_expand_vec(
|
|
&self.chain_code.0,
|
|
&[&[0x12], &fvk.to_bytes(), &self.dk.0, &le_i],
|
|
)
|
|
}
|
|
};
|
|
let i_l = &tmp.as_bytes()[..32];
|
|
let mut c_i = [0u8; 32];
|
|
c_i.copy_from_slice(&tmp.as_bytes()[32..]);
|
|
|
|
ExtendedSpendingKey {
|
|
depth: self.depth + 1,
|
|
parent_fvk_tag: FvkFingerprint::from(&fvk).tag(),
|
|
child_index: i,
|
|
chain_code: ChainCode(c_i),
|
|
expsk: {
|
|
let mut ask = jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x13]).as_array());
|
|
let mut nsk = jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x14]).as_array());
|
|
ask.add_assign(&self.expsk.ask);
|
|
nsk.add_assign(&self.expsk.nsk);
|
|
let ovk = derive_child_ovk(&self.expsk.ovk, i_l);
|
|
ExpandedSpendingKey { ask, nsk, ovk }
|
|
},
|
|
dk: self.dk.derive_child(i_l),
|
|
}
|
|
}
|
|
|
|
/// Returns the address with the lowest valid diversifier index, along with
|
|
/// the diversifier index that generated that address.
|
|
pub fn default_address(&self) -> (DiversifierIndex, PaymentAddress) {
|
|
ExtendedFullViewingKey::from(self).default_address()
|
|
}
|
|
|
|
/// Derives an internal spending key given an external spending key.
|
|
///
|
|
/// Specified in [ZIP 32](https://zips.z.cash/zip-0032#deriving-a-sapling-internal-spending-key).
|
|
#[must_use]
|
|
pub fn derive_internal(&self) -> Self {
|
|
let i = {
|
|
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
|
let mut h = Blake2bParams::new()
|
|
.hash_length(32)
|
|
.personal(crate::zip32::ZIP32_SAPLING_INT_PERSONALIZATION)
|
|
.to_state();
|
|
h.update(&fvk.to_bytes());
|
|
h.update(&self.dk.0);
|
|
h.finalize()
|
|
};
|
|
let i_nsk = jubjub::Fr::from_bytes_wide(prf_expand(i.as_bytes(), &[0x17]).as_array());
|
|
let r = prf_expand(i.as_bytes(), &[0x18]);
|
|
let r = r.as_bytes();
|
|
let nsk_internal = i_nsk + self.expsk.nsk;
|
|
let dk_internal = DiversifierKey(r[..32].try_into().unwrap());
|
|
let ovk_internal = OutgoingViewingKey(r[32..].try_into().unwrap());
|
|
|
|
ExtendedSpendingKey {
|
|
depth: self.depth,
|
|
parent_fvk_tag: self.parent_fvk_tag,
|
|
child_index: self.child_index,
|
|
chain_code: self.chain_code,
|
|
expsk: ExpandedSpendingKey {
|
|
ask: self.expsk.ask,
|
|
nsk: nsk_internal,
|
|
ovk: ovk_internal,
|
|
},
|
|
dk: dk_internal,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a ExtendedSpendingKey> for ExtendedFullViewingKey {
|
|
fn from(xsk: &ExtendedSpendingKey) -> Self {
|
|
ExtendedFullViewingKey {
|
|
depth: xsk.depth,
|
|
parent_fvk_tag: xsk.parent_fvk_tag,
|
|
child_index: xsk.child_index,
|
|
chain_code: xsk.chain_code,
|
|
fvk: FullViewingKey::from_expanded_spending_key(&xsk.expsk),
|
|
dk: xsk.dk,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ExtendedFullViewingKey {
|
|
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
|
let depth = reader.read_u8()?;
|
|
let mut tag = [0; 4];
|
|
reader.read_exact(&mut tag)?;
|
|
let i = reader.read_u32::<LittleEndian>()?;
|
|
let mut c = [0; 32];
|
|
reader.read_exact(&mut c)?;
|
|
let fvk = FullViewingKey::read(&mut reader)?;
|
|
let mut dk = [0; 32];
|
|
reader.read_exact(&mut dk)?;
|
|
|
|
Ok(ExtendedFullViewingKey {
|
|
depth,
|
|
parent_fvk_tag: FvkTag(tag),
|
|
child_index: ChildIndex::from_index(i),
|
|
chain_code: ChainCode(c),
|
|
fvk,
|
|
dk: DiversifierKey(dk),
|
|
})
|
|
}
|
|
|
|
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
|
writer.write_u8(self.depth)?;
|
|
writer.write_all(&self.parent_fvk_tag.0)?;
|
|
writer.write_u32::<LittleEndian>(self.child_index.value())?;
|
|
writer.write_all(&self.chain_code.0)?;
|
|
writer.write_all(&self.fvk.to_bytes())?;
|
|
writer.write_all(&self.dk.0)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn derive_child(&self, i: ChildIndex) -> Result<Self, ()> {
|
|
let tmp = match i {
|
|
ChildIndex::Hardened(_) => return Err(()),
|
|
ChildIndex::NonHardened(i) => {
|
|
let mut le_i = [0; 4];
|
|
LittleEndian::write_u32(&mut le_i, i);
|
|
prf_expand_vec(
|
|
&self.chain_code.0,
|
|
&[&[0x12], &self.fvk.to_bytes(), &self.dk.0, &le_i],
|
|
)
|
|
}
|
|
};
|
|
let i_l = &tmp.as_bytes()[..32];
|
|
let mut c_i = [0u8; 32];
|
|
c_i.copy_from_slice(&tmp.as_bytes()[32..]);
|
|
|
|
Ok(ExtendedFullViewingKey {
|
|
depth: self.depth + 1,
|
|
parent_fvk_tag: FvkFingerprint::from(&self.fvk).tag(),
|
|
child_index: i,
|
|
chain_code: ChainCode(c_i),
|
|
fvk: {
|
|
let i_ask = jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x13]).as_array());
|
|
let i_nsk = jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x14]).as_array());
|
|
let ak = (SPENDING_KEY_GENERATOR * i_ask) + self.fvk.vk.ak;
|
|
let nk = (PROOF_GENERATION_KEY_GENERATOR * i_nsk) + self.fvk.vk.nk;
|
|
|
|
FullViewingKey {
|
|
vk: ViewingKey { ak, nk },
|
|
ovk: derive_child_ovk(&self.fvk.ovk, i_l),
|
|
}
|
|
},
|
|
dk: self.dk.derive_child(i_l),
|
|
})
|
|
}
|
|
|
|
/// Attempt to produce a payment address given the specified diversifier
|
|
/// index, and return None if the specified index does not produce a valid
|
|
/// diversifier.
|
|
pub fn address(&self, j: DiversifierIndex) -> Option<PaymentAddress> {
|
|
sapling_address(&self.fvk, &self.dk, j)
|
|
}
|
|
|
|
/// Search the diversifier space starting at diversifier index `j` for
|
|
/// one which will produce a valid diversifier, and return the payment address
|
|
/// constructed using that diversifier along with the index at which the
|
|
/// valid diversifier was found.
|
|
pub fn find_address(&self, j: DiversifierIndex) -> Option<(DiversifierIndex, PaymentAddress)> {
|
|
sapling_find_address(&self.fvk, &self.dk, j)
|
|
}
|
|
|
|
/// Returns the payment address corresponding to the smallest valid diversifier
|
|
/// index, along with that index.
|
|
pub fn default_address(&self) -> (DiversifierIndex, PaymentAddress) {
|
|
sapling_default_address(&self.fvk, &self.dk)
|
|
}
|
|
|
|
/// Derives an internal full viewing key used for internal operations such
|
|
/// as change and auto-shielding. The internal FVK has the same spend authority
|
|
/// (the private key corresponding to ak) as the original, but viewing authority
|
|
/// only for internal transfers.
|
|
///
|
|
/// Specified in [ZIP 32](https://zips.z.cash/zip-0032#deriving-a-sapling-internal-full-viewing-key).
|
|
#[must_use]
|
|
pub fn derive_internal(&self) -> Self {
|
|
let (fvk_internal, dk_internal) = sapling_derive_internal_fvk(&self.fvk, &self.dk);
|
|
|
|
ExtendedFullViewingKey {
|
|
depth: self.depth,
|
|
parent_fvk_tag: self.parent_fvk_tag,
|
|
child_index: self.child_index,
|
|
chain_code: self.chain_code,
|
|
fvk: fvk_internal,
|
|
dk: dk_internal,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
use ff::PrimeField;
|
|
use group::GroupEncoding;
|
|
|
|
#[test]
|
|
fn derive_nonhardened_child() {
|
|
let seed = [0; 32];
|
|
let xsk_m = ExtendedSpendingKey::master(&seed);
|
|
let xfvk_m = ExtendedFullViewingKey::from(&xsk_m);
|
|
|
|
let i_5 = ChildIndex::NonHardened(5);
|
|
let xsk_5 = xsk_m.derive_child(i_5);
|
|
let xfvk_5 = xfvk_m.derive_child(i_5);
|
|
|
|
assert!(xfvk_5.is_ok());
|
|
assert_eq!(ExtendedFullViewingKey::from(&xsk_5), xfvk_5.unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn derive_hardened_child() {
|
|
let seed = [0; 32];
|
|
let xsk_m = ExtendedSpendingKey::master(&seed);
|
|
let xfvk_m = ExtendedFullViewingKey::from(&xsk_m);
|
|
|
|
let i_5h = ChildIndex::Hardened(5);
|
|
let xsk_5h = xsk_m.derive_child(i_5h);
|
|
let xfvk_5h = xfvk_m.derive_child(i_5h);
|
|
|
|
// Cannot derive a hardened child from an ExtendedFullViewingKey
|
|
assert!(xfvk_5h.is_err());
|
|
let xfvk_5h = ExtendedFullViewingKey::from(&xsk_5h);
|
|
|
|
let i_7 = ChildIndex::NonHardened(7);
|
|
let xsk_5h_7 = xsk_5h.derive_child(i_7);
|
|
let xfvk_5h_7 = xfvk_5h.derive_child(i_7);
|
|
|
|
// But we *can* derive a non-hardened child from a hardened parent
|
|
assert!(xfvk_5h_7.is_ok());
|
|
assert_eq!(ExtendedFullViewingKey::from(&xsk_5h_7), xfvk_5h_7.unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn path() {
|
|
let seed = [0; 32];
|
|
let xsk_m = ExtendedSpendingKey::master(&seed);
|
|
|
|
let xsk_5h = xsk_m.derive_child(ChildIndex::Hardened(5));
|
|
assert_eq!(
|
|
ExtendedSpendingKey::from_path(&xsk_m, &[ChildIndex::Hardened(5)]),
|
|
xsk_5h
|
|
);
|
|
|
|
let xsk_5h_7 = xsk_5h.derive_child(ChildIndex::NonHardened(7));
|
|
assert_eq!(
|
|
ExtendedSpendingKey::from_path(
|
|
&xsk_m,
|
|
&[ChildIndex::Hardened(5), ChildIndex::NonHardened(7)]
|
|
),
|
|
xsk_5h_7
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn diversifier() {
|
|
let dk = DiversifierKey([0; 32]);
|
|
let j_0 = DiversifierIndex::new();
|
|
let j_1 = DiversifierIndex([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
let j_2 = DiversifierIndex([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
let j_3 = DiversifierIndex([3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
// Computed using this Rust implementation
|
|
let d_0 = [220, 231, 126, 188, 236, 10, 38, 175, 214, 153, 140];
|
|
let d_3 = [60, 253, 170, 8, 171, 147, 220, 31, 3, 144, 34];
|
|
|
|
// j = 0
|
|
let d_j = dk.diversifier(j_0).unwrap();
|
|
assert_eq!(d_j.0, d_0);
|
|
assert_eq!(dk.diversifier_index(&Diversifier(d_0)), j_0);
|
|
|
|
// j = 1
|
|
assert_eq!(dk.diversifier(j_1), None);
|
|
|
|
// j = 2
|
|
assert_eq!(dk.diversifier(j_2), None);
|
|
|
|
// j = 3
|
|
let d_j = dk.diversifier(j_3).unwrap();
|
|
assert_eq!(d_j.0, d_3);
|
|
assert_eq!(dk.diversifier_index(&Diversifier(d_3)), j_3);
|
|
}
|
|
|
|
#[test]
|
|
fn find_diversifier() {
|
|
let dk = DiversifierKey([0; 32]);
|
|
let j_0 = DiversifierIndex::new();
|
|
let j_1 = DiversifierIndex([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
let j_2 = DiversifierIndex([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
let j_3 = DiversifierIndex([3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
// Computed using this Rust implementation
|
|
let d_0 = [220, 231, 126, 188, 236, 10, 38, 175, 214, 153, 140];
|
|
let d_3 = [60, 253, 170, 8, 171, 147, 220, 31, 3, 144, 34];
|
|
|
|
// j = 0
|
|
let (j, d_j) = dk.find_diversifier(j_0).unwrap();
|
|
assert_eq!(j, j_0);
|
|
assert_eq!(d_j.0, d_0);
|
|
|
|
// j = 1
|
|
let (j, d_j) = dk.find_diversifier(j_1).unwrap();
|
|
assert_eq!(j, j_3);
|
|
assert_eq!(d_j.0, d_3);
|
|
|
|
// j = 2
|
|
let (j, d_j) = dk.find_diversifier(j_2).unwrap();
|
|
assert_eq!(j, j_3);
|
|
assert_eq!(d_j.0, d_3);
|
|
|
|
// j = 3
|
|
let (j, d_j) = dk.find_diversifier(j_3).unwrap();
|
|
assert_eq!(j, j_3);
|
|
assert_eq!(d_j.0, d_3);
|
|
}
|
|
|
|
#[test]
|
|
fn address() {
|
|
let seed = [0; 32];
|
|
let xsk_m = ExtendedSpendingKey::master(&seed);
|
|
let xfvk_m = ExtendedFullViewingKey::from(&xsk_m);
|
|
let j_0 = DiversifierIndex::new();
|
|
let addr_m = xfvk_m.address(j_0).unwrap();
|
|
assert_eq!(
|
|
addr_m.diversifier().0,
|
|
// Computed using this Rust implementation
|
|
[59, 246, 250, 31, 131, 191, 69, 99, 200, 167, 19]
|
|
);
|
|
|
|
let j_1 = DiversifierIndex([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
assert_eq!(xfvk_m.address(j_1), None);
|
|
}
|
|
|
|
#[test]
|
|
fn default_address() {
|
|
let seed = [0; 32];
|
|
let xsk_m = ExtendedSpendingKey::master(&seed);
|
|
let (j_m, addr_m) = xsk_m.default_address();
|
|
assert_eq!(j_m.0, [0; 11]);
|
|
assert_eq!(
|
|
addr_m.diversifier().0,
|
|
// Computed using this Rust implementation
|
|
[59, 246, 250, 31, 131, 191, 69, 99, 200, 167, 19]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn read_write() {
|
|
let seed = [0; 32];
|
|
let xsk = ExtendedSpendingKey::master(&seed);
|
|
let fvk = ExtendedFullViewingKey::from(&xsk);
|
|
|
|
let mut ser = vec![];
|
|
xsk.write(&mut ser).unwrap();
|
|
let xsk2 = ExtendedSpendingKey::read(&ser[..]).unwrap();
|
|
assert_eq!(xsk2, xsk);
|
|
|
|
let mut ser = vec![];
|
|
fvk.write(&mut ser).unwrap();
|
|
let fvk2 = ExtendedFullViewingKey::read(&ser[..]).unwrap();
|
|
assert_eq!(fvk2, fvk);
|
|
}
|
|
|
|
#[test]
|
|
fn test_vectors() {
|
|
struct TestVector {
|
|
ask: Option<[u8; 32]>,
|
|
nsk: Option<[u8; 32]>,
|
|
ovk: [u8; 32],
|
|
dk: [u8; 32],
|
|
c: [u8; 32],
|
|
ak: [u8; 32],
|
|
nk: [u8; 32],
|
|
ivk: [u8; 32],
|
|
xsk: Option<[u8; 169]>,
|
|
xfvk: [u8; 169],
|
|
fp: [u8; 32],
|
|
d0: Option<[u8; 11]>,
|
|
d1: Option<[u8; 11]>,
|
|
d2: Option<[u8; 11]>,
|
|
dmax: Option<[u8; 11]>,
|
|
internal_nsk: Option<[u8; 32]>,
|
|
internal_ovk: [u8; 32],
|
|
internal_dk: [u8; 32],
|
|
internal_nk: [u8; 32],
|
|
internal_ivk: [u8; 32],
|
|
internal_xsk: Option<[u8; 169]>,
|
|
internal_xfvk: [u8; 169],
|
|
internal_fp: [u8; 32],
|
|
}
|
|
|
|
// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_zip32.py
|
|
let test_vectors = vec![
|
|
TestVector {
|
|
ask: Some([
|
|
0xb6, 0xc0, 0x0c, 0x93, 0xd3, 0x60, 0x32, 0xb9, 0xa2, 0x68, 0xe9, 0x9e, 0x86,
|
|
0xa8, 0x60, 0x77, 0x65, 0x60, 0xbf, 0x0e, 0x83, 0xc1, 0xa1, 0x0b, 0x51, 0xf6,
|
|
0x07, 0xc9, 0x54, 0x74, 0x25, 0x06,
|
|
]),
|
|
nsk: Some([
|
|
0x82, 0x04, 0xed, 0xe8, 0x3b, 0x2f, 0x1f, 0xbd, 0x84, 0xf9, 0xb4, 0x5d, 0x7f,
|
|
0x99, 0x6e, 0x2e, 0xbd, 0x0a, 0x03, 0x0a, 0xd2, 0x43, 0xb4, 0x8e, 0xd3, 0x9f,
|
|
0x74, 0x8a, 0x88, 0x21, 0xea, 0x06,
|
|
]),
|
|
ovk: [
|
|
0x39, 0x58, 0x84, 0x89, 0x03, 0x23, 0xb9, 0xd4, 0x93, 0x3c, 0x02, 0x1d, 0xb8,
|
|
0x9b, 0xcf, 0x76, 0x7d, 0xf2, 0x19, 0x77, 0xb2, 0xff, 0x06, 0x83, 0x84, 0x83,
|
|
0x21, 0xa4, 0xdf, 0x4a, 0xfb, 0x21,
|
|
],
|
|
dk: [
|
|
0x77, 0xc1, 0x7c, 0xb7, 0x5b, 0x77, 0x96, 0xaf, 0xb3, 0x9f, 0x0f, 0x3e, 0x91,
|
|
0xc9, 0x24, 0x60, 0x7d, 0xa5, 0x6f, 0xa9, 0xa2, 0x0e, 0x28, 0x35, 0x09, 0xbc,
|
|
0x8a, 0x3e, 0xf9, 0x96, 0xa1, 0x72,
|
|
],
|
|
c: [
|
|
0xd0, 0x94, 0x7c, 0x4b, 0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27,
|
|
0x6d, 0x1c, 0xf3, 0xfd, 0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55,
|
|
0x0d, 0x75, 0x20, 0x18, 0x66, 0x8e,
|
|
],
|
|
ak: [
|
|
0x93, 0x44, 0x2e, 0x5f, 0xef, 0xfb, 0xff, 0x16, 0xe7, 0x21, 0x72, 0x02, 0xdc,
|
|
0x73, 0x06, 0x72, 0x9f, 0xff, 0xfe, 0x85, 0xaf, 0x56, 0x83, 0xbc, 0xe2, 0x64,
|
|
0x2e, 0x3e, 0xeb, 0x5d, 0x38, 0x71,
|
|
],
|
|
nk: [
|
|
0xdc, 0xe8, 0xe7, 0xed, 0xec, 0xe0, 0x4b, 0x89, 0x50, 0x41, 0x7f, 0x85, 0xba,
|
|
0x57, 0x69, 0x1b, 0x78, 0x3c, 0x45, 0xb1, 0xa2, 0x74, 0x22, 0xdb, 0x16, 0x93,
|
|
0xdc, 0xeb, 0x67, 0xb1, 0x01, 0x06,
|
|
],
|
|
ivk: [
|
|
0x48, 0x47, 0xa1, 0x30, 0xe7, 0x99, 0xd3, 0xdb, 0xea, 0x36, 0xa1, 0xc1, 0x64,
|
|
0x67, 0xd6, 0x21, 0xfb, 0x2d, 0x80, 0xe3, 0x0b, 0x3b, 0x1d, 0x1a, 0x42, 0x68,
|
|
0x93, 0x41, 0x5d, 0xad, 0x66, 0x01,
|
|
],
|
|
xsk: Some([
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
|
|
0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
|
|
0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
|
|
0x66, 0x8e, 0xb6, 0xc0, 0x0c, 0x93, 0xd3, 0x60, 0x32, 0xb9, 0xa2, 0x68, 0xe9,
|
|
0x9e, 0x86, 0xa8, 0x60, 0x77, 0x65, 0x60, 0xbf, 0x0e, 0x83, 0xc1, 0xa1, 0x0b,
|
|
0x51, 0xf6, 0x07, 0xc9, 0x54, 0x74, 0x25, 0x06, 0x82, 0x04, 0xed, 0xe8, 0x3b,
|
|
0x2f, 0x1f, 0xbd, 0x84, 0xf9, 0xb4, 0x5d, 0x7f, 0x99, 0x6e, 0x2e, 0xbd, 0x0a,
|
|
0x03, 0x0a, 0xd2, 0x43, 0xb4, 0x8e, 0xd3, 0x9f, 0x74, 0x8a, 0x88, 0x21, 0xea,
|
|
0x06, 0x39, 0x58, 0x84, 0x89, 0x03, 0x23, 0xb9, 0xd4, 0x93, 0x3c, 0x02, 0x1d,
|
|
0xb8, 0x9b, 0xcf, 0x76, 0x7d, 0xf2, 0x19, 0x77, 0xb2, 0xff, 0x06, 0x83, 0x84,
|
|
0x83, 0x21, 0xa4, 0xdf, 0x4a, 0xfb, 0x21, 0x77, 0xc1, 0x7c, 0xb7, 0x5b, 0x77,
|
|
0x96, 0xaf, 0xb3, 0x9f, 0x0f, 0x3e, 0x91, 0xc9, 0x24, 0x60, 0x7d, 0xa5, 0x6f,
|
|
0xa9, 0xa2, 0x0e, 0x28, 0x35, 0x09, 0xbc, 0x8a, 0x3e, 0xf9, 0x96, 0xa1, 0x72,
|
|
]),
|
|
xfvk: [
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
|
|
0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
|
|
0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
|
|
0x66, 0x8e, 0x93, 0x44, 0x2e, 0x5f, 0xef, 0xfb, 0xff, 0x16, 0xe7, 0x21, 0x72,
|
|
0x02, 0xdc, 0x73, 0x06, 0x72, 0x9f, 0xff, 0xfe, 0x85, 0xaf, 0x56, 0x83, 0xbc,
|
|
0xe2, 0x64, 0x2e, 0x3e, 0xeb, 0x5d, 0x38, 0x71, 0xdc, 0xe8, 0xe7, 0xed, 0xec,
|
|
0xe0, 0x4b, 0x89, 0x50, 0x41, 0x7f, 0x85, 0xba, 0x57, 0x69, 0x1b, 0x78, 0x3c,
|
|
0x45, 0xb1, 0xa2, 0x74, 0x22, 0xdb, 0x16, 0x93, 0xdc, 0xeb, 0x67, 0xb1, 0x01,
|
|
0x06, 0x39, 0x58, 0x84, 0x89, 0x03, 0x23, 0xb9, 0xd4, 0x93, 0x3c, 0x02, 0x1d,
|
|
0xb8, 0x9b, 0xcf, 0x76, 0x7d, 0xf2, 0x19, 0x77, 0xb2, 0xff, 0x06, 0x83, 0x84,
|
|
0x83, 0x21, 0xa4, 0xdf, 0x4a, 0xfb, 0x21, 0x77, 0xc1, 0x7c, 0xb7, 0x5b, 0x77,
|
|
0x96, 0xaf, 0xb3, 0x9f, 0x0f, 0x3e, 0x91, 0xc9, 0x24, 0x60, 0x7d, 0xa5, 0x6f,
|
|
0xa9, 0xa2, 0x0e, 0x28, 0x35, 0x09, 0xbc, 0x8a, 0x3e, 0xf9, 0x96, 0xa1, 0x72,
|
|
],
|
|
fp: [
|
|
0x14, 0xc2, 0x71, 0x3a, 0xdc, 0xe9, 0x3a, 0x83, 0x0e, 0xa8, 0x3a, 0x05, 0x19,
|
|
0x08, 0xb7, 0x44, 0x77, 0x83, 0xf5, 0xd1, 0x06, 0xc0, 0x98, 0x5e, 0x02, 0x55,
|
|
0x0e, 0x42, 0x6f, 0x27, 0x59, 0x7c,
|
|
],
|
|
d0: Some([
|
|
0xd8, 0x62, 0x1b, 0x98, 0x1c, 0xf3, 0x00, 0xe9, 0xd4, 0xcc, 0x89,
|
|
]),
|
|
d1: Some([
|
|
0x48, 0xea, 0x17, 0xa1, 0x99, 0xc8, 0x4b, 0xd1, 0xba, 0xa5, 0xd4,
|
|
]),
|
|
d2: None,
|
|
dmax: None,
|
|
internal_nsk: Some([
|
|
0x51, 0x12, 0x33, 0x63, 0x6b, 0x95, 0xfd, 0x0a, 0xfb, 0x6b, 0xf8, 0x19, 0x3a,
|
|
0x7d, 0x8f, 0x49, 0xef, 0xd7, 0x36, 0xa9, 0x88, 0x77, 0x5c, 0x54, 0xf9, 0x56,
|
|
0x68, 0x76, 0x46, 0xea, 0xab, 0x07,
|
|
]),
|
|
internal_ovk: [
|
|
0x9d, 0xc4, 0x77, 0xfe, 0x1e, 0x7d, 0x28, 0x29, 0x13, 0xf6, 0x51, 0x65, 0x4d,
|
|
0x39, 0x85, 0xf0, 0x9d, 0x53, 0xc2, 0xd3, 0xb5, 0x76, 0x3d, 0x7a, 0x72, 0x3b,
|
|
0xcb, 0xd6, 0xee, 0x05, 0x3d, 0x5a,
|
|
],
|
|
internal_dk: [
|
|
0x40, 0xdd, 0xc5, 0x6e, 0x69, 0x75, 0x13, 0x8c, 0x08, 0x39, 0xe5, 0x80, 0xb5,
|
|
0x4d, 0x6d, 0x99, 0x9d, 0xc6, 0x16, 0x84, 0x3c, 0xfe, 0x04, 0x1e, 0x8f, 0x38,
|
|
0x8b, 0x12, 0x4e, 0xf7, 0xb5, 0xed,
|
|
],
|
|
internal_nk: [
|
|
0xa3, 0x83, 0x1a, 0x5c, 0x69, 0x33, 0xf8, 0xec, 0x6a, 0xa5, 0xce, 0x31, 0x6c,
|
|
0x50, 0x8b, 0x79, 0x91, 0xcd, 0x94, 0xd3, 0xbd, 0xb7, 0x00, 0xa1, 0xc4, 0x27,
|
|
0xa6, 0xae, 0x15, 0xe7, 0x2f, 0xb5,
|
|
],
|
|
internal_ivk: [
|
|
0x79, 0x05, 0x77, 0x32, 0x1c, 0x51, 0x18, 0x04, 0x63, 0x6e, 0xe6, 0xba, 0xa4,
|
|
0xee, 0xa7, 0x79, 0xb4, 0xa4, 0x6a, 0x5a, 0x12, 0xf8, 0x5d, 0x36, 0x50, 0x74,
|
|
0xa0, 0x9d, 0x05, 0x4f, 0x34, 0x01,
|
|
],
|
|
internal_xsk: Some([
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
|
|
0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
|
|
0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
|
|
0x66, 0x8e, 0xb6, 0xc0, 0x0c, 0x93, 0xd3, 0x60, 0x32, 0xb9, 0xa2, 0x68, 0xe9,
|
|
0x9e, 0x86, 0xa8, 0x60, 0x77, 0x65, 0x60, 0xbf, 0x0e, 0x83, 0xc1, 0xa1, 0x0b,
|
|
0x51, 0xf6, 0x07, 0xc9, 0x54, 0x74, 0x25, 0x06, 0x51, 0x12, 0x33, 0x63, 0x6b,
|
|
0x95, 0xfd, 0x0a, 0xfb, 0x6b, 0xf8, 0x19, 0x3a, 0x7d, 0x8f, 0x49, 0xef, 0xd7,
|
|
0x36, 0xa9, 0x88, 0x77, 0x5c, 0x54, 0xf9, 0x56, 0x68, 0x76, 0x46, 0xea, 0xab,
|
|
0x07, 0x9d, 0xc4, 0x77, 0xfe, 0x1e, 0x7d, 0x28, 0x29, 0x13, 0xf6, 0x51, 0x65,
|
|
0x4d, 0x39, 0x85, 0xf0, 0x9d, 0x53, 0xc2, 0xd3, 0xb5, 0x76, 0x3d, 0x7a, 0x72,
|
|
0x3b, 0xcb, 0xd6, 0xee, 0x05, 0x3d, 0x5a, 0x40, 0xdd, 0xc5, 0x6e, 0x69, 0x75,
|
|
0x13, 0x8c, 0x08, 0x39, 0xe5, 0x80, 0xb5, 0x4d, 0x6d, 0x99, 0x9d, 0xc6, 0x16,
|
|
0x84, 0x3c, 0xfe, 0x04, 0x1e, 0x8f, 0x38, 0x8b, 0x12, 0x4e, 0xf7, 0xb5, 0xed,
|
|
]),
|
|
internal_xfvk: [
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
|
|
0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
|
|
0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
|
|
0x66, 0x8e, 0x93, 0x44, 0x2e, 0x5f, 0xef, 0xfb, 0xff, 0x16, 0xe7, 0x21, 0x72,
|
|
0x02, 0xdc, 0x73, 0x06, 0x72, 0x9f, 0xff, 0xfe, 0x85, 0xaf, 0x56, 0x83, 0xbc,
|
|
0xe2, 0x64, 0x2e, 0x3e, 0xeb, 0x5d, 0x38, 0x71, 0xa3, 0x83, 0x1a, 0x5c, 0x69,
|
|
0x33, 0xf8, 0xec, 0x6a, 0xa5, 0xce, 0x31, 0x6c, 0x50, 0x8b, 0x79, 0x91, 0xcd,
|
|
0x94, 0xd3, 0xbd, 0xb7, 0x00, 0xa1, 0xc4, 0x27, 0xa6, 0xae, 0x15, 0xe7, 0x2f,
|
|
0xb5, 0x9d, 0xc4, 0x77, 0xfe, 0x1e, 0x7d, 0x28, 0x29, 0x13, 0xf6, 0x51, 0x65,
|
|
0x4d, 0x39, 0x85, 0xf0, 0x9d, 0x53, 0xc2, 0xd3, 0xb5, 0x76, 0x3d, 0x7a, 0x72,
|
|
0x3b, 0xcb, 0xd6, 0xee, 0x05, 0x3d, 0x5a, 0x40, 0xdd, 0xc5, 0x6e, 0x69, 0x75,
|
|
0x13, 0x8c, 0x08, 0x39, 0xe5, 0x80, 0xb5, 0x4d, 0x6d, 0x99, 0x9d, 0xc6, 0x16,
|
|
0x84, 0x3c, 0xfe, 0x04, 0x1e, 0x8f, 0x38, 0x8b, 0x12, 0x4e, 0xf7, 0xb5, 0xed,
|
|
],
|
|
internal_fp: [
|
|
0x82, 0x64, 0xed, 0xec, 0x63, 0xb1, 0x55, 0x00, 0x1d, 0x84, 0x96, 0x68, 0x5c,
|
|
0xc7, 0xc2, 0x1e, 0xa9, 0x57, 0xc6, 0xf5, 0x91, 0x09, 0x0a, 0x1c, 0x20, 0xe5,
|
|
0x2a, 0x41, 0x89, 0xb8, 0xbb, 0x96,
|
|
],
|
|
},
|
|
TestVector {
|
|
ask: Some([
|
|
0x28, 0x2b, 0xc1, 0x97, 0xa5, 0x16, 0x28, 0x7c, 0x8e, 0xa8, 0xf6, 0x8c, 0x42,
|
|
0x4a, 0xba, 0xd3, 0x02, 0xb4, 0x5c, 0xdf, 0x95, 0x40, 0x79, 0x61, 0xd7, 0xb8,
|
|
0xb4, 0x55, 0x26, 0x7a, 0x35, 0x0c,
|
|
]),
|
|
nsk: Some([
|
|
0xe7, 0xa3, 0x29, 0x88, 0xfd, 0xca, 0x1e, 0xfc, 0xd6, 0xd1, 0xc4, 0xc5, 0x62,
|
|
0xe6, 0x29, 0xc2, 0xe9, 0x6b, 0x2c, 0x3f, 0x7e, 0xda, 0x04, 0xac, 0x4e, 0xfd,
|
|
0x18, 0x10, 0xff, 0x6b, 0xba, 0x01,
|
|
]),
|
|
ovk: [
|
|
0x5f, 0x13, 0x81, 0xfc, 0x88, 0x86, 0xda, 0x6a, 0x02, 0xdf, 0xfe, 0xef, 0xcf,
|
|
0x50, 0x3c, 0x40, 0xfa, 0x8f, 0x5a, 0x36, 0xf7, 0xa7, 0x14, 0x2f, 0xd8, 0x1b,
|
|
0x55, 0x18, 0xc5, 0xa4, 0x74, 0x74,
|
|
],
|
|
dk: [
|
|
0xe0, 0x4d, 0xe8, 0x32, 0xa2, 0xd7, 0x91, 0xec, 0x12, 0x9a, 0xb9, 0x00, 0x2b,
|
|
0x91, 0xc9, 0xe9, 0xcd, 0xee, 0xd7, 0x92, 0x41, 0xa7, 0xc4, 0x96, 0x0e, 0x51,
|
|
0x78, 0xd8, 0x70, 0xc1, 0xb4, 0xdc,
|
|
],
|
|
c: [
|
|
0x01, 0x47, 0x11, 0x0c, 0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05,
|
|
0xc5, 0xe7, 0x90, 0xa5, 0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43,
|
|
0x8a, 0x67, 0x05, 0xda, 0xbc, 0xe6,
|
|
],
|
|
ak: [
|
|
0xdc, 0x14, 0xb5, 0x14, 0xd3, 0xa9, 0x25, 0x94, 0xc2, 0x19, 0x25, 0xaf, 0x2f,
|
|
0x77, 0x65, 0xa5, 0x47, 0xb3, 0x0e, 0x73, 0xfa, 0x7b, 0x70, 0x0e, 0xa1, 0xbf,
|
|
0xf2, 0xe5, 0xef, 0xaa, 0xa8, 0x8b,
|
|
],
|
|
nk: [
|
|
0x61, 0x52, 0xeb, 0x7f, 0xdb, 0x25, 0x27, 0x79, 0xdd, 0xcb, 0x95, 0xd2, 0x17,
|
|
0xea, 0x4b, 0x6f, 0xd3, 0x40, 0x36, 0xe9, 0xad, 0xad, 0xb3, 0xb5, 0xc9, 0xcb,
|
|
0xec, 0xeb, 0x41, 0xba, 0x45, 0x2a,
|
|
],
|
|
ivk: [
|
|
0x15, 0x5a, 0x8e, 0xe2, 0x05, 0xd3, 0x87, 0x2d, 0x12, 0xf8, 0xa3, 0xe6, 0x39,
|
|
0x91, 0x46, 0x33, 0xc2, 0x3c, 0xde, 0x1f, 0x30, 0xed, 0x50, 0x51, 0xe5, 0x21,
|
|
0x30, 0xb1, 0xd0, 0x10, 0x4c, 0x06,
|
|
],
|
|
xsk: Some([
|
|
0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
|
|
0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
|
|
0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
|
|
0xbc, 0xe6, 0x28, 0x2b, 0xc1, 0x97, 0xa5, 0x16, 0x28, 0x7c, 0x8e, 0xa8, 0xf6,
|
|
0x8c, 0x42, 0x4a, 0xba, 0xd3, 0x02, 0xb4, 0x5c, 0xdf, 0x95, 0x40, 0x79, 0x61,
|
|
0xd7, 0xb8, 0xb4, 0x55, 0x26, 0x7a, 0x35, 0x0c, 0xe7, 0xa3, 0x29, 0x88, 0xfd,
|
|
0xca, 0x1e, 0xfc, 0xd6, 0xd1, 0xc4, 0xc5, 0x62, 0xe6, 0x29, 0xc2, 0xe9, 0x6b,
|
|
0x2c, 0x3f, 0x7e, 0xda, 0x04, 0xac, 0x4e, 0xfd, 0x18, 0x10, 0xff, 0x6b, 0xba,
|
|
0x01, 0x5f, 0x13, 0x81, 0xfc, 0x88, 0x86, 0xda, 0x6a, 0x02, 0xdf, 0xfe, 0xef,
|
|
0xcf, 0x50, 0x3c, 0x40, 0xfa, 0x8f, 0x5a, 0x36, 0xf7, 0xa7, 0x14, 0x2f, 0xd8,
|
|
0x1b, 0x55, 0x18, 0xc5, 0xa4, 0x74, 0x74, 0xe0, 0x4d, 0xe8, 0x32, 0xa2, 0xd7,
|
|
0x91, 0xec, 0x12, 0x9a, 0xb9, 0x00, 0x2b, 0x91, 0xc9, 0xe9, 0xcd, 0xee, 0xd7,
|
|
0x92, 0x41, 0xa7, 0xc4, 0x96, 0x0e, 0x51, 0x78, 0xd8, 0x70, 0xc1, 0xb4, 0xdc,
|
|
]),
|
|
xfvk: [
|
|
0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
|
|
0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
|
|
0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
|
|
0xbc, 0xe6, 0xdc, 0x14, 0xb5, 0x14, 0xd3, 0xa9, 0x25, 0x94, 0xc2, 0x19, 0x25,
|
|
0xaf, 0x2f, 0x77, 0x65, 0xa5, 0x47, 0xb3, 0x0e, 0x73, 0xfa, 0x7b, 0x70, 0x0e,
|
|
0xa1, 0xbf, 0xf2, 0xe5, 0xef, 0xaa, 0xa8, 0x8b, 0x61, 0x52, 0xeb, 0x7f, 0xdb,
|
|
0x25, 0x27, 0x79, 0xdd, 0xcb, 0x95, 0xd2, 0x17, 0xea, 0x4b, 0x6f, 0xd3, 0x40,
|
|
0x36, 0xe9, 0xad, 0xad, 0xb3, 0xb5, 0xc9, 0xcb, 0xec, 0xeb, 0x41, 0xba, 0x45,
|
|
0x2a, 0x5f, 0x13, 0x81, 0xfc, 0x88, 0x86, 0xda, 0x6a, 0x02, 0xdf, 0xfe, 0xef,
|
|
0xcf, 0x50, 0x3c, 0x40, 0xfa, 0x8f, 0x5a, 0x36, 0xf7, 0xa7, 0x14, 0x2f, 0xd8,
|
|
0x1b, 0x55, 0x18, 0xc5, 0xa4, 0x74, 0x74, 0xe0, 0x4d, 0xe8, 0x32, 0xa2, 0xd7,
|
|
0x91, 0xec, 0x12, 0x9a, 0xb9, 0x00, 0x2b, 0x91, 0xc9, 0xe9, 0xcd, 0xee, 0xd7,
|
|
0x92, 0x41, 0xa7, 0xc4, 0x96, 0x0e, 0x51, 0x78, 0xd8, 0x70, 0xc1, 0xb4, 0xdc,
|
|
],
|
|
fp: [
|
|
0xdb, 0x99, 0x9e, 0x07, 0x1d, 0xcb, 0x58, 0xdd, 0x93, 0x02, 0x9a, 0xe6, 0x97,
|
|
0x05, 0x3e, 0x90, 0xed, 0xb3, 0x59, 0xd1, 0xa1, 0xb7, 0xa1, 0x25, 0x16, 0x7e,
|
|
0xfb, 0xe9, 0x28, 0x06, 0x84, 0x23,
|
|
],
|
|
d0: Some([
|
|
0x8b, 0x41, 0x38, 0x32, 0x0d, 0xfa, 0xfd, 0x7b, 0x39, 0x97, 0x81,
|
|
]),
|
|
d1: None,
|
|
d2: Some([
|
|
0x57, 0x49, 0xa1, 0x33, 0x52, 0xbc, 0x22, 0x3e, 0x30, 0x80, 0x78,
|
|
]),
|
|
dmax: Some([
|
|
0x63, 0x89, 0x57, 0x4c, 0xde, 0x0f, 0xbb, 0xc6, 0x36, 0x81, 0x31,
|
|
]),
|
|
internal_nsk: Some([
|
|
0x74, 0x92, 0x9f, 0x79, 0x0c, 0x11, 0xdc, 0xab, 0x3a, 0x2f, 0x93, 0x12, 0x35,
|
|
0xcd, 0xb2, 0x67, 0xf5, 0xa3, 0x1b, 0x9f, 0x13, 0x9f, 0x2c, 0x9f, 0xd8, 0x16,
|
|
0xb0, 0x44, 0x4f, 0xb8, 0x05, 0x05,
|
|
]),
|
|
internal_ovk: [
|
|
0x0c, 0xd4, 0xd7, 0xc5, 0xcc, 0x7f, 0x53, 0x4b, 0x96, 0xd2, 0x41, 0x82, 0xa3,
|
|
0x14, 0x65, 0xb4, 0x78, 0x11, 0x05, 0x48, 0x9c, 0xd1, 0x0d, 0x50, 0x0c, 0xf5,
|
|
0x29, 0x5a, 0x6f, 0xd8, 0x18, 0xcc,
|
|
],
|
|
internal_dk: [
|
|
0xd2, 0x78, 0xb7, 0x2c, 0x62, 0x1d, 0x19, 0xcb, 0x00, 0xf9, 0x70, 0x07, 0x9c,
|
|
0x89, 0x22, 0x76, 0x1c, 0xdd, 0x3a, 0xe7, 0xf2, 0x7b, 0x18, 0x47, 0xc5, 0x53,
|
|
0x60, 0xdb, 0xeb, 0xf6, 0x54, 0x92,
|
|
],
|
|
internal_nk: [
|
|
0x2b, 0x5c, 0x78, 0xa2, 0xfb, 0xa5, 0x01, 0x9c, 0x15, 0xa7, 0x51, 0x50, 0x2b,
|
|
0xa9, 0x91, 0x6f, 0xae, 0xda, 0xe1, 0xfc, 0x14, 0xdc, 0x81, 0xb0, 0xb8, 0x35,
|
|
0xf2, 0xbf, 0x95, 0xc0, 0x68, 0xe8,
|
|
],
|
|
internal_ivk: [
|
|
0xdf, 0x44, 0x54, 0xa6, 0x76, 0xd1, 0xde, 0x32, 0xe2, 0x0a, 0xe6, 0x28, 0x7a,
|
|
0x92, 0xfa, 0xfe, 0xfb, 0xbb, 0x3e, 0x54, 0xb5, 0x88, 0xc8, 0xda, 0x28, 0x07,
|
|
0xec, 0x43, 0x68, 0x2c, 0x85, 0x00,
|
|
],
|
|
internal_xsk: Some([
|
|
0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
|
|
0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
|
|
0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
|
|
0xbc, 0xe6, 0x28, 0x2b, 0xc1, 0x97, 0xa5, 0x16, 0x28, 0x7c, 0x8e, 0xa8, 0xf6,
|
|
0x8c, 0x42, 0x4a, 0xba, 0xd3, 0x02, 0xb4, 0x5c, 0xdf, 0x95, 0x40, 0x79, 0x61,
|
|
0xd7, 0xb8, 0xb4, 0x55, 0x26, 0x7a, 0x35, 0x0c, 0x74, 0x92, 0x9f, 0x79, 0x0c,
|
|
0x11, 0xdc, 0xab, 0x3a, 0x2f, 0x93, 0x12, 0x35, 0xcd, 0xb2, 0x67, 0xf5, 0xa3,
|
|
0x1b, 0x9f, 0x13, 0x9f, 0x2c, 0x9f, 0xd8, 0x16, 0xb0, 0x44, 0x4f, 0xb8, 0x05,
|
|
0x05, 0x0c, 0xd4, 0xd7, 0xc5, 0xcc, 0x7f, 0x53, 0x4b, 0x96, 0xd2, 0x41, 0x82,
|
|
0xa3, 0x14, 0x65, 0xb4, 0x78, 0x11, 0x05, 0x48, 0x9c, 0xd1, 0x0d, 0x50, 0x0c,
|
|
0xf5, 0x29, 0x5a, 0x6f, 0xd8, 0x18, 0xcc, 0xd2, 0x78, 0xb7, 0x2c, 0x62, 0x1d,
|
|
0x19, 0xcb, 0x00, 0xf9, 0x70, 0x07, 0x9c, 0x89, 0x22, 0x76, 0x1c, 0xdd, 0x3a,
|
|
0xe7, 0xf2, 0x7b, 0x18, 0x47, 0xc5, 0x53, 0x60, 0xdb, 0xeb, 0xf6, 0x54, 0x92,
|
|
]),
|
|
internal_xfvk: [
|
|
0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
|
|
0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
|
|
0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
|
|
0xbc, 0xe6, 0xdc, 0x14, 0xb5, 0x14, 0xd3, 0xa9, 0x25, 0x94, 0xc2, 0x19, 0x25,
|
|
0xaf, 0x2f, 0x77, 0x65, 0xa5, 0x47, 0xb3, 0x0e, 0x73, 0xfa, 0x7b, 0x70, 0x0e,
|
|
0xa1, 0xbf, 0xf2, 0xe5, 0xef, 0xaa, 0xa8, 0x8b, 0x2b, 0x5c, 0x78, 0xa2, 0xfb,
|
|
0xa5, 0x01, 0x9c, 0x15, 0xa7, 0x51, 0x50, 0x2b, 0xa9, 0x91, 0x6f, 0xae, 0xda,
|
|
0xe1, 0xfc, 0x14, 0xdc, 0x81, 0xb0, 0xb8, 0x35, 0xf2, 0xbf, 0x95, 0xc0, 0x68,
|
|
0xe8, 0x0c, 0xd4, 0xd7, 0xc5, 0xcc, 0x7f, 0x53, 0x4b, 0x96, 0xd2, 0x41, 0x82,
|
|
0xa3, 0x14, 0x65, 0xb4, 0x78, 0x11, 0x05, 0x48, 0x9c, 0xd1, 0x0d, 0x50, 0x0c,
|
|
0xf5, 0x29, 0x5a, 0x6f, 0xd8, 0x18, 0xcc, 0xd2, 0x78, 0xb7, 0x2c, 0x62, 0x1d,
|
|
0x19, 0xcb, 0x00, 0xf9, 0x70, 0x07, 0x9c, 0x89, 0x22, 0x76, 0x1c, 0xdd, 0x3a,
|
|
0xe7, 0xf2, 0x7b, 0x18, 0x47, 0xc5, 0x53, 0x60, 0xdb, 0xeb, 0xf6, 0x54, 0x92,
|
|
],
|
|
internal_fp: [
|
|
0x0d, 0xe5, 0x83, 0xca, 0x50, 0x2b, 0x1c, 0x4b, 0x87, 0xca, 0xc8, 0xc9, 0x78,
|
|
0x6c, 0x61, 0x9b, 0x79, 0xe1, 0x69, 0xb4, 0x15, 0x61, 0xf2, 0x44, 0xee, 0xec,
|
|
0x86, 0x86, 0xb8, 0xdb, 0xc4, 0xe1,
|
|
],
|
|
},
|
|
TestVector {
|
|
ask: Some([
|
|
0x8b, 0xe8, 0x11, 0x3c, 0xee, 0x34, 0x13, 0xa7, 0x1f, 0x82, 0xc4, 0x1f, 0xc8,
|
|
0xda, 0x51, 0x7b, 0xe1, 0x34, 0x04, 0x98, 0x32, 0xe6, 0x82, 0x5c, 0x92, 0xda,
|
|
0x6b, 0x84, 0xfe, 0xe4, 0xc6, 0x0d,
|
|
]),
|
|
nsk: Some([
|
|
0x37, 0x78, 0x05, 0x9d, 0xc5, 0x69, 0xe7, 0xd0, 0xd3, 0x23, 0x91, 0x57, 0x3f,
|
|
0x95, 0x1b, 0xbd, 0xe9, 0x2f, 0xc6, 0xb9, 0xcf, 0x61, 0x47, 0x73, 0x66, 0x1c,
|
|
0x5c, 0x27, 0x3a, 0xa6, 0x99, 0x0c,
|
|
]),
|
|
ovk: [
|
|
0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb, 0x47,
|
|
0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1, 0x93,
|
|
0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc,
|
|
],
|
|
dk: [
|
|
0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff, 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10,
|
|
0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4, 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0,
|
|
0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
|
|
],
|
|
c: [
|
|
0x97, 0xce, 0x15, 0xf4, 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b,
|
|
0xcb, 0x3d, 0xc9, 0xb3, 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42,
|
|
0x77, 0x73, 0x83, 0xa8, 0xd4, 0x35,
|
|
],
|
|
ak: [
|
|
0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e, 0x3a, 0x49,
|
|
0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4, 0x52, 0x0e,
|
|
0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41,
|
|
],
|
|
nk: [
|
|
0x30, 0x4e, 0x30, 0x59, 0x16, 0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae,
|
|
0x50, 0xec, 0xd1, 0x88, 0xfc, 0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f,
|
|
0x30, 0x77, 0x25, 0xe2, 0xee, 0x11,
|
|
],
|
|
ivk: [
|
|
0xa2, 0xa1, 0x3c, 0x1e, 0x38, 0xb4, 0x59, 0x84, 0x44, 0x58, 0x03, 0xe4, 0x30,
|
|
0xa6, 0x83, 0xc9, 0x0b, 0xb2, 0xe1, 0x4d, 0x4c, 0x86, 0x92, 0xff, 0x25, 0x3a,
|
|
0x64, 0x84, 0xdd, 0x9b, 0xb5, 0x04,
|
|
],
|
|
xsk: Some([
|
|
0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
|
|
0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
|
|
0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
|
|
0xd4, 0x35, 0x8b, 0xe8, 0x11, 0x3c, 0xee, 0x34, 0x13, 0xa7, 0x1f, 0x82, 0xc4,
|
|
0x1f, 0xc8, 0xda, 0x51, 0x7b, 0xe1, 0x34, 0x04, 0x98, 0x32, 0xe6, 0x82, 0x5c,
|
|
0x92, 0xda, 0x6b, 0x84, 0xfe, 0xe4, 0xc6, 0x0d, 0x37, 0x78, 0x05, 0x9d, 0xc5,
|
|
0x69, 0xe7, 0xd0, 0xd3, 0x23, 0x91, 0x57, 0x3f, 0x95, 0x1b, 0xbd, 0xe9, 0x2f,
|
|
0xc6, 0xb9, 0xcf, 0x61, 0x47, 0x73, 0x66, 0x1c, 0x5c, 0x27, 0x3a, 0xa6, 0x99,
|
|
0x0c, 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb,
|
|
0x47, 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1,
|
|
0x93, 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc, 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff,
|
|
0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10, 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4,
|
|
0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0, 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
|
|
]),
|
|
xfvk: [
|
|
0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
|
|
0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
|
|
0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
|
|
0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
|
|
0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
|
|
0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0x30, 0x4e, 0x30, 0x59, 0x16,
|
|
0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae, 0x50, 0xec, 0xd1, 0x88, 0xfc,
|
|
0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f, 0x30, 0x77, 0x25, 0xe2, 0xee,
|
|
0x11, 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb,
|
|
0x47, 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1,
|
|
0x93, 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc, 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff,
|
|
0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10, 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4,
|
|
0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0, 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
|
|
],
|
|
fp: [
|
|
0x48, 0xc1, 0x83, 0x75, 0x7b, 0x5d, 0xa6, 0x61, 0x2a, 0x81, 0xb3, 0x0e, 0x40,
|
|
0xb4, 0xac, 0xaa, 0x2d, 0x9e, 0x73, 0x95, 0x12, 0xe1, 0xd2, 0xd0, 0x01, 0x0e,
|
|
0x92, 0xa7, 0xf7, 0xf2, 0xfc, 0xdf,
|
|
],
|
|
d0: Some([
|
|
0xe8, 0xd0, 0x37, 0x93, 0xcd, 0xd2, 0xba, 0xcc, 0x9c, 0x70, 0x41,
|
|
]),
|
|
d1: Some([
|
|
0x02, 0x0a, 0x7a, 0x6b, 0x0b, 0xf8, 0x4d, 0x3e, 0x89, 0x9f, 0x68,
|
|
]),
|
|
d2: None,
|
|
dmax: None,
|
|
internal_nsk: Some([
|
|
0x34, 0x78, 0x65, 0xac, 0xf4, 0x7e, 0x50, 0x45, 0x38, 0xf5, 0xef, 0x8b, 0x04,
|
|
0x70, 0x20, 0x80, 0xe6, 0x09, 0x1c, 0xda, 0x57, 0x97, 0xcd, 0x7d, 0x23, 0x5a,
|
|
0x54, 0x6e, 0xb1, 0x0f, 0x55, 0x08,
|
|
]),
|
|
internal_ovk: [
|
|
0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13, 0xde,
|
|
0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b, 0xaf,
|
|
0x94, 0x05, 0xce, 0x78, 0x04, 0xfd,
|
|
],
|
|
internal_dk: [
|
|
0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce, 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4,
|
|
0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59, 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f,
|
|
0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
|
|
],
|
|
internal_nk: [
|
|
0xf9, 0x12, 0x87, 0xc0, 0x6e, 0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2,
|
|
0x31, 0xde, 0x67, 0x78, 0xa5, 0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a,
|
|
0xba, 0xca, 0xe0, 0xaa, 0xe2, 0x3b,
|
|
],
|
|
internal_ivk: [
|
|
0x1d, 0x59, 0xea, 0x20, 0x17, 0x88, 0x18, 0x64, 0xd2, 0x4e, 0xad, 0xb5, 0xcf,
|
|
0x34, 0x68, 0xa4, 0x1a, 0x1b, 0x2a, 0xaa, 0x0d, 0x1b, 0x3a, 0x72, 0xc6, 0xda,
|
|
0x9c, 0xe6, 0x50, 0x2a, 0x0a, 0x05,
|
|
],
|
|
internal_xsk: Some([
|
|
0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
|
|
0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
|
|
0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
|
|
0xd4, 0x35, 0x8b, 0xe8, 0x11, 0x3c, 0xee, 0x34, 0x13, 0xa7, 0x1f, 0x82, 0xc4,
|
|
0x1f, 0xc8, 0xda, 0x51, 0x7b, 0xe1, 0x34, 0x04, 0x98, 0x32, 0xe6, 0x82, 0x5c,
|
|
0x92, 0xda, 0x6b, 0x84, 0xfe, 0xe4, 0xc6, 0x0d, 0x34, 0x78, 0x65, 0xac, 0xf4,
|
|
0x7e, 0x50, 0x45, 0x38, 0xf5, 0xef, 0x8b, 0x04, 0x70, 0x20, 0x80, 0xe6, 0x09,
|
|
0x1c, 0xda, 0x57, 0x97, 0xcd, 0x7d, 0x23, 0x5a, 0x54, 0x6e, 0xb1, 0x0f, 0x55,
|
|
0x08, 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13,
|
|
0xde, 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b,
|
|
0xaf, 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd, 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce,
|
|
0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4, 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59,
|
|
0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f, 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
|
|
]),
|
|
internal_xfvk: [
|
|
0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
|
|
0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
|
|
0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
|
|
0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
|
|
0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
|
|
0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0xf9, 0x12, 0x87, 0xc0, 0x6e,
|
|
0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2, 0x31, 0xde, 0x67, 0x78, 0xa5,
|
|
0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a, 0xba, 0xca, 0xe0, 0xaa, 0xe2,
|
|
0x3b, 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13,
|
|
0xde, 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b,
|
|
0xaf, 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd, 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce,
|
|
0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4, 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59,
|
|
0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f, 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
|
|
],
|
|
internal_fp: [
|
|
0x30, 0xfe, 0x0d, 0x61, 0x0f, 0x94, 0x7b, 0x2c, 0x26, 0x0e, 0x7b, 0x29, 0xe7,
|
|
0x9e, 0x5c, 0x2e, 0x7d, 0x3e, 0x14, 0xab, 0xf9, 0x79, 0xf6, 0x40, 0x6d, 0x07,
|
|
0xba, 0xf8, 0xfa, 0xdd, 0xf4, 0x95,
|
|
],
|
|
},
|
|
TestVector {
|
|
ask: None,
|
|
nsk: None,
|
|
ovk: [
|
|
0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb, 0x47,
|
|
0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1, 0x93,
|
|
0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc,
|
|
],
|
|
dk: [
|
|
0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff, 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10,
|
|
0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4, 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0,
|
|
0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
|
|
],
|
|
c: [
|
|
0x97, 0xce, 0x15, 0xf4, 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b,
|
|
0xcb, 0x3d, 0xc9, 0xb3, 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42,
|
|
0x77, 0x73, 0x83, 0xa8, 0xd4, 0x35,
|
|
],
|
|
ak: [
|
|
0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e, 0x3a, 0x49,
|
|
0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4, 0x52, 0x0e,
|
|
0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41,
|
|
],
|
|
nk: [
|
|
0x30, 0x4e, 0x30, 0x59, 0x16, 0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae,
|
|
0x50, 0xec, 0xd1, 0x88, 0xfc, 0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f,
|
|
0x30, 0x77, 0x25, 0xe2, 0xee, 0x11,
|
|
],
|
|
ivk: [
|
|
0xa2, 0xa1, 0x3c, 0x1e, 0x38, 0xb4, 0x59, 0x84, 0x44, 0x58, 0x03, 0xe4, 0x30,
|
|
0xa6, 0x83, 0xc9, 0x0b, 0xb2, 0xe1, 0x4d, 0x4c, 0x86, 0x92, 0xff, 0x25, 0x3a,
|
|
0x64, 0x84, 0xdd, 0x9b, 0xb5, 0x04,
|
|
],
|
|
xsk: None,
|
|
xfvk: [
|
|
0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
|
|
0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
|
|
0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
|
|
0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
|
|
0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
|
|
0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0x30, 0x4e, 0x30, 0x59, 0x16,
|
|
0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae, 0x50, 0xec, 0xd1, 0x88, 0xfc,
|
|
0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f, 0x30, 0x77, 0x25, 0xe2, 0xee,
|
|
0x11, 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb,
|
|
0x47, 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1,
|
|
0x93, 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc, 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff,
|
|
0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10, 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4,
|
|
0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0, 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
|
|
],
|
|
fp: [
|
|
0x48, 0xc1, 0x83, 0x75, 0x7b, 0x5d, 0xa6, 0x61, 0x2a, 0x81, 0xb3, 0x0e, 0x40,
|
|
0xb4, 0xac, 0xaa, 0x2d, 0x9e, 0x73, 0x95, 0x12, 0xe1, 0xd2, 0xd0, 0x01, 0x0e,
|
|
0x92, 0xa7, 0xf7, 0xf2, 0xfc, 0xdf,
|
|
],
|
|
d0: Some([
|
|
0xe8, 0xd0, 0x37, 0x93, 0xcd, 0xd2, 0xba, 0xcc, 0x9c, 0x70, 0x41,
|
|
]),
|
|
d1: Some([
|
|
0x02, 0x0a, 0x7a, 0x6b, 0x0b, 0xf8, 0x4d, 0x3e, 0x89, 0x9f, 0x68,
|
|
]),
|
|
d2: None,
|
|
dmax: None,
|
|
internal_nsk: None,
|
|
internal_ovk: [
|
|
0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13, 0xde,
|
|
0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b, 0xaf,
|
|
0x94, 0x05, 0xce, 0x78, 0x04, 0xfd,
|
|
],
|
|
internal_dk: [
|
|
0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce, 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4,
|
|
0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59, 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f,
|
|
0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
|
|
],
|
|
internal_nk: [
|
|
0xf9, 0x12, 0x87, 0xc0, 0x6e, 0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2,
|
|
0x31, 0xde, 0x67, 0x78, 0xa5, 0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a,
|
|
0xba, 0xca, 0xe0, 0xaa, 0xe2, 0x3b,
|
|
],
|
|
internal_ivk: [
|
|
0x1d, 0x59, 0xea, 0x20, 0x17, 0x88, 0x18, 0x64, 0xd2, 0x4e, 0xad, 0xb5, 0xcf,
|
|
0x34, 0x68, 0xa4, 0x1a, 0x1b, 0x2a, 0xaa, 0x0d, 0x1b, 0x3a, 0x72, 0xc6, 0xda,
|
|
0x9c, 0xe6, 0x50, 0x2a, 0x0a, 0x05,
|
|
],
|
|
internal_xsk: None,
|
|
internal_xfvk: [
|
|
0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
|
|
0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
|
|
0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
|
|
0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
|
|
0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
|
|
0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0xf9, 0x12, 0x87, 0xc0, 0x6e,
|
|
0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2, 0x31, 0xde, 0x67, 0x78, 0xa5,
|
|
0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a, 0xba, 0xca, 0xe0, 0xaa, 0xe2,
|
|
0x3b, 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13,
|
|
0xde, 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b,
|
|
0xaf, 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd, 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce,
|
|
0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4, 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59,
|
|
0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f, 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
|
|
],
|
|
internal_fp: [
|
|
0x30, 0xfe, 0x0d, 0x61, 0x0f, 0x94, 0x7b, 0x2c, 0x26, 0x0e, 0x7b, 0x29, 0xe7,
|
|
0x9e, 0x5c, 0x2e, 0x7d, 0x3e, 0x14, 0xab, 0xf9, 0x79, 0xf6, 0x40, 0x6d, 0x07,
|
|
0xba, 0xf8, 0xfa, 0xdd, 0xf4, 0x95,
|
|
],
|
|
},
|
|
TestVector {
|
|
ask: None,
|
|
nsk: None,
|
|
ovk: [
|
|
0x69, 0xb9, 0xe0, 0xfa, 0x1c, 0x4b, 0x3d, 0xeb, 0x91, 0xd5, 0x3b, 0xee, 0xe8,
|
|
0x71, 0x15, 0x61, 0x21, 0x47, 0x4b, 0x8b, 0x62, 0xef, 0x24, 0x13, 0x44, 0x78,
|
|
0xdc, 0x34, 0x99, 0x69, 0x1a, 0xf6,
|
|
],
|
|
dk: [
|
|
0xbe, 0xcb, 0x50, 0xc3, 0x63, 0xbb, 0x2e, 0xd9, 0xda, 0x5c, 0x30, 0x43, 0xce,
|
|
0xb0, 0xf1, 0xa0, 0x52, 0x7b, 0xf8, 0x36, 0xb2, 0x9a, 0x35, 0xf7, 0xc0, 0xc9,
|
|
0xf2, 0x61, 0x12, 0x3b, 0xe5, 0x6e,
|
|
],
|
|
c: [
|
|
0x8d, 0x93, 0x7b, 0xcf, 0x81, 0xba, 0x43, 0x0d, 0x5b, 0x49, 0xaf, 0xc0, 0xa4,
|
|
0x03, 0x36, 0x7b, 0x1f, 0xd9, 0x98, 0x79, 0xec, 0xba, 0x41, 0xbe, 0x05, 0x1c,
|
|
0x5a, 0x4a, 0xa7, 0xd6, 0xe7, 0xe8,
|
|
],
|
|
ak: [
|
|
0xb1, 0x85, 0xc5, 0x7b, 0x50, 0x9c, 0x25, 0x36, 0xc4, 0xf2, 0xd3, 0x26, 0xd7,
|
|
0x66, 0xc8, 0xfa, 0xb2, 0x54, 0x47, 0xde, 0x53, 0x75, 0xa9, 0x32, 0x8d, 0x64,
|
|
0x9d, 0xda, 0xbd, 0x97, 0xa6, 0xa3,
|
|
],
|
|
nk: [
|
|
0xdb, 0x88, 0x04, 0x9e, 0x02, 0xd2, 0x07, 0x56, 0x8a, 0xfc, 0x42, 0xe0, 0x7d,
|
|
0xb2, 0xab, 0xed, 0x50, 0x0b, 0x27, 0x01, 0xc0, 0x1b, 0xbf, 0xf3, 0x63, 0x99,
|
|
0x76, 0x4b, 0x81, 0xc0, 0x66, 0x4f,
|
|
],
|
|
ivk: [
|
|
0xb0, 0xa5, 0xf3, 0x37, 0x23, 0x2f, 0x2c, 0x3d, 0xac, 0x70, 0xc2, 0xa4, 0x10,
|
|
0xfa, 0x56, 0x1f, 0xc4, 0x5d, 0x8c, 0xc5, 0x9c, 0xda, 0x24, 0x6d, 0x31, 0xc8,
|
|
0xb1, 0x71, 0x5a, 0x57, 0xd9, 0x00,
|
|
],
|
|
xsk: None,
|
|
xfvk: [
|
|
0x03, 0x48, 0xc1, 0x83, 0x75, 0x03, 0x00, 0x00, 0x00, 0x8d, 0x93, 0x7b, 0xcf,
|
|
0x81, 0xba, 0x43, 0x0d, 0x5b, 0x49, 0xaf, 0xc0, 0xa4, 0x03, 0x36, 0x7b, 0x1f,
|
|
0xd9, 0x98, 0x79, 0xec, 0xba, 0x41, 0xbe, 0x05, 0x1c, 0x5a, 0x4a, 0xa7, 0xd6,
|
|
0xe7, 0xe8, 0xb1, 0x85, 0xc5, 0x7b, 0x50, 0x9c, 0x25, 0x36, 0xc4, 0xf2, 0xd3,
|
|
0x26, 0xd7, 0x66, 0xc8, 0xfa, 0xb2, 0x54, 0x47, 0xde, 0x53, 0x75, 0xa9, 0x32,
|
|
0x8d, 0x64, 0x9d, 0xda, 0xbd, 0x97, 0xa6, 0xa3, 0xdb, 0x88, 0x04, 0x9e, 0x02,
|
|
0xd2, 0x07, 0x56, 0x8a, 0xfc, 0x42, 0xe0, 0x7d, 0xb2, 0xab, 0xed, 0x50, 0x0b,
|
|
0x27, 0x01, 0xc0, 0x1b, 0xbf, 0xf3, 0x63, 0x99, 0x76, 0x4b, 0x81, 0xc0, 0x66,
|
|
0x4f, 0x69, 0xb9, 0xe0, 0xfa, 0x1c, 0x4b, 0x3d, 0xeb, 0x91, 0xd5, 0x3b, 0xee,
|
|
0xe8, 0x71, 0x15, 0x61, 0x21, 0x47, 0x4b, 0x8b, 0x62, 0xef, 0x24, 0x13, 0x44,
|
|
0x78, 0xdc, 0x34, 0x99, 0x69, 0x1a, 0xf6, 0xbe, 0xcb, 0x50, 0xc3, 0x63, 0xbb,
|
|
0x2e, 0xd9, 0xda, 0x5c, 0x30, 0x43, 0xce, 0xb0, 0xf1, 0xa0, 0x52, 0x7b, 0xf8,
|
|
0x36, 0xb2, 0x9a, 0x35, 0xf7, 0xc0, 0xc9, 0xf2, 0x61, 0x12, 0x3b, 0xe5, 0x6e,
|
|
],
|
|
fp: [
|
|
0x2e, 0x08, 0x15, 0x6d, 0xf8, 0xdf, 0xa2, 0x5b, 0x50, 0x55, 0xfc, 0x06, 0x3c,
|
|
0x67, 0x15, 0x35, 0xa6, 0xa6, 0x5a, 0x60, 0x43, 0x7d, 0x96, 0xe7, 0x93, 0x08,
|
|
0x15, 0xd0, 0x90, 0xf6, 0x2d, 0x67,
|
|
],
|
|
d0: None,
|
|
d1: Some([
|
|
0x03, 0x0f, 0xfb, 0x26, 0x3a, 0x93, 0x9e, 0x23, 0x0e, 0x96, 0xdd,
|
|
]),
|
|
d2: Some([
|
|
0x7b, 0xbf, 0x63, 0x93, 0x4c, 0x7e, 0x92, 0x67, 0x0c, 0xdb, 0x55,
|
|
]),
|
|
dmax: Some([
|
|
0x1a, 0x73, 0x0f, 0xeb, 0x00, 0x59, 0xcf, 0x1f, 0x5b, 0xde, 0xa8,
|
|
]),
|
|
internal_nsk: None,
|
|
internal_ovk: [
|
|
0xbf, 0x19, 0xe2, 0x57, 0xdd, 0x83, 0x3e, 0x02, 0x94, 0xec, 0x2a, 0xcb, 0xdf,
|
|
0xa4, 0x0e, 0x14, 0x52, 0xf8, 0xe6, 0xa1, 0xf0, 0xc7, 0xf6, 0xf3, 0xab, 0xe5,
|
|
0x6a, 0xfd, 0x5f, 0x6e, 0x26, 0x18,
|
|
],
|
|
internal_dk: [
|
|
0x1f, 0xfd, 0x6f, 0x81, 0xfe, 0x85, 0xc4, 0x9f, 0xe3, 0xe7, 0x3e, 0xf7, 0x3e,
|
|
0x50, 0x11, 0x38, 0x22, 0xca, 0x62, 0x67, 0x31, 0x2b, 0x7a, 0xce, 0xd0, 0xc1,
|
|
0x56, 0xa3, 0x2b, 0x3f, 0x24, 0x38,
|
|
],
|
|
internal_nk: [
|
|
0x82, 0x2f, 0x2f, 0x70, 0x96, 0x0f, 0x05, 0xd6, 0x96, 0x74, 0x58, 0xe3, 0x92,
|
|
0x10, 0xd5, 0x77, 0x1f, 0x98, 0x47, 0xae, 0xf9, 0xe3, 0x4d, 0x94, 0xb8, 0xaf,
|
|
0xbf, 0x95, 0xbb, 0xc4, 0xd2, 0x27,
|
|
],
|
|
internal_ivk: [
|
|
0xf9, 0x8a, 0x76, 0x09, 0x8e, 0x91, 0x05, 0x03, 0xe8, 0x02, 0x77, 0x52, 0x04,
|
|
0x2d, 0xe8, 0x7e, 0x7d, 0x89, 0x3a, 0xb0, 0x14, 0x5e, 0xbc, 0x3b, 0x05, 0x97,
|
|
0xc2, 0x39, 0x7f, 0x69, 0xd2, 0x01,
|
|
],
|
|
internal_xsk: None,
|
|
internal_xfvk: [
|
|
0x03, 0x48, 0xc1, 0x83, 0x75, 0x03, 0x00, 0x00, 0x00, 0x8d, 0x93, 0x7b, 0xcf,
|
|
0x81, 0xba, 0x43, 0x0d, 0x5b, 0x49, 0xaf, 0xc0, 0xa4, 0x03, 0x36, 0x7b, 0x1f,
|
|
0xd9, 0x98, 0x79, 0xec, 0xba, 0x41, 0xbe, 0x05, 0x1c, 0x5a, 0x4a, 0xa7, 0xd6,
|
|
0xe7, 0xe8, 0xb1, 0x85, 0xc5, 0x7b, 0x50, 0x9c, 0x25, 0x36, 0xc4, 0xf2, 0xd3,
|
|
0x26, 0xd7, 0x66, 0xc8, 0xfa, 0xb2, 0x54, 0x47, 0xde, 0x53, 0x75, 0xa9, 0x32,
|
|
0x8d, 0x64, 0x9d, 0xda, 0xbd, 0x97, 0xa6, 0xa3, 0x82, 0x2f, 0x2f, 0x70, 0x96,
|
|
0x0f, 0x05, 0xd6, 0x96, 0x74, 0x58, 0xe3, 0x92, 0x10, 0xd5, 0x77, 0x1f, 0x98,
|
|
0x47, 0xae, 0xf9, 0xe3, 0x4d, 0x94, 0xb8, 0xaf, 0xbf, 0x95, 0xbb, 0xc4, 0xd2,
|
|
0x27, 0xbf, 0x19, 0xe2, 0x57, 0xdd, 0x83, 0x3e, 0x02, 0x94, 0xec, 0x2a, 0xcb,
|
|
0xdf, 0xa4, 0x0e, 0x14, 0x52, 0xf8, 0xe6, 0xa1, 0xf0, 0xc7, 0xf6, 0xf3, 0xab,
|
|
0xe5, 0x6a, 0xfd, 0x5f, 0x6e, 0x26, 0x18, 0x1f, 0xfd, 0x6f, 0x81, 0xfe, 0x85,
|
|
0xc4, 0x9f, 0xe3, 0xe7, 0x3e, 0xf7, 0x3e, 0x50, 0x11, 0x38, 0x22, 0xca, 0x62,
|
|
0x67, 0x31, 0x2b, 0x7a, 0xce, 0xd0, 0xc1, 0x56, 0xa3, 0x2b, 0x3f, 0x24, 0x38,
|
|
],
|
|
internal_fp: [
|
|
0xba, 0x64, 0xe4, 0x0d, 0x08, 0x6d, 0x36, 0x2c, 0xa5, 0xa1, 0x7f, 0x5e, 0x3b,
|
|
0x1b, 0xee, 0x63, 0x24, 0xc8, 0x4f, 0x10, 0x12, 0x44, 0xa4, 0x00, 0x2a, 0x2e,
|
|
0xca, 0xaf, 0x05, 0xbd, 0xd9, 0x81,
|
|
],
|
|
},
|
|
];
|
|
|
|
let seed = [
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
|
24, 25, 26, 27, 28, 29, 30, 31,
|
|
];
|
|
|
|
let i1 = ChildIndex::NonHardened(1);
|
|
let i2h = ChildIndex::Hardened(2);
|
|
let i3 = ChildIndex::NonHardened(3);
|
|
|
|
let m = ExtendedSpendingKey::master(&seed);
|
|
let m_1 = m.derive_child(i1);
|
|
let m_1_2h = ExtendedSpendingKey::from_path(&m, &[i1, i2h]);
|
|
let m_1_2hv = ExtendedFullViewingKey::from(&m_1_2h);
|
|
let m_1_2hv_3 = m_1_2hv.derive_child(i3).unwrap();
|
|
|
|
let xfvks = [
|
|
ExtendedFullViewingKey::from(&m),
|
|
ExtendedFullViewingKey::from(&m_1),
|
|
ExtendedFullViewingKey::from(&m_1_2h),
|
|
m_1_2hv, // Appears twice so we can de-duplicate test code below
|
|
m_1_2hv_3,
|
|
];
|
|
assert_eq!(test_vectors.len(), xfvks.len());
|
|
|
|
let xsks = [m, m_1, m_1_2h];
|
|
|
|
for (xsk, tv) in xsks.iter().zip(test_vectors.iter()) {
|
|
assert_eq!(xsk.expsk.ask.to_repr().as_ref(), tv.ask.unwrap());
|
|
assert_eq!(xsk.expsk.nsk.to_repr().as_ref(), tv.nsk.unwrap());
|
|
|
|
assert_eq!(xsk.expsk.ovk.0, tv.ovk);
|
|
assert_eq!(xsk.dk.0, tv.dk);
|
|
assert_eq!(xsk.chain_code.0, tv.c);
|
|
|
|
let mut ser = vec![];
|
|
xsk.write(&mut ser).unwrap();
|
|
assert_eq!(&ser[..], &tv.xsk.unwrap()[..]);
|
|
|
|
let internal_xsk = xsk.derive_internal();
|
|
assert_eq!(internal_xsk.expsk.ask.to_repr().as_ref(), tv.ask.unwrap());
|
|
assert_eq!(
|
|
internal_xsk.expsk.nsk.to_repr().as_ref(),
|
|
tv.internal_nsk.unwrap()
|
|
);
|
|
|
|
assert_eq!(internal_xsk.expsk.ovk.0, tv.internal_ovk);
|
|
assert_eq!(internal_xsk.dk.0, tv.internal_dk);
|
|
assert_eq!(internal_xsk.chain_code.0, tv.c);
|
|
|
|
let mut ser = vec![];
|
|
internal_xsk.write(&mut ser).unwrap();
|
|
assert_eq!(&ser[..], &tv.internal_xsk.unwrap()[..]);
|
|
}
|
|
|
|
for (xfvk, tv) in xfvks.iter().zip(test_vectors.iter()) {
|
|
assert_eq!(xfvk.fvk.vk.ak.to_bytes(), tv.ak);
|
|
assert_eq!(xfvk.fvk.vk.nk.to_bytes(), tv.nk);
|
|
|
|
assert_eq!(xfvk.fvk.ovk.0, tv.ovk);
|
|
assert_eq!(xfvk.dk.0, tv.dk);
|
|
assert_eq!(xfvk.chain_code.0, tv.c);
|
|
|
|
assert_eq!(xfvk.fvk.vk.ivk().to_repr().as_ref(), tv.ivk);
|
|
|
|
let mut ser = vec![];
|
|
xfvk.write(&mut ser).unwrap();
|
|
assert_eq!(&ser[..], &tv.xfvk[..]);
|
|
assert_eq!(FvkFingerprint::from(&xfvk.fvk).0, tv.fp);
|
|
|
|
// d0
|
|
let mut di = DiversifierIndex::new();
|
|
match xfvk.dk.find_diversifier(di).unwrap() {
|
|
(l, d) if l == di => assert_eq!(d.0, tv.d0.unwrap()),
|
|
(_, _) => assert!(tv.d0.is_none()),
|
|
}
|
|
|
|
// d1
|
|
di.increment().unwrap();
|
|
match xfvk.dk.find_diversifier(di).unwrap() {
|
|
(l, d) if l == di => assert_eq!(d.0, tv.d1.unwrap()),
|
|
(_, _) => assert!(tv.d1.is_none()),
|
|
}
|
|
|
|
// d2
|
|
di.increment().unwrap();
|
|
match xfvk.dk.find_diversifier(di).unwrap() {
|
|
(l, d) if l == di => assert_eq!(d.0, tv.d2.unwrap()),
|
|
(_, _) => assert!(tv.d2.is_none()),
|
|
}
|
|
|
|
// dmax
|
|
let dmax = DiversifierIndex([0xff; 11]);
|
|
match xfvk.dk.find_diversifier(dmax) {
|
|
Some((l, d)) if l == dmax => assert_eq!(d.0, tv.dmax.unwrap()),
|
|
Some((_, _)) => panic!(),
|
|
None => assert!(tv.dmax.is_none()),
|
|
}
|
|
|
|
let internal_xfvk = xfvk.derive_internal();
|
|
assert_eq!(internal_xfvk.fvk.vk.ak.to_bytes(), tv.ak);
|
|
assert_eq!(internal_xfvk.fvk.vk.nk.to_bytes(), tv.internal_nk);
|
|
|
|
assert_eq!(internal_xfvk.fvk.ovk.0, tv.internal_ovk);
|
|
assert_eq!(internal_xfvk.dk.0, tv.internal_dk);
|
|
assert_eq!(internal_xfvk.chain_code.0, tv.c);
|
|
|
|
assert_eq!(
|
|
internal_xfvk.fvk.vk.ivk().to_repr().as_ref(),
|
|
tv.internal_ivk
|
|
);
|
|
|
|
let mut ser = vec![];
|
|
internal_xfvk.write(&mut ser).unwrap();
|
|
assert_eq!(&ser[..], &tv.internal_xfvk[..]);
|
|
assert_eq!(FvkFingerprint::from(&internal_xfvk.fvk).0, tv.internal_fp);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(any(test, feature = "test-dependencies"))]
|
|
pub mod testing {
|
|
use proptest::prelude::*;
|
|
|
|
use super::ExtendedSpendingKey;
|
|
|
|
prop_compose! {
|
|
pub fn arb_extended_spending_key()(seed in prop::array::uniform32(prop::num::u8::ANY)) -> ExtendedSpendingKey {
|
|
ExtendedSpendingKey::master(&seed)
|
|
}
|
|
}
|
|
}
|