Skip to content

Commit

Permalink
correct nullifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
jleni committed May 8, 2024
1 parent d826d88 commit 9aeef63
Show file tree
Hide file tree
Showing 16 changed files with 143 additions and 140 deletions.
4 changes: 2 additions & 2 deletions app/rust/include/zip32.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ void get_diversifier_list(const uint8_t *sk_ptr, uint8_t *diversifier_list);

void get_diversifier_fromlist(const uint8_t *diversifier_list, uint8_t *diversifier);

bool is_valid_diversifier(const uint8_t *diversifier);
bool diversifier_is_valid(const uint8_t *diversifier);

void get_diversifier_list_withstartindex(const uint8_t *seed_ptr, const uint32_t pos, const uint8_t *startindex,
uint8_t *diversifier_list);
Expand All @@ -24,7 +24,7 @@ void zip32_child_ask_nsk(const uint8_t *seed_ptr, uint8_t *ask, uint8_t *nsk, co
/**
* @deprecated This function is deprecated and should not be used in new code.
*/
void zip32_nsk_from_seed(const uint8_t *seed_ptr, uint8_t *nsk);
void zip32_nsk_from_seed(const uint8_t *seed_ptr, uint32_t zip32_path, uint8_t *nsk);

/**
* @deprecated This function is deprecated and should not be used in new code.
Expand Down
3 changes: 2 additions & 1 deletion app/rust/src/commitments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ mod tests {

#[test]
fn test_get_nf() {
let account = 1;
let pos: u64 = 2578461368;

let seed: [u8; 32] = [
Expand All @@ -257,7 +258,7 @@ mod tests {
];

let mut nsk = [0u8; 32];
zip32_nsk_from_seed(&seed, &mut nsk);
zip32_nsk_from_seed(&seed, account, &mut nsk);

let mut nf = [0u8; 32];
compute_nullifier(&cm, pos, &nsk, &mut nf);
Expand Down
4 changes: 2 additions & 2 deletions app/rust/src/commitments_extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use jubjub::Fr;
#[no_mangle]
pub extern "C" fn compute_nullifier(
ncm_ptr: *const [u8; 32],
pos: u64,
note_pos: u64,
nsk_ptr: *const [u8; 32],
output_ptr: *mut [u8; 32],
) {
Expand All @@ -22,7 +22,7 @@ pub extern "C" fn compute_nullifier(

crate::bolos::heartbeat();

let scalar = Fr::from(pos);
let scalar = Fr::from(note_pos);
let e = cryptoops::bytes_to_extended(ncm);
crate::bolos::heartbeat();

Expand Down
12 changes: 7 additions & 5 deletions app/rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub type DkBytes = [u8; 32];
// FIXME: move to 64 to align with ed25519 private key?
pub type Zip32Seed = [u8; 32];

pub type Zip32Path = [u32];

pub type Zip32MasterSpendingKey = [u8; 32];
pub type Zip32MasterChainCode = [u8; 32];

Expand Down Expand Up @@ -75,22 +77,22 @@ create_ztruct! {
}
}

// https://zips.z.cash/zip-0032#specification-sapling-key-derivation
create_ztruct! {
pub struct SaplingExtendedSpendingKey {
pub struct SaplingKeyBundle {
pub ask: AskBytes,
pub nsk: NskBytes,
pub ovk: OvkBytes,
pub dk: DkBytes,
pub chain_code: Zip32MasterChainCode,
}
}

// https://zips.z.cash/zip-0032#specification-sapling-key-derivation
create_ztruct! {
pub struct SaplingKeyBundle {
pub struct SaplingExtendedSpendingKey {
pub ask: AskBytes,
pub nsk: NskBytes,
pub dk: DkBytes,
pub ovk: OvkBytes,
pub dk: DkBytes,
pub chain_code: Zip32MasterChainCode,
}
}
110 changes: 32 additions & 78 deletions app/rust/src/zip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use crate::personalization::ZIP32_SAPLING_MASTER_PERSONALIZATION;
use crate::sapling::{sapling_aknk_to_ivk, sapling_ask_to_ak, sapling_nsk_to_nk};
use crate::types::{
diversifier_zero, AskBytes, Diversifier, DiversifierList10, DiversifierList20,
DiversifierList4, DkBytes, FullViewingKey, NskBytes, OvkBytes, SaplingKeyBundle,
SaplingExpandedSpendingKey, Zip32MasterKey, Zip32Seed,
DiversifierList4, DkBytes, FullViewingKey, IvkBytes, NskBytes, OvkBytes,
SaplingExpandedSpendingKey, SaplingKeyBundle, Zip32MasterKey, Zip32MasterSpendingKey,
Zip32Path, Zip32Seed,
};

#[inline(never)]
Expand Down Expand Up @@ -234,7 +235,7 @@ pub fn pkd_group_hash(d: &Diversifier) -> [u8; 32] {
}

#[inline(never)]
pub fn default_pkd(ivk: &[u8; 32], d: &Diversifier) -> [u8; 32] {
pub fn pkd_default(ivk: &IvkBytes, d: &Diversifier) -> [u8; 32] {
let h = blake2b::blake2s_diversification(d);
let mut y = bytes_to_extended(h);

Expand All @@ -245,15 +246,6 @@ pub fn default_pkd(ivk: &[u8; 32], d: &Diversifier) -> [u8; 32] {
tmp
}

#[inline(never)]
fn zip32_sapling_esk(s_k: &[u8; 32]) -> SaplingExpandedSpendingKey {
SaplingExpandedSpendingKey::new(
zip32_sapling_ask_m(s_k),
zip32_sapling_nsk_m(s_k),
zip32_sapling_ovk_m(s_k),
)
}

#[inline(never)]
pub(crate) fn zip32_sapling_fvk(k: &SaplingKeyBundle) -> FullViewingKey {
FullViewingKey::new(
Expand All @@ -266,8 +258,7 @@ pub(crate) fn zip32_sapling_fvk(k: &SaplingKeyBundle) -> FullViewingKey {
fn zip32_sapling_derive_child(
ik: &mut Zip32MasterKey,
path_i: u32,
esk_i: &mut SaplingExpandedSpendingKey,
mut dk_i: &mut DkBytes,
key_bundle_i: &mut SaplingKeyBundle,
) {
let hardened = (path_i & 0x8000_0000) != 0;
let c = path_i & 0x7FFF_FFFF;
Expand All @@ -284,7 +275,7 @@ fn zip32_sapling_derive_child(
//zip32 child derivation
let c_i = &ik.chain_code();

let prf_result = blake2b_expand_v4(c_i, &[0x11], &esk_i.to_bytes(), &*dk_i, &le_i);
let prf_result = blake2b_expand_v4(c_i, &[0x11], &key_bundle_i.to_bytes(), &[], &le_i);

ik.to_bytes_mut().copy_from_slice(&prf_result);
} else {
Expand All @@ -307,81 +298,44 @@ fn zip32_sapling_derive_child(

let fvk = FullViewingKey::new(ak, nk, ovk);

let prf_result =
blake2b_expand_v4(&ik.chain_code(), &[0x12], &fvk.to_bytes(), &*dk_i, &le_i);
let prf_result = blake2b_expand_v4(
&ik.chain_code(),
&[0x12],
&fvk.to_bytes(),
&key_bundle_i.dk(),
&le_i,
);

ik.to_bytes_mut().copy_from_slice(&prf_result);
}
crate::bolos::heartbeat();

// https://zips.z.cash/zip-0032#deriving-a-child-extended-spending-key

zip32_sapling_ask_i_update(&ik.spending_key(), esk_i.ask_mut());
zip32_sapling_nsk_i_update(&ik.spending_key(), esk_i.nsk_mut());
zip32_sapling_ovk_i_update(&ik.spending_key(), esk_i.ovk_mut());

zip32_sapling_dk_i_update(&ik.spending_key(), &mut dk_i);
zip32_sapling_ask_i_update(&ik.spending_key(), key_bundle_i.ask_mut());
zip32_sapling_nsk_i_update(&ik.spending_key(), key_bundle_i.nsk_mut());
zip32_sapling_ovk_i_update(&ik.spending_key(), key_bundle_i.ovk_mut());
zip32_sapling_dk_i_update(&ik.spending_key(), &mut key_bundle_i.dk_mut());
}

#[inline(never)]
pub fn zip32_sapling_derive(seed: &[u8; 32], path: &[u32]) -> SaplingKeyBundle {
pub fn zip32_sapling_derive(seed: &Zip32Seed, path: &Zip32Path) -> SaplingKeyBundle {
// ik as in capital I (https://zips.z.cash/zip-0032#sapling-child-key-derivation)
let mut ik = zip32_master_key_i(seed);
let mut esk_i = zip32_sapling_esk(&ik.spending_key());
let mut dk_i = zip32_sapling_dk_m(&ik.spending_key());

if cfg!(test) {
debug!("------------------------------ ");
debug!("---- s_k_i : {}", hex::encode(ik.spending_key()));
debug!("---- c_k_i : {}", hex::encode(ik.chain_code()));
debug!("---- ask_i : {}", hex::encode(esk_i.ask()));
debug!("---- nsk_i : {}", hex::encode(esk_i.nsk()));
debug!("---- osk_i : {}", hex::encode(esk_i.ovk()));
}

for path_i in path.iter().copied() {
zip32_sapling_derive_child(&mut ik, path_i, &mut esk_i, &mut dk_i);

if cfg!(test) {
debug!("---- path_i: {:x}", path_i);
debug!("---- s_k_i : {}", hex::encode(ik.spending_key()));
debug!("---- c_k_i : {}", hex::encode(ik.chain_code()));
debug!("---- ask_i : {}", hex::encode(esk_i.ask()));
debug!("---- nsk_i : {}", hex::encode(esk_i.nsk()));
debug!("---- osk_i : {}", hex::encode(esk_i.ovk()));
}
let mut key_bundle_i = SaplingKeyBundle::new(
zip32_sapling_ask_m(&ik.spending_key()),
zip32_sapling_nsk_m(&ik.spending_key()),
zip32_sapling_ovk_m(&ik.spending_key()),
zip32_sapling_dk_m(&ik.spending_key()),
);

for path_i in path.iter().copied() {
zip32_sapling_derive_child(&mut ik, path_i, &mut key_bundle_i);
c_check_app_canary();
}

if cfg!(test) {
debug!("------------------------------ ");
}

SaplingKeyBundle::new(esk_i.ask(), esk_i.nsk(), dk_i, esk_i.ovk())
}

#[inline(never)]
#[deprecated(note = "This function is deprecated and will be removed in future releases.")]
pub fn deprecated_master_nsk_from_seed(seed: &[u8; 32]) -> [u8; 32] {
let master_key = zip32_master_key_i(seed);

crate::bolos::heartbeat();
let nsk = Fr::from_bytes_wide(&cryptoops::prf_expand(&master_key.spending_key(), &[0x01]));

let mut result = [0u8; 32];
result.copy_from_slice(&nsk.to_bytes());
result
}

#[no_mangle]
pub fn zip32_sapling_dk(seed_ptr: *const Zip32Seed, account: u32, dk_ptr: *mut [u8; 32]) {
let seed = unsafe { &*seed_ptr };
let dk = unsafe { &mut *dk_ptr };

let k = zip32_sapling_derive(seed, &[ZIP32_PURPOSE, ZIP32_COIN_TYPE, account]);

dk.copy_from_slice(&k.dk());
key_bundle_i
}

#[inline(never)]
Expand Down Expand Up @@ -433,7 +387,7 @@ fn zip32_sapling_derive_master(seed: &Zip32Seed) -> SaplingKeyBundle {
let dk = zip32_sapling_dk_m(&master_key.spending_key());
let ovk = zip32_sapling_ovk_m(&master_key.spending_key());

SaplingKeyBundle::new(ask, nsk, dk, ovk)
SaplingKeyBundle::new(ask, nsk, ovk, dk)
}

#[cfg(test)]
Expand Down Expand Up @@ -800,7 +754,7 @@ mod tests {
ff1aes_list_10(&k.dk(), &mut listbytes);
let default_d = diversifier_default_fromlist(&listbytes);

let pk_d = default_pkd(&ivk, &default_d);
let pk_d = pkd_default(&ivk, &default_d);

assert_eq!(hex::encode(default_d), "9f6e0bf90a18fc0b9b83ae");
assert_eq!(
Expand Down Expand Up @@ -830,7 +784,7 @@ mod tests {
ff1aes_list_10(&k.dk(), &mut list);
let default_d = diversifier_default_fromlist(&list);

let pk_d = default_pkd(&ivk, &default_d);
let pk_d = pkd_default(&ivk, &default_d);

assert_eq!(hex::encode(default_d), "186df0ee24e1b09f3a8c0f");
assert_eq!(
Expand Down Expand Up @@ -859,7 +813,7 @@ mod tests {
ff1aes_list_10(&dk, &mut list);
let default_d = diversifier_default_fromlist(&list);

let pk_d = default_pkd(&ivk, &default_d);
let pk_d = pkd_default(&ivk, &default_d);

assert_eq!(hex::encode(default_d), "f93dcfe2047253eebc17d4");
assert_eq!(
Expand All @@ -885,7 +839,7 @@ mod tests {
ff1aes_list_10(&dk, &mut list);
let default_d = diversifier_default_fromlist(&list);

let pk_d = default_pkd(&ivk, &default_d);
let pk_d = pkd_default(&ivk, &default_d);

assert_eq!(hex::encode(default_d), "3bf6fa1f83bf4563c8a713");
assert_eq!(
Expand Down
38 changes: 21 additions & 17 deletions app/rust/src/zip32_extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::constants::{DIV_DEFAULT_LIST_LEN, DIV_SIZE, ZIP32_COIN_TYPE, ZIP32_PU
use crate::sapling::{sapling_aknk_to_ivk, sapling_ask_to_ak};
use crate::types::{
diversifier_zero, Diversifier, DiversifierList10, DiversifierList20, DiversifierList4,
SaplingKeyBundle, Zip32Seed,
NskBytes, Zip32Seed,
};
use crate::zip32::{diversifier_group_hash_light, zip32_sapling_derive, zip32_sapling_fvk};
use crate::{sapling, zip32};
Expand Down Expand Up @@ -128,14 +128,16 @@ pub extern "C" fn zip32_child_ask_nsk(
}

#[no_mangle]
#[deprecated(note = "This function is deprecated and will be removed in future releases.")]
pub extern "C" fn zip32_nsk_from_seed(seed_ptr: *const [u8; 32], nsk_ptr: *mut [u8; 32]) {
pub extern "C" fn zip32_nsk_from_seed(
seed_ptr: *const Zip32Seed,
account: u32,
nsk_ptr: *mut NskBytes,
) {
let seed = unsafe { &*seed_ptr };
let nsk = unsafe { &mut *nsk_ptr };
let k = zip32_sapling_derive(seed, &[ZIP32_PURPOSE, ZIP32_COIN_TYPE, account]);

let k = zip32::deprecated_master_nsk_from_seed(seed);

nsk.copy_from_slice(&k);
nsk.copy_from_slice(&k.nsk());
}

#[no_mangle]
Expand All @@ -151,31 +153,33 @@ pub extern "C" fn get_diversifier_list(
#[no_mangle]
pub extern "C" fn get_diversifier_list_withstartindex(
seed_ptr: *const [u8; 32],
pos: u32,
account: u32,
start_index: *const Diversifier,
diversifier_list_ptr: *mut DiversifierList20,
) {
let mut dk = [0u8; 32];
let seed = unsafe { &*seed_ptr };
let start = unsafe { &*start_index };
let diversifier = unsafe { &mut *diversifier_list_ptr };
zip32::zip32_sapling_dk(seed, pos, &mut dk);
zip32::ff1aes_list_with_startingindex_20(&mut dk, start, diversifier);

let k = zip32_sapling_derive(seed, &[ZIP32_PURPOSE, ZIP32_COIN_TYPE, account]);

zip32::ff1aes_list_with_startingindex_20(&mut k.dk(), start, diversifier);
}

#[no_mangle]
pub extern "C" fn get_default_diversifier_list_withstartindex(
seed_ptr: *const [u8; 32],
pos: u32,
seed_ptr: *const Zip32Seed,
account: u32,
start_ptr: *mut Diversifier,
diversifier_list_ptr: *mut DiversifierList4,
) {
let mut dk = [0u8; 32];
let seed = unsafe { &*seed_ptr };
let start = unsafe { &mut *start_ptr };
let diversifier = unsafe { &mut *diversifier_list_ptr };
zip32::zip32_sapling_dk(seed, pos, &mut dk);
zip32::ff1aes_list_with_startingindex_4(&mut dk, start, diversifier);

let k = zip32_sapling_derive(seed, &[ZIP32_PURPOSE, ZIP32_COIN_TYPE, account]);

zip32::ff1aes_list_with_startingindex_4(&mut k.dk(), start, diversifier);
}

#[no_mangle]
Expand Down Expand Up @@ -220,7 +224,7 @@ pub extern "C" fn get_pkd_from_seed(
sapling::sapling_asknsk_to_ivk(&k.ask().try_into().unwrap(), &k.nsk().try_into().unwrap());

let pkd = unsafe { &mut *pkd_ptr };
let tmp_pkd = zip32::default_pkd(&ivk, div);
let tmp_pkd = zip32::pkd_default(&ivk, div);
pkd.copy_from_slice(&tmp_pkd);
}

Expand Down Expand Up @@ -249,7 +253,7 @@ pub extern "C" fn get_pkd(
let pkd = unsafe { &mut *pkd_ptr };
zip32_ivk(seed_ptr, ivk_ptr, account);

let tmp_pkd = zip32::default_pkd(ivk_ptr, &diversifier);
let tmp_pkd = zip32::pkd_default(ivk_ptr, &diversifier);
pkd.copy_from_slice(&tmp_pkd)
}

Expand Down
3 changes: 2 additions & 1 deletion app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ __Z_INLINE void handleGetNullifier(volatile uint32_t *flags, volatile uint32_t *
// this needs to get Full viewing key = (ak, nk, ovk) and note position, to
// then compute nullifier G_io_apdu_buffer contains zip32path, note position,
// note commitment
zxerr_t err = crypto_nullifier_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, notepos, cm, &replyLen);
zxerr_t err = crypto_nullifier_sapling(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, zip32path, notepos, cm, &replyLen);

if (err != zxerr_ok) {
zemu_log("Failed to get nullifier!\n");
*tx = 0;
Expand Down

0 comments on commit 9aeef63

Please sign in to comment.