mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-02 13:23:10 +00:00
implement encryption/decryption of private outputs
This commit is contained in:
parent
d00c551027
commit
96ca181f2d
@ -53,7 +53,7 @@ version = "0.8.5"
|
||||
|
||||
[workspace.dependencies.k256]
|
||||
features = ["ecdsa-core", "arithmetic", "expose-field", "serde", "pem"]
|
||||
version = "0.13.4"
|
||||
version = "0.13.3"
|
||||
|
||||
[workspace.dependencies.elliptic-curve]
|
||||
features = ["arithmetic"]
|
||||
|
||||
@ -4,10 +4,12 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
risc0-zkvm = "2.3.1"
|
||||
risc0-zkvm = { version = "2.3.1"}
|
||||
serde = { version = "1.0", default-features = false }
|
||||
thiserror = { version = "2.0.12", optional = true }
|
||||
bytemuck = { version = "1.13", optional = true }
|
||||
chacha20 = { version = "0.9", default-features = false }
|
||||
k256 = "0.13.3"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
use chacha20::{
|
||||
ChaCha20,
|
||||
cipher::{KeyIvInit, StreamCipher},
|
||||
};
|
||||
use risc0_zkvm::{
|
||||
serde::to_vec,
|
||||
sha::{Impl, Sha256},
|
||||
@ -16,11 +20,19 @@ use crate::{
|
||||
};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use std::io::Cursor;
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
pub mod account;
|
||||
pub mod program;
|
||||
|
||||
use k256::{
|
||||
AffinePoint, EncodedPoint, FieldBytes, ProjectivePoint, PublicKey, Scalar,
|
||||
elliptic_curve::{
|
||||
PrimeField,
|
||||
sec1::{FromEncodedPoint, ToEncodedPoint},
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub mod error;
|
||||
|
||||
@ -55,49 +67,167 @@ pub fn verify_membership_proof(
|
||||
&result == digest
|
||||
}
|
||||
|
||||
pub type IncomingViewingPublicKey = [u8; 32];
|
||||
pub type EphemeralPublicKey = Secp256k1Point;
|
||||
pub type IncomingViewingPublicKey = Secp256k1Point;
|
||||
|
||||
pub type EphemeralSecretKey = [u8; 32];
|
||||
pub struct EphemeralPublicKey;
|
||||
|
||||
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
|
||||
fn from(value: &EphemeralSecretKey) -> Self {
|
||||
todo!()
|
||||
Secp256k1Point::from_scalar(*value)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tag(u8);
|
||||
impl Tag {
|
||||
pub fn new(Npk: &NullifierPublicKey, Ipk: &IncomingViewingPublicKey) -> Self {
|
||||
todo!()
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))]
|
||||
pub struct Secp256k1Point(pub Vec<u8>);
|
||||
impl Secp256k1Point {
|
||||
pub fn from_scalar(value: [u8; 32]) -> Secp256k1Point {
|
||||
let x_bytes: FieldBytes = value.into();
|
||||
let x = Scalar::from_repr(x_bytes).unwrap();
|
||||
|
||||
let p = ProjectivePoint::GENERATOR * x;
|
||||
let q = AffinePoint::from(p);
|
||||
let enc = q.to_encoded_point(true);
|
||||
|
||||
Self(enc.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, PartialEq, Eq))]
|
||||
pub struct EncryptedAccountData(u8);
|
||||
pub struct EncryptedAccountData {
|
||||
ciphertext: Vec<u8>,
|
||||
epk: EphemeralPublicKey,
|
||||
view_tag: u8,
|
||||
}
|
||||
|
||||
impl EncryptedAccountData {
|
||||
#[cfg(feature = "host")]
|
||||
pub fn decrypt(self, isk: &[u8; 32], output_index: u32) -> Option<Account> {
|
||||
let ss_bytes = Self::ecdh(isk, &self.epk.0.clone().try_into().unwrap());
|
||||
let ipk = IncomingViewingPublicKey::from_scalar(*isk);
|
||||
|
||||
let key = Self::kdf(
|
||||
ss_bytes,
|
||||
&self.epk,
|
||||
&ipk,
|
||||
// &commitment.to_byte_array(),
|
||||
output_index,
|
||||
);
|
||||
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
||||
let mut buffer = self.ciphertext;
|
||||
|
||||
cipher.apply_keystream(&mut buffer);
|
||||
let mut cursor = Cursor::new(buffer.as_slice());
|
||||
Account::from_cursor(&mut cursor).ok()
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
account: &Account,
|
||||
// commitment: &Commitment,
|
||||
esk: &EphemeralSecretKey,
|
||||
Npk: &NullifierPublicKey,
|
||||
Ivk: &IncomingViewingPublicKey,
|
||||
npk: &NullifierPublicKey,
|
||||
ipk: &IncomingViewingPublicKey,
|
||||
output_index: u32,
|
||||
) -> Self {
|
||||
// TODO: implement
|
||||
Self(0)
|
||||
let mut buffer = account.to_bytes().to_vec();
|
||||
|
||||
let ss_bytes = Self::ecdh(esk, &ipk.0.clone().try_into().unwrap());
|
||||
let epk = EphemeralPublicKey::from(esk);
|
||||
|
||||
let key = Self::kdf(
|
||||
ss_bytes,
|
||||
&epk,
|
||||
ipk,
|
||||
// &commitment.to_byte_array(),
|
||||
output_index,
|
||||
);
|
||||
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
||||
cipher.apply_keystream(&mut buffer);
|
||||
|
||||
let view_tag = Self::view_tag(&npk, &ipk);
|
||||
Self {
|
||||
ciphertext: buffer,
|
||||
epk,
|
||||
view_tag,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kdf(
|
||||
ss_bytes: [u8; 32],
|
||||
epk: &EphemeralPublicKey,
|
||||
ipk: &IncomingViewingPublicKey,
|
||||
// commitment: &[u8; 32],
|
||||
output_index: u32,
|
||||
) -> [u8; 32] {
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
bytes.extend_from_slice(b"NSSA/v0.1/KDF-SHA256");
|
||||
bytes.extend_from_slice(&ss_bytes);
|
||||
bytes.extend_from_slice(&epk.0[..]);
|
||||
bytes.extend_from_slice(&ipk.0[..]);
|
||||
// bytes.extend_from_slice(&commitment[..]);
|
||||
bytes.extend_from_slice(&output_index.to_le_bytes());
|
||||
|
||||
Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()
|
||||
}
|
||||
|
||||
pub fn ecdh(scalar: &[u8; 32], point: &[u8; 33]) -> [u8; 32] {
|
||||
let scalar = Scalar::from_repr((*scalar).into()).unwrap();
|
||||
|
||||
let encoded = EncodedPoint::from_bytes(point).unwrap();
|
||||
let pubkey_affine = AffinePoint::from_encoded_point(&encoded).unwrap();
|
||||
|
||||
let shared = ProjectivePoint::from(pubkey_affine) * scalar;
|
||||
let shared_affine = shared.to_affine();
|
||||
|
||||
let encoded = shared_affine.to_encoded_point(false);
|
||||
let x_bytes_slice = encoded.x().unwrap();
|
||||
let mut x_bytes = [0u8; 32];
|
||||
x_bytes.copy_from_slice(x_bytes_slice);
|
||||
|
||||
x_bytes
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||
let dummy_value = EncryptedAccountData(0);
|
||||
Ok(dummy_value)
|
||||
let mut u32_bytes = [0; 4];
|
||||
|
||||
cursor.read_exact(&mut u32_bytes)?;
|
||||
let ciphertext_lenght = u32::from_le_bytes(u32_bytes);
|
||||
let mut ciphertext = vec![0; ciphertext_lenght as usize];
|
||||
cursor.read_exact(&mut ciphertext)?;
|
||||
|
||||
let mut epk_bytes = vec![0; 33];
|
||||
cursor.read_exact(&mut epk_bytes)?;
|
||||
|
||||
let mut tag_bytes = [0; 1];
|
||||
cursor.read_exact(&mut tag_bytes)?;
|
||||
|
||||
Ok(Self {
|
||||
ciphertext,
|
||||
epk: Secp256k1Point(epk_bytes),
|
||||
view_tag: tag_bytes[0],
|
||||
})
|
||||
}
|
||||
|
||||
fn view_tag(npk: &NullifierPublicKey, ipk: &&IncomingViewingPublicKey) -> u8 {
|
||||
// TODO: implement
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl EncryptedAccountData {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
// TODO: implement
|
||||
vec![0]
|
||||
let mut bytes = Vec::new();
|
||||
let ciphertext_length: u32 = self.ciphertext.len() as u32;
|
||||
bytes.extend_from_slice(&ciphertext_length.to_le_bytes());
|
||||
bytes.extend_from_slice(&self.ciphertext);
|
||||
bytes.extend_from_slice(&self.epk.0);
|
||||
bytes.push(self.view_tag);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,10 +266,12 @@ impl PrivacyPreservingCircuitOutput {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use risc0_zkvm::serde::from_slice;
|
||||
|
||||
use crate::{
|
||||
EncryptedAccountData, PrivacyPreservingCircuitOutput,
|
||||
EncryptedAccountData, EphemeralPublicKey, PrivacyPreservingCircuitOutput, Secp256k1Point,
|
||||
account::{Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey},
|
||||
};
|
||||
|
||||
@ -172,7 +304,11 @@ mod tests {
|
||||
data: b"post state data".to_vec(),
|
||||
nonce: 18446744073709551615,
|
||||
}],
|
||||
encrypted_private_post_states: vec![EncryptedAccountData(0)],
|
||||
encrypted_private_post_states: vec![EncryptedAccountData {
|
||||
ciphertext: vec![255, 255, 1, 1, 2, 2],
|
||||
epk: EphemeralPublicKey::from_scalar([123; 32]),
|
||||
view_tag: 1,
|
||||
}],
|
||||
new_commitments: vec![Commitment::new(
|
||||
&NullifierPublicKey::from(&[1; 32]),
|
||||
&Account::default(),
|
||||
@ -187,4 +323,17 @@ mod tests {
|
||||
let output_from_slice: PrivacyPreservingCircuitOutput = from_slice(&bytes).unwrap();
|
||||
assert_eq!(output, output_from_slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encrypted_account_data_to_bytes_roundtrip() {
|
||||
let data = EncryptedAccountData {
|
||||
ciphertext: vec![255, 255, 1, 1, 2, 2],
|
||||
epk: EphemeralPublicKey::from_scalar([123; 32]),
|
||||
view_tag: 95,
|
||||
};
|
||||
let bytes = data.to_bytes();
|
||||
let mut cursor = Cursor::new(bytes.as_slice());
|
||||
let data_from_cursor = EncryptedAccountData::from_cursor(&mut cursor).unwrap();
|
||||
assert_eq!(data, data_from_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,3 +8,4 @@ risc0-build = { version = "2.3.1" }
|
||||
|
||||
[package.metadata.risc0]
|
||||
methods = ["guest"]
|
||||
|
||||
|
||||
206
nssa/program_methods/guest/Cargo.lock
generated
206
nssa/program_methods/guest/Cargo.lock
generated
@ -297,12 +297,24 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
@ -484,6 +496,27 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chacha20"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.3.0"
|
||||
@ -535,6 +568,18 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
@ -580,6 +625,16 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
@ -709,6 +764,20 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
||||
dependencies = [
|
||||
"der",
|
||||
"digest",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "educe"
|
||||
version = "0.6.0"
|
||||
@ -733,6 +802,25 @@ version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.13.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"digest",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group",
|
||||
"pkcs8",
|
||||
"rand_core 0.6.4",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.4.0"
|
||||
@ -796,6 +884,16 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -908,6 +1006,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -943,6 +1042,17 @@ version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
@ -994,6 +1104,15 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.3.1"
|
||||
@ -1223,6 +1342,15 @@ dependencies = [
|
||||
"hashbrown 0.15.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.9"
|
||||
@ -1275,6 +1403,20 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"once_cell",
|
||||
"sha2",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak"
|
||||
version = "0.1.5"
|
||||
@ -1445,6 +1587,8 @@ checksum = "a5b0c77c1b780822bc749a33e39aeb2c07584ab93332303babeabb645298a76e"
|
||||
name = "nssa-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chacha20",
|
||||
"k256",
|
||||
"risc0-zkvm",
|
||||
"serde",
|
||||
]
|
||||
@ -1531,6 +1675,16 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.3"
|
||||
@ -1749,6 +1903,9 @@ name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
@ -1841,6 +1998,16 @@ dependencies = [
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
@ -2162,6 +2329,20 @@ dependencies = [
|
||||
"yaml-rust2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.26"
|
||||
@ -2241,6 +2422,16 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
@ -2279,6 +2470,16 @@ version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stability"
|
||||
version = "0.2.1"
|
||||
@ -3193,3 +3394,8 @@ dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[patch.unused]]
|
||||
name = "k256"
|
||||
version = "0.13.3"
|
||||
source = "git+https://github.com/risc0/RustCrypto-elliptic-curves?tag=k256%2Fv0.13.3-risczero.1#ff5d67b095cfcc2569b7789f2079ed87ef2c7756"
|
||||
|
||||
@ -8,3 +8,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
risc0-zkvm = { version = "2.3.1", default-features = false, features = ['std'] }
|
||||
nssa-core = { path = "../../core" }
|
||||
|
||||
[patch.crates-io]
|
||||
k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.3-risczero.1" }
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey},
|
||||
program::{validate_execution, ProgramOutput, DEFAULT_PROGRAM_ID},
|
||||
verify_membership_proof, EncryptedAccountData, EphemeralPublicKey, EphemeralSecretKey,
|
||||
IncomingViewingPublicKey, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput, Tag,
|
||||
IncomingViewingPublicKey, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@ -50,12 +50,18 @@ fn main() {
|
||||
let mut private_keys_iter = private_account_keys.iter();
|
||||
let mut private_auth_iter = private_account_auth.iter();
|
||||
|
||||
let mut output_index = 0;
|
||||
for i in 0..n_accounts {
|
||||
match visibility_mask[i] {
|
||||
0 => {
|
||||
let mut post = post_states[i].clone();
|
||||
if post.program_owner == DEFAULT_PROGRAM_ID {
|
||||
// Claim account
|
||||
post.program_owner = program_id;
|
||||
}
|
||||
// Public account
|
||||
public_pre_states.push(pre_states[i].clone());
|
||||
public_post_states.push(post_states[i].clone());
|
||||
public_post_states.push(post);
|
||||
}
|
||||
1 | 2 => {
|
||||
let new_nonce = private_nonces_iter.next().expect("Missing private nonce");
|
||||
@ -111,12 +117,20 @@ fn main() {
|
||||
|
||||
// Compute commitment
|
||||
let commitment_post = Commitment::new(Npk, &post_with_updated_values);
|
||||
new_commitments.push(commitment_post);
|
||||
|
||||
// Encrypt and push post state
|
||||
let encrypted_account =
|
||||
EncryptedAccountData::new(&post_with_updated_values, esk, Npk, Ipk);
|
||||
let encrypted_account = EncryptedAccountData::new(
|
||||
&post_with_updated_values,
|
||||
// &commitment_post,
|
||||
esk,
|
||||
Npk,
|
||||
Ipk,
|
||||
output_index,
|
||||
);
|
||||
|
||||
new_commitments.push(commitment_post);
|
||||
encrypted_private_post_states.push(encrypted_account);
|
||||
output_index += 1;
|
||||
}
|
||||
_ => panic!("Invalid visibility mask value"),
|
||||
}
|
||||
|
||||
@ -117,6 +117,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn prove_privacy_preserving_execution_circuit_public_and_private_pre_accounts() {
|
||||
let program = Program::authenticated_transfer_program();
|
||||
let sender = AccountWithMetadata {
|
||||
account: Account {
|
||||
balance: 100,
|
||||
@ -133,17 +134,26 @@ mod tests {
|
||||
let balance_to_move: u128 = 37;
|
||||
|
||||
let expected_sender_post = Account {
|
||||
program_owner: program.id(),
|
||||
balance: 100 - balance_to_move,
|
||||
..Default::default()
|
||||
..Account::default()
|
||||
};
|
||||
|
||||
let expected_recipient_post = Account {
|
||||
program_owner: program.id(),
|
||||
balance: balance_to_move,
|
||||
nonce: 0xdeadbeef,
|
||||
data: vec![],
|
||||
};
|
||||
|
||||
let expected_sender_pre = sender.clone();
|
||||
let recipient_keys = test_private_account_keys_1();
|
||||
let (output, proof) = execute_and_prove(
|
||||
&[sender, recipient],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 2],
|
||||
&[0xdeadbeef],
|
||||
&[(NullifierPublicKey::from(&[1; 32]), [2; 32], [3; 32])],
|
||||
&[(recipient_keys.npk(), recipient_keys.ivk(), [3; 32])],
|
||||
&[],
|
||||
&Program::authenticated_transfer_program(),
|
||||
&[99; 32],
|
||||
@ -160,8 +170,12 @@ mod tests {
|
||||
assert_eq!(output.new_nullifiers.len(), 0);
|
||||
assert_eq!(output.commitment_set_digest, [99; 32]);
|
||||
assert_eq!(output.encrypted_private_post_states.len(), 1);
|
||||
// TODO: replace with real assertion when encryption is implemented
|
||||
assert_eq!(output.encrypted_private_post_states[0].to_bytes(), vec![0]);
|
||||
|
||||
let recipient_post = output.encrypted_private_post_states[0]
|
||||
.clone()
|
||||
.decrypt(&recipient_keys.isk, 0)
|
||||
.unwrap();
|
||||
assert_eq!(recipient_post, expected_recipient_post);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -210,8 +224,8 @@ mod tests {
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
(sender_keys.npk(), sender_keys.ivk, [3; 32]),
|
||||
(recipient_keys.npk(), recipient_keys.ivk, [5; 32]),
|
||||
(sender_keys.npk(), sender_keys.ivk(), [3; 32]),
|
||||
(recipient_keys.npk(), recipient_keys.ivk(), [5; 32]),
|
||||
],
|
||||
&[(
|
||||
sender_keys.nsk,
|
||||
@ -228,9 +242,18 @@ mod tests {
|
||||
assert_eq!(output.new_commitments, expected_new_commitments);
|
||||
assert_eq!(output.new_nullifiers, expected_new_nullifiers);
|
||||
assert_eq!(output.commitment_set_digest, commitment_set.digest());
|
||||
// TODO: replace with real assertion when encryption is implemented
|
||||
assert_eq!(output.encrypted_private_post_states.len(), 2);
|
||||
assert_eq!(output.encrypted_private_post_states[0].to_bytes(), vec![0]);
|
||||
assert_eq!(output.encrypted_private_post_states[1].to_bytes(), vec![0]);
|
||||
|
||||
let recipient_post_1 = output.encrypted_private_post_states[0]
|
||||
.clone()
|
||||
.decrypt(&sender_keys.isk, 0)
|
||||
.unwrap();
|
||||
assert_eq!(recipient_post_1, expected_private_account_1);
|
||||
|
||||
let recipient_post_2 = output.encrypted_private_post_states[1]
|
||||
.clone()
|
||||
.decrypt(&recipient_keys.isk, 1)
|
||||
.unwrap();
|
||||
assert_eq!(recipient_post_2, expected_private_account_2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -711,26 +711,30 @@ pub mod tests {
|
||||
|
||||
pub struct TestPrivateKeys {
|
||||
pub nsk: NullifierSecretKey,
|
||||
pub ivk: IncomingViewingPublicKey,
|
||||
pub isk: [u8; 32],
|
||||
}
|
||||
|
||||
impl TestPrivateKeys {
|
||||
pub fn npk(&self) -> NullifierPublicKey {
|
||||
NullifierPublicKey::from(&self.nsk)
|
||||
}
|
||||
|
||||
pub fn ivk(&self) -> IncomingViewingPublicKey {
|
||||
IncomingViewingPublicKey::from_scalar(self.isk)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_private_account_keys_1() -> TestPrivateKeys {
|
||||
TestPrivateKeys {
|
||||
nsk: [13; 32],
|
||||
ivk: [31; 32],
|
||||
isk: [31; 32],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_private_account_keys_2() -> TestPrivateKeys {
|
||||
TestPrivateKeys {
|
||||
nsk: [38; 32],
|
||||
ivk: [83; 32],
|
||||
isk: [83; 32],
|
||||
}
|
||||
}
|
||||
|
||||
@ -757,7 +761,7 @@ pub mod tests {
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 2],
|
||||
&[0xdeadbeef],
|
||||
&[(recipient_keys.npk(), recipient_keys.ivk, esk)],
|
||||
&[(recipient_keys.npk(), recipient_keys.ivk(), esk)],
|
||||
&[],
|
||||
&Program::authenticated_transfer_program(),
|
||||
&state.commitment_set_digest(),
|
||||
@ -802,8 +806,8 @@ pub mod tests {
|
||||
&[1, 2],
|
||||
&new_nonces,
|
||||
&[
|
||||
(sender_keys.npk(), sender_keys.ivk, [3; 32]),
|
||||
(recipient_keys.npk(), recipient_keys.ivk, [4; 32]),
|
||||
(sender_keys.npk(), sender_keys.ivk(), [3; 32]),
|
||||
(recipient_keys.npk(), recipient_keys.ivk(), [4; 32]),
|
||||
],
|
||||
&[(
|
||||
sender_keys.nsk,
|
||||
@ -856,7 +860,7 @@ pub mod tests {
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 0],
|
||||
&[new_nonce],
|
||||
&[(sender_keys.npk(), sender_keys.ivk, [3; 32])],
|
||||
&[(sender_keys.npk(), sender_keys.ivk(), [3; 32])],
|
||||
&[(
|
||||
sender_keys.nsk,
|
||||
state
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user