Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Jul 15, 2024
1 parent e69efd2 commit 8a8e3b6
Show file tree
Hide file tree
Showing 17 changed files with 80 additions and 131 deletions.
4 changes: 2 additions & 2 deletions docs/docs/aztec/concepts/accounts/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ Typically, `Npk_m` is stored in a note and later on, the note is nullified using
Validity of `nsk_app` is verified by our [protocol kernel circuits](../../../protocol-specs/circuits/private-kernel-tail#verifying-and-splitting-ordered-data).

## Incoming viewing keys
The app-siloed version of public key (denoted `Ivpk_app`) is used to encrypt a note for a recipient and the corresponding secret key (`ivsk_app`) is used by recipient during decryption.
The public key (denoted `Ivpk`) is used to encrypt a note for a recipient and the corresponding secret key (`ivsk`) is used by the recipient during decryption.

## Outgoing viewing keys
App-siloed versions of outgoing viewing keys are denoted `ovsk_app` and `Ovpk_app`.
These keys are used to encrypt a note for a note sender which is necessary for reconstructing transaction history from on-chain data.
For example, during a token transfer, the token contract may dictate that the sender encrypts the note with value with the recipient's `Ivpk_app`, but also records the transfer with its own `Ovpk_app` for bookkeeping purposes.
For example, during a token transfer, the token contract may dictate that the sender encrypts the note with value with the recipient's `Ivpk`, but also records the transfer with its own `Ovpk_app` for bookkeeping purposes.
If these keys were not used and a new device would be synched there would be no "direct" information available about notes that a user created for other people.

## Tagging keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ $\ciphertextheader$ | $enc^{\Ivpkm}_{\hmencheader}$(app\_address) | Ciphertext h
|||||
$\esk$ | $\stackrel{rand}{\leftarrow} \mathbb{F}$ | ephemeral secret key |
$\Epkd$ | $\esk \cdot \Gd$ | (Diversified) Ephemeral public key |
$\sharedsecret_{app,enc}$ | $\esk \cdot \Ivpkappdstealth$ | Shared secret, for ciphertext encryption |
$\sharedsecret_{app,enc}$ | $\esk \cdot \Ivpkdstealth$ | Shared secret, for ciphertext encryption |
$\happenc$ | h("?", $\sharedsecret_{app,enc}$) | Incoming data encryption key |
$\ciphertext$ | $enc^{\Ivpkappdstealth}_{\happenc}(\plaintext)$ | Ciphertext |
$\ciphertext$ | $enc^{\Ivpkdstealth}_{\happenc}(\plaintext)$ | Ciphertext |
$\payload$ | [$\tagg_{m, i}^{Bob \rightarrow Alice}$, $\ciphertextheader$, $\ciphertext$, $\Epkdheader$, $\Epkd$] | Payload |

<!-- TODO: This requires app-specific incoming viewing keys, which we don't have. How do we adapt this derivation? -->
Expand All @@ -33,10 +33,10 @@ $\sharedsecret_{m,header}$ | $\ivskm \cdot \Epkdheader$ | Shared secret, for enc
$\hmencheader$ | h("?", $\sharedsecret_{m,header}$) | Incoming encryption key |
app_address | $decrypt_{\hmencheader}^{\ivskm}(\ciphertextheader)$ | App address |
||||
$\ivskappstealth$ | See derivations above. Use the decrypted app_address. | App-specific incoming viewing secret key |
$\sharedsecret_{app, enc}$ | $\ivskappstealth \cdot \Epkd$ | Shared secret, for ciphertext encryption |
$\ivskstealth$ | See derivations above. Use the decrypted app_address. | Incoming viewing secret key |
$\sharedsecret_{app, enc}$ | $\ivskstealth \cdot \Epkd$ | Shared secret, for ciphertext encryption |
$\happenc$ | h("?", $\sharedsecret_{app, enc}$) | Ciphertext encryption key |
$\plaintext$ | $decrypt_{\happenc}^{\ivskappstealth}(\ciphertext)$ | Plaintext |
$\plaintext$ | $decrypt_{\happenc}^{\ivskstealth}(\ciphertext)$ | Plaintext |

## Encrypt and tag an outgoing message

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/protocol-specs/addresses-and-keys/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ If an app developer thinks some of their users might wish to have the option to

> Note: this key can be optionally shared with a trusted 3rd party, and they would not be able to derive the user's secret keys.
> Note: knowledge of this key enables someone to identify when an emitted nullifier belongs to the user, and to identify which note hashes have been nullified.
> Note: knowledge of this key would not enable a 3rd party to view the contents of any notes; knowledge of the $\ivskapp$ / $\ovskapp$ would be needed for that.
> Note: knowledge of this key would not enable a 3rd party to view the contents of any notes; knowledge of the $\ivsk$ / $\ovskapp$ would be needed for that.
> Note: this is intentionally not named as a "public" key, since it must not be shared with the wider public.
$$
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/tutorials/contract_tutorials/token_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ Unconstrained functions are similar to `view` functions in Solidity in that they

#### `balance_of_private`

A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have `ivsk_app` ([incoming viewing secret key](../../aztec/concepts/accounts/keys.md##incoming-viewing-keys)) in order to decrypt the notes.
A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have `ivsk` ([incoming viewing secret key](../../aztec/concepts/accounts/keys.md##incoming-viewing-keys)) in order to decrypt the notes.

#include_code balance_of_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust

Expand Down
12 changes: 6 additions & 6 deletions docs/src/katex-macros.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ module.exports = {

"\\nskapp": "{\\color{red}{nsk_{app}}}",
"\\tskapp": "{\\color{red}{tsk_{app}}}",
"\\ivskapp": "{\\color{red}{ivsk_{app}}}",
"\\ivsk": "{\\color{red}{ivsk}}",
"\\ovskapp": "{\\color{red}{ovsk_{app}}}",

"\\Nkapp": "{\\color{orange}{Nk_{app}}}",

"\\Npkapp": "{\\color{green}{Npk_{app}}}",

"\\Ivpkapp": "{\\color{green}{Ivpk_{app}}}",
"\\Ivpk": "{\\color{green}{Ivpk_{app}}}",

"\\happL": "{\\color{green}{h_{app}^L}}",
"\\happn": "{\\color{green}{h_{app}^n}}",
Expand All @@ -34,13 +34,13 @@ module.exports = {
"\\d": "{\\color{green}{d}}",
"\\Gd": "{\\color{green}{G_d}}",

"\\Ivpkappd": "{\\color{violet}{Ivpk_{app,d}}}",
"\\shareableIvpkappd": "{\\color{violet}{\\widetilde{Ivpk_{app,d}}}}",
"\\Ivpkd": "{\\color{violet}{Ivpk_{app,d}}}",
"\\shareableIvpkd": "{\\color{violet}{\\widetilde{Ivpk_{app,d}}}}",
"\\Ivpkmd": "{\\color{violet}{Ivpk_{m,d}}}",
"\\shareableIvpkmd": "{\\color{violet}{\\widetilde{Ivpk_{m,d}}}}",

"\\ivskappstealth": "{\\color{red}{ivsk_{app,stealth}}}",
"\\Ivpkappdstealth": "{\\color{violet}{Ivpk_{app,d,stealth}}}",
"\\ivskstealth": "{\\color{red}{ivsk_{stealth}}}",
"\\Ivpkdstealth": "{\\color{violet}{Ivpk_{app,d,stealth}}}",
"\\Pkappdstealth": "{\\color{violet}{Pk_{app,d,stealth}}}",
"\\ivskmstealth": "{\\color{red}{ivsk_{m,stealth}}}",
"\\Ivpkmdstealth": "{\\color{violet}{Ivpk_{m,d,stealth}}}",
Expand Down
12 changes: 6 additions & 6 deletions noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ impl<M> EncryptedLogIncomingBody<M> {
EncryptedLogIncomingBody { plaintext }
}

pub fn compute_ciphertext(self, eph_sk: Scalar, ivpk_app: Point) -> [u8] {
let full_key = point_to_symmetric_key(eph_sk, ivpk_app);
pub fn compute_ciphertext(self, eph_sk: Scalar, ivpk: Point) -> [u8] {
let full_key = point_to_symmetric_key(eph_sk, ivpk);
let mut sym_key = [0; 16];
let mut iv = [0; 16];

Expand Down Expand Up @@ -122,15 +122,15 @@ mod test {
lo: 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd,
hi: 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06
};
let ivpk_app = Point {
let ivpk = Point {
x: 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,
y: 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e,
is_infinite: false
};

let body = EncryptedLogIncomingBody::from_note(note, storage_slot);

let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);
let ciphertext = body.compute_ciphertext(eph_sk, ivpk);

let expected_note_body_ciphertext = [
228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 48, 153, 169, 1, 25, 182, 93, 39, 39, 207, 251, 218, 234, 147, 156, 13, 110, 180, 190, 199, 41, 6, 211, 203, 176, 110, 165, 186, 110, 127, 199, 22, 201, 149, 92, 249, 219, 68, 145, 68, 179, 29, 233, 34, 98, 123, 197, 234, 169, 53, 44, 14, 81, 60, 92, 27, 250, 134, 49, 248, 57, 119, 236, 118, 158, 104, 82, 243, 98, 164, 60, 72, 74, 27, 177, 194, 221, 225, 193, 150, 67, 235, 205, 106, 150, 24, 126, 186, 220, 178, 199, 189, 113, 54, 181, 55, 46, 15, 236, 236, 9, 159, 5, 172, 237, 154, 110, 50, 241, 64, 92, 13, 37, 53, 20, 140, 42, 146, 229, 63, 97, 25, 159, 63, 235, 104, 68, 100
Expand Down Expand Up @@ -222,7 +222,7 @@ mod test {
hi: 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06
};

let ivpk_app = Point {
let ivpk = Point {
x: 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,
y: 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e,
is_infinite: false
Expand All @@ -232,7 +232,7 @@ mod test {

let body = EncryptedLogIncomingBody::from_event(test_event, randomness);

let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);
let ciphertext = body.compute_ciphertext(eph_sk, ivpk);

let expected_event_body_ciphertext = [
228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 66, 122, 29, 35, 42, 33, 153, 216, 199, 208, 103, 207, 126, 153, 189, 136, 19, 220, 238, 15, 169, 29, 255, 11, 123, 107, 70, 192, 53, 40, 36, 93, 187, 32, 123, 136, 104, 23, 229, 245, 152, 90, 84, 2, 136, 112, 42, 27, 82, 214, 104, 14, 250, 48, 199, 245, 88, 22, 200, 77, 38, 51, 127, 56, 138, 255, 16, 46, 179, 129, 215, 185, 185, 116, 148, 16, 133, 62, 56, 180, 10, 132, 109, 77, 206, 199, 21, 167, 7, 163, 171, 158, 244, 23, 18, 121, 108, 42, 107, 7, 48, 84, 212, 104, 39, 16, 109, 7, 108, 129, 60, 80, 112, 241, 223, 140, 186, 158, 38, 74, 230, 213, 159, 175, 142, 228, 128, 160
Expand Down
22 changes: 11 additions & 11 deletions noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use crate::keys::point_to_symmetric_key::point_to_symmetric_key;
struct EncryptedLogOutgoingBody {
eph_sk: Scalar,
recipient: AztecAddress,
recipient_ivpk_app: Point,
recipient_ivpk: Point,
}

impl EncryptedLogOutgoingBody {
pub fn new(eph_sk: Scalar, recipient: AztecAddress, recipient_ivpk_app: Point) -> Self {
Self { eph_sk, recipient, recipient_ivpk_app }
pub fn new(eph_sk: Scalar, recipient: AztecAddress, recipient_ivpk: Point) -> Self {
Self { eph_sk, recipient, recipient_ivpk }
}

pub fn compute_ciphertext(self, ovsk_app: Scalar, eph_pk: Point) -> [u8; 176] {
Expand All @@ -27,16 +27,16 @@ impl EncryptedLogOutgoingBody {
let serialized_eph_sk_low = self.eph_sk.lo.to_be_bytes(32);

let address_bytes = self.recipient.to_field().to_be_bytes(32);
let serialized_recipient_ivpk_app = self.recipient_ivpk_app.serialize();
let serialized_recipient_ivpk_app_x = serialized_recipient_ivpk_app[0].to_be_bytes(32);
let serialized_recipient_ivpk_app_y = serialized_recipient_ivpk_app[1].to_be_bytes(32);
let serialized_recipient_ivpk = self.recipient_ivpk.serialize();
let serialized_recipient_ivpk_x = serialized_recipient_ivpk[0].to_be_bytes(32);
let serialized_recipient_ivpk_y = serialized_recipient_ivpk[1].to_be_bytes(32);

for i in 0..32 {
buffer[i] = serialized_eph_sk_high[i];
buffer[i + 32] = serialized_eph_sk_low[i];
buffer[i + 64] = address_bytes[i];
buffer[i + 96] = serialized_recipient_ivpk_app_x[i];
buffer[i + 128] = serialized_recipient_ivpk_app_y[i];
buffer[i + 96] = serialized_recipient_ivpk_x[i];
buffer[i + 128] = serialized_recipient_ivpk_y[i];
}

// We compute the symmetric key using poseidon.
Expand Down Expand Up @@ -74,7 +74,7 @@ mod test {
lo: 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe,
hi: 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb
};
let recipient_ivsk_app = Scalar {
let recipient_ivsk = Scalar {
lo: 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022,
hi: 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31
};
Expand All @@ -84,11 +84,11 @@ mod test {
};

let eph_pk = derive_public_key(eph_sk);
let recipient_ivpk_app = derive_public_key(recipient_ivsk_app);
let recipient_ivpk = derive_public_key(recipient_ivsk);

let recipient = AztecAddress::from_field(0xdeadbeef);

let body = EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app);
let body = EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk);

let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk);

Expand Down
32 changes: 4 additions & 28 deletions noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,12 @@ pub fn compute_encrypted_event_log<Event, NB, MB, OB>(
let eph_sk: Scalar = fr_to_fq(unsafe_rand());
let eph_pk = derive_public_key(eph_sk);

let ivpk_app = compute_ivpk_app(ivpk, contract_address);

let header = EncryptedLogHeader::new(contract_address);

let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);
let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);
let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app);
let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_fq(ovsk_app), eph_pk);
let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk);
let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk).compute_ciphertext(fr_to_fq(ovsk_app), eph_pk);

let mut encrypted_bytes: [u8; OB] = [0; OB];
// @todo We ignore the tags for now
Expand Down Expand Up @@ -83,14 +81,12 @@ pub fn compute_encrypted_note_log<Note, N, NB, M>(
let eph_sk: Scalar = fr_to_fq(unsafe_rand());
let eph_pk = derive_public_key(eph_sk);

let ivpk_app = compute_ivpk_app(ivpk, contract_address);

let header = EncryptedLogHeader::new(contract_address);

let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);
let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);
let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk_app);
let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_fq(ovsk_app), eph_pk);
let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk);
let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk).compute_ciphertext(fr_to_fq(ovsk_app), eph_pk);

let mut encrypted_bytes: [u8; M] = [0; M];
// @todo We ignore the tags for now
Expand Down Expand Up @@ -143,23 +139,3 @@ fn fr_to_fq(r: Field) -> Scalar {

Scalar { lo, hi }
}

fn compute_ivpk_app(ivpk: Point, contract_address: AztecAddress) -> Point {
// It is useless to compute this, it brings no value to derive fully.
// Issue(#6955)
ivpk
/*
// @todo Just setting infinite to false, but it should be checked.
// for example user could define ivpk = infinity using the registry
assert((ivpk.x != 0) & (ivpk.y != 0), "ivpk is infinite");
let i = fr_to_fq(poseidon2_hash([contract_address.to_field(), ivpk.x, ivpk.y, GENERATOR_INDEX__IVSK_M]));
let I = derive_public_key(i);
let embed_I = Point { x: I.x, y: I.y, is_infinite: false };
let embed_ivpk = Point { x: ivpk.x, y: ivpk.y, is_infinite: false };
let embed_result = embedded_curve_add(embed_I, embed_ivpk);
Point { x: embed_result.x, embed_result.y)*/
}
Original file line number Diff line number Diff line change
Expand Up @@ -427,11 +427,11 @@ contract Test {
fn compute_outgoing_log_body_ciphertext(
eph_sk: Scalar,
recipient: AztecAddress,
recipient_ivpk_app: Point,
recipient_ivpk: Point,
ovsk_app: Scalar
) -> [u8; 176] {
let eph_pk = derive_public_key(eph_sk);
EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app).compute_ciphertext(ovsk_app, eph_pk)
EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk).compute_ciphertext(ovsk_app, eph_pk)
}

#[aztec(public)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,20 @@ export class EncryptedEventLogIncomingBody extends EncryptedLogIncomingBody {
* Decrypts a log body
*
* @param ciphertext - The ciphertext buffer
* @param ivskAppOrEphSk - The private key matching the public key used in encryption (the viewing key secret or)
* @param ephPkOrIvpkApp - The public key generated with the ephemeral secret key used in encryption
* @param ivskOrEphSk - The private key matching the public key used in encryption (the viewing key secret or)
* @param ephPkOrIvpk - The public key generated with the ephemeral secret key used in encryption
*
* The "odd" input stems from ivskApp * ephPk == ivpkApp * ephSk producing the same value.
* The "odd" input stems from ivsk * ephPk == ivpk * ephSk producing the same value.
* This is used to allow for the same decryption function to be used by both the sender and the recipient.
*
* @returns The decrypted log body
*/
public static fromCiphertext(
ciphertext: Buffer | bigint[],
ivskAppOrEphSk: GrumpkinScalar,
ephPkOrIvpkApp: PublicKey,
ivskOrEphSk: GrumpkinScalar,
ephPkOrIvpk: PublicKey,
): EncryptedEventLogIncomingBody {
const buffer = super.fromCiphertextToBuffer(ciphertext, ivskAppOrEphSk, ephPkOrIvpkApp);
const buffer = super.fromCiphertextToBuffer(ciphertext, ivskOrEphSk, ephPkOrIvpk);
return EncryptedEventLogIncomingBody.fromBuffer(buffer);
}
}
Loading

0 comments on commit 8a8e3b6

Please sign in to comment.