Skip to content

Commit

Permalink
feat: AES oracle padding (#6013)
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan authored Apr 25, 2024
1 parent dafb3ed commit 4b563cd
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 13 deletions.
6 changes: 4 additions & 2 deletions noir-projects/aztec-nr/aztec/src/oracle/encryption.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@

#[oracle(aes128Encrypt)]
pub fn aes128_encrypt_oracle<N>(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; N] {}
pub fn aes128_encrypt_oracle<N, M>(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; M] {}

unconstrained pub fn aes128_encrypt<N>(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; N] {
// AES 128 CBC with PKCS7 is padding to multiples of 16 bytes so M has to be a multiple of 16!
// (e.g. from 65 bytes long input you get 80 bytes long output and M has to be set to `80`)
unconstrained pub fn aes128_encrypt<N, M>(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; M] {
aes128_encrypt_oracle(input, iv, key)
}
10 changes: 7 additions & 3 deletions noir-projects/noir-contracts/contracts/test_contract/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,13 @@ contract Test {
}

#[aztec(private)]
fn encrypt(input: [u8; 64], iv: [u8; 16], key: [u8; 16]) {
let result = aes128_encrypt(input, iv, key);
context.emit_unencrypted_log(result);
fn encrypt(input: [u8; 64], iv: [u8; 16], key: [u8; 16]) -> [u8; 64] {
aes128_encrypt(input, iv, key)
}

#[aztec(private)]
fn encrypt_with_padding(input: [u8; 65], iv: [u8; 16], key: [u8; 16]) -> [u8; 80] {
aes128_encrypt(input, iv, key)
}

#[aztec(public)]
Expand Down
30 changes: 22 additions & 8 deletions yarn-project/end-to-end/src/e2e_encryption.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,35 @@ describe('e2e_encryption', () => {

afterAll(() => teardown());

it('encrypts', async () => {
it('encrypts πŸ”’πŸ“„πŸ”‘πŸ’»', async () => {
const input = randomBytes(64);
const iv = randomBytes(16);
const key = randomBytes(16);

const expectedCiphertext = aes128.encryptBufferCBC(input, iv, key);

const logs = await contract.methods
const ciphertextAsBigInts = await contract.methods
.encrypt(Array.from(input), Array.from(iv), Array.from(key))
.send()
.getUnencryptedLogs();
// Each byte of encrypted data is in its own field and it's all serialized into a long buffer so we simply extract
// each 32nd byte from the buffer to get the encrypted data
const recoveredCiphertext = logs.logs[0].log.data.filter((_, i) => (i + 1) % 32 === 0);
.simulate();
const ciphertext = Buffer.from(ciphertextAsBigInts.map((x: bigint) => Number(x)));

expect(recoveredCiphertext).toEqual(expectedCiphertext);
expect(ciphertext).toEqual(expectedCiphertext);
});

it('encrypts with padding πŸ”’πŸ“„πŸ”‘πŸ’» βž• πŸ“¦', async () => {
const input = randomBytes(65);
const iv = randomBytes(16);
const key = randomBytes(16);

const expectedCiphertext = aes128.encryptBufferCBC(input, iv, key);
// AES 128 CBC with PKCS7 is padding to multiples of 16 bytes so from 65 bytes long input we get 80 bytes long output
expect(expectedCiphertext.length).toBe(80);

const ciphertextAsBigInts = await contract.methods
.encrypt_with_padding(Array.from(input), Array.from(iv), Array.from(key))
.simulate();
const ciphertext = Buffer.from(ciphertextAsBigInts.map((x: bigint) => Number(x)));

expect(ciphertext).toEqual(expectedCiphertext);
});
});

0 comments on commit 4b563cd

Please sign in to comment.