mirror of
https://github.com/logos-blockchain/lssa-zkvm-testing.git
synced 2026-01-02 13:23:08 +00:00
encryption example with risc0
This commit is contained in:
parent
29b56e3a32
commit
579bf0a624
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"encryption-demo",
|
||||
"encryption-demo-methods",
|
||||
]
|
||||
workspace.resolver = "2"
|
||||
15
encryption-demo-methods/Cargo.toml
Normal file
15
encryption-demo-methods/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "encryption-demo-methods"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
build = "0.0.2"
|
||||
risc0-zkvm = { version = "2.2", default-features = false }
|
||||
risc0-build = { version = "2.2", default-features = false }
|
||||
|
||||
[package.metadata.risc0]
|
||||
methods = ["guest/chacha20", "guest/xchacha20"]
|
||||
|
||||
4
encryption-demo-methods/build.rs
Normal file
4
encryption-demo-methods/build.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
risc0_build::embed_methods();
|
||||
}
|
||||
|
||||
19
encryption-demo-methods/guest/chacha20/Cargo.toml
Normal file
19
encryption-demo-methods/guest/chacha20/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "chacha20"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
# Ensure staticlib for RISC-V
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
# no_std stream cipher
|
||||
chacha20 = { version = "0.9", default-features = false }
|
||||
cipher = { version = "0.5", default-features = false }
|
||||
|
||||
risc0-zkvm-guest = "2.2"
|
||||
|
||||
[features]
|
||||
default = ["alloc"] # pull in alloc inside guest
|
||||
alloc = []
|
||||
|
||||
27
encryption-demo-methods/guest/chacha20/src/main.rs
Normal file
27
encryption-demo-methods/guest/chacha20/src/main.rs
Normal file
@ -0,0 +1,27 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use chacha20::cipher::{KeyIvInit, StreamCipher};
|
||||
use chacha20::ChaCha20;
|
||||
use risc0_zkvm::guest::env;
|
||||
risc0_zkvm_guest::entry!(main);
|
||||
|
||||
pub fn main() {
|
||||
// Read 32-byte key
|
||||
let key: [u8; 32] = env::read();
|
||||
// Read 12-byte nonce
|
||||
let nonce: [u8; 12] = env::read();
|
||||
// Read plaintext length
|
||||
let len: u32 = env::read();
|
||||
// Read plaintext bytes
|
||||
let mut plaintext = vec![0u8; len as usize];
|
||||
env::read_slice(&mut plaintext).unwrap();
|
||||
|
||||
// Encrypt in-place
|
||||
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
|
||||
cipher.apply_keystream(&mut plaintext);
|
||||
|
||||
// Commit ciphertext
|
||||
env::commit_slice(&plaintext);
|
||||
}
|
||||
|
||||
19
encryption-demo-methods/guest/xchacha20/Cargo.toml
Normal file
19
encryption-demo-methods/guest/xchacha20/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "xchacha20"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
# Ensure staticlib for RISC-V
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
# no_std stream cipher
|
||||
xchacha20 = { version = "0.9", default-features = false }
|
||||
cipher = { version = "0.5", default-features = false }
|
||||
|
||||
risc0-zkvm-guest = "2.2"
|
||||
|
||||
[features]
|
||||
default = ["alloc"] # pull in alloc inside guest
|
||||
alloc = []
|
||||
|
||||
21
encryption-demo-methods/guest/xchacha20/src/main.rs
Normal file
21
encryption-demo-methods/guest/xchacha20/src/main.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use chacha20::cipher::{KeyIvInit, StreamCipher};
|
||||
use chacha20::XChaCha20;
|
||||
use risc0_zkvm::guest::env;
|
||||
risc0_zkvm_guest::entry!(main);
|
||||
|
||||
pub fn main() {
|
||||
let key: [u8; 32] = env::read();
|
||||
let nonce: [u8; 24] = env::read();
|
||||
let len: u32 = env::read();
|
||||
let mut plaintext = vec![0u8; len as usize];
|
||||
env::read_slice(&mut plaintext).unwrap();
|
||||
|
||||
let mut cipher = XChaCha20::new(&key.into(), &nonce.into());
|
||||
cipher.apply_keystream(&mut plaintext);
|
||||
|
||||
env::commit_slice(&plaintext);
|
||||
}
|
||||
|
||||
2
encryption-demo-methods/src/lib.rs
Normal file
2
encryption-demo-methods/src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
||||
include!(concat!(env!("OUT_DIR"), "/methods.rs"));
|
||||
|
||||
16
encryption-demo/Cargo.toml
Normal file
16
encryption-demo/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "encryption-demo"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
risc0-zkvm = "2.2"
|
||||
rand = { version = "0.8", features = ["std"]}
|
||||
hex = "0.4"
|
||||
|
||||
encryption-demo-methods = { path = "../encryption-demo-methods" }
|
||||
|
||||
[[bin]]
|
||||
name = "encrypt-demo"
|
||||
path = "src/main.rs"
|
||||
14
encryption-demo/encryption-demo/src/main.rs
Normal file
14
encryption-demo/encryption-demo/src/main.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use encryption_demo::*;
|
||||
use rand::Rng;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let msg = b"zk-encrypted hello world!";
|
||||
let mut rng = rand::thread_rng();
|
||||
let key: [u8; 32] = rng.gen();
|
||||
let nonce: [u8; 12] = rng.gen();
|
||||
|
||||
let (ciphertext, _proof) = encrypt_chacha20(&key, &nonce, msg)?;
|
||||
println!("ciphertext = {}", hex::encode(ciphertext));
|
||||
println!("proof OK");
|
||||
Ok(())
|
||||
}
|
||||
114
encryption-demo/src/lib.rs
Normal file
114
encryption-demo/src/lib.rs
Normal file
@ -0,0 +1,114 @@
|
||||
//! Host-side helpers: prove encryption inside RISC Zero and verify receipts.
|
||||
|
||||
use risc0_zkvm::{
|
||||
default_prover, ExecutorEnv, Receipt,
|
||||
};
|
||||
use encryption_demo_methods::{
|
||||
CHACHA20_ELF, CHACHA20_ID, XCHACHA20_ELF, XCHACHA20_ID,
|
||||
};
|
||||
|
||||
/// Encrypt `plaintext` with ChaCha20 inside the zkVM.
|
||||
/// Returns `(ciphertext, receipt)`.
|
||||
pub fn encrypt_chacha20(
|
||||
key: &[u8; 32],
|
||||
nonce: &[u8; 12],
|
||||
plaintext: &[u8],
|
||||
) -> anyhow::Result<(Vec<u8>, Receipt)> {
|
||||
let env = ExecutorEnv::builder()
|
||||
.write(key)?
|
||||
.write(nonce)?
|
||||
.write(&(plaintext.len() as u32))?
|
||||
.write_slice(plaintext)?
|
||||
.build()?;
|
||||
|
||||
let prover = default_prover();
|
||||
let receipt = prover.prove(env, CHACHA20_ELF)?;
|
||||
receipt.verify(CHACHA20_ID)?;
|
||||
|
||||
let ciphertext: Vec<u8> = receipt.journal.decode()?;
|
||||
Ok((ciphertext, receipt))
|
||||
}
|
||||
|
||||
/// Same API for XChaCha20 (24-byte nonce)
|
||||
pub fn encrypt_xchacha20(
|
||||
key: &[u8; 32],
|
||||
nonce: &[u8; 24],
|
||||
plaintext: &[u8],
|
||||
) -> anyhow::Result<(Vec<u8>, Receipt)> {
|
||||
let env = ExecutorEnv::builder()
|
||||
.write(key)?
|
||||
.write(nonce)?
|
||||
.write(&(plaintext.len() as u32))?
|
||||
.write_slice(plaintext)?
|
||||
.build()?;
|
||||
|
||||
let prover = default_prover();
|
||||
let receipt = prover.prove(env, XCHACHA20_ELF)?;
|
||||
receipt.verify(XCHACHA20_ID)?;
|
||||
|
||||
let ciphertext: Vec<u8> = receipt.journal.decode()?;
|
||||
Ok((ciphertext, receipt))
|
||||
}
|
||||
|
||||
|
||||
// Test for chacha20
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use chacha20::cipher::{KeyIvInit, StreamCipher};
|
||||
use chacha20::ChaCha20;
|
||||
|
||||
// RFC 8439 test vector
|
||||
const KEY: [u8; 32] = [
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
];
|
||||
const NONCE: [u8; 12] = [0; 12];
|
||||
const PLAINTEXT: [u8; 16] = *b"example message!";
|
||||
|
||||
#[test]
|
||||
fn chacha20_vector_matches() {
|
||||
let (ciphertext, _) = encrypt_chacha20(&KEY, &NONCE, &PLAINTEXT).unwrap();
|
||||
|
||||
// host decryption
|
||||
let mut buf = ciphertext.clone();
|
||||
let mut cipher = ChaCha20::new(&KEY.into(), &NONCE.into());
|
||||
cipher.apply_keystream(&mut buf);
|
||||
|
||||
assert_eq!(&buf, &PLAINTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tests for Xchacha20
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use xchacha20::cipher::{KeyIvInit, StreamCipher};
|
||||
use xchacha20::xChaCha20;
|
||||
|
||||
// RFC 8439 test vector
|
||||
const KEY: [u8; 32] = [
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
];
|
||||
const NONCE: [u8; 12] = [0; 12];
|
||||
const PLAINTEXT: [u8; 16] = *b"example message!";
|
||||
|
||||
#[test]
|
||||
fn xchacha20_vector_matches() {
|
||||
let (ciphertext, _) = encrypt_xchacha20(&KEY, &NONCE, &PLAINTEXT).unwrap();
|
||||
|
||||
// host decryption
|
||||
let mut buf = ciphertext.clone();
|
||||
let mut cipher = xChaCha20::new(&KEY.into(), &NONCE.into());
|
||||
cipher.apply_keystream(&mut buf);
|
||||
|
||||
assert_eq!(&buf, &PLAINTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
1
encryption-demo/src/main.rs
Normal file
1
encryption-demo/src/main.rs
Normal file
@ -0,0 +1 @@
|
||||
|
||||
BIN
risc0-selective-privacy-poc/.DS_Store
vendored
Normal file
BIN
risc0-selective-privacy-poc/.DS_Store
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user