Skip to content

Commit 35d52e1

Browse files
committed
update to do full encryption & hash plaintext inside zkVM
1 parent be9ff15 commit 35d52e1

File tree

2 files changed

+39
-41
lines changed

2 files changed

+39
-41
lines changed

host/src/main.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use hex_literal::hex;
55
// These constants represent the RISC-V ELF and the image ID generated by risc0-build.
66
// The ELF is used for proving and the ID is used for verification.
77
use methods::{GUEST_ENCRYPT_ELF, GUEST_ENCRYPT_ID};
8-
use risc0_zkvm::{default_prover, ExecutorEnv};
8+
use risc0_zkvm::{default_prover, sha::Digest, ExecutorEnv};
99

1010
fn main() {
1111
// Initialize tracing. In order to view logs, run `RUST_LOG=info cargo run`
@@ -22,19 +22,13 @@ fn main() {
2222
let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
2323
println!("Plaintext bytes: {:?}", plaintext);
2424

25-
// Key and IV must be references to the `GenericArray` type.
26-
// Here we use the `Into` trait to convert arrays into it.
27-
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
28-
// Generate raw keystream bytes
29-
let mut keystream = [0u8; 16]; // ChaCha20 generates keystream in 64-byte blocks, but this can be any number of bits.
30-
cipher.apply_keystream(&mut keystream); // keystream XOR with 0s = keystream
31-
println!("Keystream bytes: {:?}", keystream);
32-
3325
// zkVM
3426
let env = ExecutorEnv::builder()
35-
.write(&plaintext)
27+
.write(&key)
28+
.unwrap()
29+
.write(&nonce)
3630
.unwrap()
37-
.write(&keystream)
31+
.write(&plaintext)
3832
.unwrap()
3933
.build()
4034
.unwrap();
@@ -49,23 +43,26 @@ fn main() {
4943
// extract the receipt.
5044
let receipt = prove_info.receipt;
5145

52-
let mut output: [u8; 16] = receipt.journal.decode().unwrap();
53-
println!("zkVM output bytes: {:?}", output);
46+
let mut output: (Digest, [u8; 16]) = receipt.journal.decode().unwrap();
47+
println!("zkVM -> plaintext hash: {:?}", output.0);
48+
println!("zkVM -> ciphertext bytes: {:?}", output.1);
5449

5550
let ciphertext = hex!("e405626e 4f1236b3 670ee428 332ea20e");
5651
println!("expected output bytes: {:?}", ciphertext);
5752

5853
// The receipt was verified at the end of proving, but the below code is an
5954
// example of how someone else could verify this receipt.
60-
receipt
61-
.verify(GUEST_ENCRYPT_ID)
62-
.unwrap();
55+
receipt.verify(GUEST_ENCRYPT_ID).unwrap();
6356
println!("Reciept from zkVM OK!");
64-
57+
58+
// Key and IV must be references to the `GenericArray` type.
59+
// Here we use the `Into` trait to convert arrays into it.
60+
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
61+
6562
// ChaCha ciphers support seeking
6663
cipher.seek(0u32);
6764

6865
// decrypt ciphertext by applying keystream again
69-
cipher.apply_keystream(&mut output);
70-
assert_eq!(output, plaintext);
66+
cipher.apply_keystream(&mut output.1);
67+
assert_eq!(output.1, plaintext);
7168
}

methods/guest/src/main.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
1-
use risc0_zkvm::guest::env;
1+
use risc0_zkvm::{
2+
guest::env,
3+
sha::{Impl, Sha256},
4+
}
5+
;use chacha20::ChaCha20;
6+
use chacha20::cipher::{KeyIvInit, StreamCipher};
27

38
fn main() {
4-
let plaintext: [u8; 16] = env::read();
5-
let keystream: [u8; 16] = env::read();
9+
let key: [u8; 32] = env::read();
10+
let nonce: [u8; 12] = env::read();
11+
// Expects to be filled with plaintext to be encrypted
12+
let mut buffer: [u8; 16] = env::read();
13+
14+
// Hash plaintext & commit
15+
let digest = Impl::hash_bytes(&buffer);
16+
env::commit(&digest);
617

718
// TODO:
8-
// - Hash plaintext & commit?
9-
// - Hash keystream & commit?
10-
11-
let mut buffer = plaintext.clone();
12-
xor_arrays(&plaintext,&keystream, &mut buffer);
13-
14-
// write public output to the journal
15-
env::commit(&buffer);
16-
}
19+
// - Hash key and/or nonce & commit?
20+
21+
// Key and IV must be references to the `GenericArray` type.
22+
// Here we use the `Into` trait to convert arrays into it.
23+
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
1724

18-
/// UNSAFE: We demand input and output arrays here are the SAME length.
19-
fn xor_arrays(arr1: &[u8], arr2: &[u8], output: &mut [u8]) {
20-
// assert_eq!(arr1.len(), arr2.len(), "Arrays must have the same length");
21-
// assert_eq!(arr1.len(), output.len(), "Output array must have the same length");
25+
// Write ciphertext into buffer by applying keystream to plaintext
26+
cipher.apply_keystream(&mut buffer);
2227

23-
for i in 0..arr1.len() {
24-
// We assume that input arrays are the same length, skipping checks to save cycles
25-
unsafe {
26-
*output.get_unchecked_mut(i) = arr1.get_unchecked(i) ^ arr2.get_unchecked(i);
27-
}
28-
}
28+
// write public output to the journal
29+
env::commit(&buffer);
2930
}

0 commit comments

Comments
 (0)