diff --git a/Cargo.lock b/Cargo.lock index dfdc517..c78abff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,33 @@ +[[package]] +name = "aes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-soft" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aesni" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayvec" version = "0.4.7" @@ -41,6 +71,19 @@ dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-cipher-trait" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.2" @@ -64,6 +107,18 @@ dependencies = [ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fpe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -122,6 +177,7 @@ dependencies = [ "pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1 (git+https://github.com/zcash-hackworks/sapling-crypto?rev=21084bde2019c04bd34208e63c3560fe2c02fb0e)", + "zip32 0.0.0 (git+https://github.com/zcash-hackworks/zip32?rev=176470ef41583b5bd0bd749bd1b61d417aa8ec79)", ] [[package]] @@ -129,6 +185,28 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-bigint" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.8.0" @@ -137,6 +215,11 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pairing" version = "0.14.2" @@ -169,6 +252,14 @@ dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "stream-cipher" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typenum" version = "1.10.0" @@ -193,16 +284,36 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "zip32" +version = "0.0.0" +source = "git+https://github.com/zcash-hackworks/zip32?rev=176470ef41583b5bd0bd749bd1b61d417aa8ec79#176470ef41583b5bd0bd749bd1b61d417aa8ec79" +dependencies = [ + "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sapling-crypto 0.0.1 (git+https://github.com/zcash-hackworks/sapling-crypto?rev=21084bde2019c04bd34208e63c3560fe2c02fb0e)", +] + [metadata] +"checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873" +"checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" +"checksum aesni 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2838c142db62c0c6aea0a24054c46d35488532fdaea0f51dbeba430f0985df5" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum bellman 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eae372472c7ea8f7c8fc6a62f7d5535db8302de7f1aafda2e13a97c4830d3bcf" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "" +"checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603" +"checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" @@ -211,11 +322,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eceac7784c5dc97c2d6edf30259b4e153e6e2b42b3c85e9a6e9f45d06caef6e" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" "checksum pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ceda21136251c6d5a422d3d798d8ac22515a6e8d3521bb60c59a8349d36d0d57" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum sapling-crypto 0.0.1 (git+https://github.com/zcash-hackworks/sapling-crypto?rev=21084bde2019c04bd34208e63c3560fe2c02fb0e)" = "" +"checksum stream-cipher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac49bc6cb2847200d18bfb738ce89448570f4aa1c34ac0348db6205ee69a0777" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum zip32 0.0.0 (git+https://github.com/zcash-hackworks/zip32?rev=176470ef41583b5bd0bd749bd1b61d417aa8ec79)" = "" diff --git a/Cargo.toml b/Cargo.toml index 91daec5..d1c9e7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,10 @@ rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" git = "https://github.com/zcash-hackworks/sapling-crypto" rev = "21084bde2019c04bd34208e63c3560fe2c02fb0e" +[dependencies.zip32] +git = "https://github.com/zcash-hackworks/zip32" +rev = "176470ef41583b5bd0bd749bd1b61d417aa8ec79" + [profile.release] lto = true panic = 'abort' diff --git a/include/librustzcash.h b/include/librustzcash.h index adab766..6fa9469 100644 --- a/include/librustzcash.h +++ b/include/librustzcash.h @@ -270,6 +270,35 @@ extern "C" { uint64_t vpub_old, uint64_t vpub_new ); + + /// Derive the master ExtendedSpendingKey from a seed. + void librustzcash_zip32_xsk_master( + const unsigned char *seed, + size_t seedlen, + unsigned char *xsk_master + ); + + /// Derive a child ExtendedSpendingKey from a parent. + void librustzcash_zip32_xsk_derive( + const unsigned char *xsk_parent, + uint32_t i, + unsigned char *xsk_i + ); + + /// Derive a child ExtendedFullViewingKey from a parent. + bool librustzcash_zip32_xfvk_derive( + const unsigned char *xfvk_parent, + uint32_t i, + unsigned char *xfvk_i + ); + + /// Derive a PaymentAddress from an ExtendedFullViewingKey. + bool librustzcash_zip32_xfvk_address( + const unsigned char *xfvk, + const unsigned char *j, + unsigned char *j_ret, + unsigned char *addr_ret + ); } #endif // LIBRUSTZCASH_INCLUDE_H_ diff --git a/src/rustzcash.rs b/src/rustzcash.rs index 8ca9647..86cb659 100644 --- a/src/rustzcash.rs +++ b/src/rustzcash.rs @@ -5,6 +5,7 @@ extern crate libc; extern crate pairing; extern crate rand; extern crate sapling_crypto; +extern crate zip32; mod hashreader; @@ -12,16 +13,20 @@ mod hashreader; extern crate lazy_static; use pairing::{ - bls12_381::{Bls12, Fr, FrRepr}, BitIterator, Field, PrimeField, PrimeFieldRepr, + bls12_381::{Bls12, Fr, FrRepr}, + BitIterator, Field, PrimeField, PrimeFieldRepr, }; use sapling_crypto::{ - circuit::multipack, constants::CRH_IVK_PERSONALIZATION, + circuit::multipack, + constants::CRH_IVK_PERSONALIZATION, jubjub::{ - edwards, fs::{Fs, FsRepr}, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, - PrimeOrder, ToUniform, Unknown, + edwards, + fs::{Fs, FsRepr}, + FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, PrimeOrder, ToUniform, Unknown, }, - pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{self, Signature}, + pedersen_hash::{pedersen_hash, Personalization}, + redjubjub::{self, Signature}, }; use sapling_crypto::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH}; @@ -1563,3 +1568,86 @@ pub extern "system" fn librustzcash_sapling_proving_ctx_init() -> *mut SaplingPr pub extern "system" fn librustzcash_sapling_proving_ctx_free(ctx: *mut SaplingProvingContext) { drop(unsafe { Box::from_raw(ctx) }); } + +#[no_mangle] +pub extern "system" fn librustzcash_zip32_xsk_master( + seed: *const c_uchar, + seedlen: size_t, + xsk_master: *mut [c_uchar; 169], +) { + let seed = unsafe { std::slice::from_raw_parts(seed, seedlen) }; + + let xsk = zip32::ExtendedSpendingKey::master(seed); + + xsk.write(&mut (unsafe { &mut *xsk_master })[..]) + .expect("should be able to serialize an ExtendedSpendingKey"); +} + +#[no_mangle] +pub extern "system" fn librustzcash_zip32_xsk_derive( + xsk_parent: *const [c_uchar; 169], + i: uint32_t, + xsk_i: *mut [c_uchar; 169], +) { + let xsk_parent = zip32::ExtendedSpendingKey::read(&unsafe { *xsk_parent }[..]) + .expect("valid ExtendedSpendingKey"); + let i = zip32::ChildIndex::from_index(i); + + let xsk = xsk_parent.derive_child(i); + + xsk.write(&mut (unsafe { &mut *xsk_i })[..]) + .expect("should be able to serialize an ExtendedSpendingKey"); +} + +#[no_mangle] +pub extern "system" fn librustzcash_zip32_xfvk_derive( + xfvk_parent: *const [c_uchar; 169], + i: uint32_t, + xfvk_i: *mut [c_uchar; 169], +) -> bool { + let xfvk_parent = zip32::ExtendedFullViewingKey::read(&unsafe { *xfvk_parent }[..]) + .expect("valid ExtendedFullViewingKey"); + let i = zip32::ChildIndex::from_index(i); + + let xfvk = match xfvk_parent.derive_child(i) { + Ok(xfvk) => xfvk, + Err(_) => return false, + }; + + xfvk.write(&mut (unsafe { &mut *xfvk_i })[..]) + .expect("should be able to serialize an ExtendedFullViewingKey"); + + true +} + +#[no_mangle] +pub extern "system" fn librustzcash_zip32_xfvk_address( + xfvk: *const [c_uchar; 169], + j: *const [c_uchar; 11], + j_ret: *mut [c_uchar; 11], + addr_ret: *mut [c_uchar; 43], +) -> bool { + let xfvk = zip32::ExtendedFullViewingKey::read(&unsafe { *xfvk }[..]) + .expect("valid ExtendedFullViewingKey"); + let j = zip32::DiversifierIndex(unsafe { *j }); + + let addr = match xfvk.address(j) { + Ok(addr) => addr, + Err(_) => return false, + }; + + let j_ret = unsafe { &mut *j_ret }; + let addr_ret = unsafe { &mut *addr_ret }; + + j_ret.copy_from_slice(&(addr.0).0); + addr_ret + .get_mut(..11) + .unwrap() + .copy_from_slice(&addr.1.diversifier.0); + addr.1 + .pk_d + .write(addr_ret.get_mut(11..).unwrap()) + .expect("should be able to serialize a PaymentAddress"); + + true +} diff --git a/src/tests/signatures.rs b/src/tests/signatures.rs index ae4ba3a..23fc75b 100644 --- a/src/tests/signatures.rs +++ b/src/tests/signatures.rs @@ -1,6 +1,7 @@ use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr}; use sapling_crypto::{ - jubjub::{FixedGenerators, JubjubEngine}, redjubjub::{PrivateKey, PublicKey, Signature}, + jubjub::{FixedGenerators, JubjubEngine}, + redjubjub::{PrivateKey, PublicKey, Signature}, }; use super::JUBJUB;