https://github.com/lambdaclass/aes_zero_knowledge_proof_circuit
https://github.com/lambdaclass/aes_zero_knowledge_proof_circuit
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/lambdaclass/aes_zero_knowledge_proof_circuit
- Owner: lambdaclass
- License: mit
- Created: 2022-12-01T15:59:15.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2023-03-30T21:00:55.000Z (about 3 years ago)
- Last Synced: 2025-04-04T13:54:21.659Z (about 1 year ago)
- Language: Rust
- Size: 189 KB
- Stars: 72
- Watchers: 6
- Forks: 4
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# AES Encryption circuit
ZK-Snark circuit to prove that a given ciphertext is the correct `AES-128` encryption using a certain secret key.
This first iteration uses ECB as the mode of operation and `Marlin` as the proving system for the circuit. In the future we will support CBC and GCM as alternative modes and `Plonk` as an alternative proving system.
## Circuit Inputs
### Private
- `message`: The message to encrypt.
- `secret_key`: The secret key used for the AES encryption.
### Public
- `ciphertext`: The encrypted message. This is public as the entire point of the circuit is for a verifier to be assured that the ciphertext they were given is the correct one.
## Usage
You can find an example usage under the `main.rs` module. Below is an explanation of it.
First, the proving and verifying keys must be generated. You can generate ones for testing by calling
```rust
let (proving_key, verifying_key) = synthesize_keys(message_length)?;
```
where `message_length` is the length of the message to be encrypted. Underneath, this is generating some universal SRS and then deriving the keys from it. In a real world scenario, the SRS should be generated in a secure manner through some setup using MPC.
With the proving key in hand, a prover calls
```rust
let message = [1_u8; 16];
let secret_key = [0_u8; 16];
let proof = encrypt(&message, &secret_key, &primitive_ciphertext, proving_key)?;
```
where `primitive_ciphertext` is a byte slice with the result of the `AES` encryption (under the example there's a helper function for it, but you can use any standard `AES` implementation).
The prover then hands the resulting proof along with the ciphertext to the verifier, who calls
```rust
let result = verify_encryption(
verifying_key,
&proof,
&primitive_ciphertext
)?;
assert!(result);
```
## AES Flow
`AES-128` consists of 11 rounds. The secret key is used to derive 11 round keys, one for each round.
Each AES round then takes a message as input and performs the following steps:
- `Add Round Key`
- `Sub Bytes`
- `Shift Rows`
- `Mix Columns`
## Building Blocks Required
Given the above, the building blocks required at the circuit level are the following:
| Building Blocks | Required Primitives |
| --------------- | ------------------- |
| AddRoundKey | `xor` |
| SubBytes | conditional select |
| ShiftRows | Row shifting |
| MixColumns | `addmany` |
| KeyDerivation | All of the above |
### Add RoundKey
This is just an xor of the input against the current round key.
### Sub Bytes
This is the so called [Rijndael S-Box](https://en.wikipedia.org/wiki/Rijndael_S-box), a lookup table that has a pretty complicated calculation involving [Rijndael's finite field](https://cryptohack.gitbook.io/cryptobook/symmetric-cryptography/aes/rijndael-finite-field).
Inside the circuit, we implement it by instantiating the precomputed table as 256 constants and then using a conditional select operation to do the lookup.
### Shift Rows
This step simply writes the input as a byte matrix and then rotates each row.
### Mix Columns
`Mix Columns` is essentially multiplying the input by a matrix, only the multiplication is once again performed in [Rijndael's finite field](https://cryptohack.gitbook.io/cryptobook/symmetric-cryptography/aes/rijndael-finite-field).
### Key Derivation
The key derivation is the most complex step, but it's ultimately just a combination of all the basic operations used in the four steps for every round.