diff --git a/noir-projects/aztec-nr/aztec/src/oracle.nr b/noir-projects/aztec-nr/aztec/src/oracle.nr index 57415dc9575..753ef6e930a 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle.nr @@ -4,6 +4,7 @@ mod arguments; mod call_private_function; +mod encryption; mod get_contract_instance; mod get_l1_to_l2_membership_witness; mod get_nullifier_membership_witness; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/encryption.nr b/noir-projects/aztec-nr/aztec/src/oracle/encryption.nr new file mode 100644 index 00000000000..cb655c756ce --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/oracle/encryption.nr @@ -0,0 +1,7 @@ + +#[oracle(aes128Encrypt)] +pub fn aes128_encrypt_oracle(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; N] {} + +unconstrained pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; N] { + aes128_encrypt_oracle(input, iv, key) +} diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index f7a40cf41a8..107df25dc72 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -25,7 +25,7 @@ contract Test { note_getter_options::NoteStatus }, deploy::deploy_contract as aztec_deploy_contract, - oracle::{get_public_key::get_public_key as get_public_key_oracle, unsafe_rand::unsafe_rand} + oracle::{encryption::aes128_encrypt, get_public_key::get_public_key as get_public_key_oracle, unsafe_rand::unsafe_rand} }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; use dep::value_note::value_note::ValueNote; @@ -309,6 +309,12 @@ contract Test { assert(context.version() == version, "Invalid version"); } + #[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); + } + #[aztec(public)] fn assert_public_global_vars( chain_id: Field, diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 9b91327c5f9..f112db7d65a 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -4,7 +4,6 @@ import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; -import { to2Fields } from '@aztec/foundation/serialize'; import { type ACVMField } from '../acvm_types.js'; import { frToBoolean, frToNumber, fromACVMField } from '../deserialize.js'; @@ -380,21 +379,16 @@ export class Oracle { return toAcvmEnqueuePublicFunctionResult(enqueuedRequest); } - encrypt([symmetricKey]: ACVMField[], [initializationVector]: ACVMField[], plaintext: ACVMField[]): ACVMField[] { - // Symmetric key and initialization vector (IV) are 16 bytes and we store them as big endian in Fr - const processedSK = fromACVMField(symmetricKey).toBuffer().subarray(0, 16); - const processedIV = fromACVMField(initializationVector).toBuffer().subarray(0, 16); - // TODO(benesjan): we could save some info here by not including the 2 empty bits at the end of each serialized - // field --> this could be valuable as the ciphertext will go on-chain - const processedPlaintext = Buffer.concat(plaintext.map(fromACVMField).map(f => f.toBuffer())); - const ciphertext = this.typedOracle.encrypt(processedSK, processedIV, processedPlaintext); - // Chunk the ciphertext buffer to 32 bytes and on each chunk call to2Fields function - const ciphertextFields: Fr[] = []; - for (let i = 0; i < ciphertext.length; i += Fr.SIZE_IN_BYTES) { - const chunk = ciphertext.subarray(i, i + Fr.SIZE_IN_BYTES); - ciphertextFields.push(...to2Fields(chunk)); - } + aes128Encrypt(input: ACVMField[], initializationVector: ACVMField[], key: ACVMField[]): ACVMField[] { + // Convert each field to a number and then to a buffer (1 byte is stored in 1 field) + const processedInput = Buffer.from(input.map(fromACVMField).map(f => f.toNumber())); + const processedIV = Buffer.from(initializationVector.map(fromACVMField).map(f => f.toNumber())); + const processedKey = Buffer.from(key.map(fromACVMField).map(f => f.toNumber())); + + // Encrypt the input + const ciphertext = this.typedOracle.aes128Encrypt(processedInput, processedIV, processedKey); - return ciphertextFields.map(toACVMField); + // Convert each byte of ciphertext to a field and return it + return Array.from(ciphertext).map(byte => toACVMField(byte)); } } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 3a0ebe415e3..0771458a972 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -234,7 +234,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('enqueuePublicFunctionCall'); } - encrypt(_symmetricKey: Buffer, _initializationVector: Buffer, _plaintext: Buffer): Buffer { + aes128Encrypt(_input: Buffer, _initializationVector: Buffer, _key: Buffer): Buffer { throw new OracleMethodNotAvailableError('encrypt'); } } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 618cca083ce..0bcb1f07dbb 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -523,8 +523,8 @@ export class ClientExecutionContext extends ViewDataOracle { return values; } - public override encrypt(symmetricKey: Buffer, initializationVector: Buffer, plaintext: Buffer): Buffer { + public override aes128Encrypt(input: Buffer, initializationVector: Buffer, key: Buffer): Buffer { const aes128 = new Aes128(); - return aes128.encryptBufferCBC(plaintext, initializationVector, symmetricKey); + return aes128.encryptBufferCBC(input, initializationVector, key); } }