Skip to content

Commit 7750a4b

Browse files
authored
fix: align overview.md encrypted deposit snippets with ZoneInbox.sol spec (#358)
The overview document had three discrepancies with the Solidity reference implementation in ZoneInbox.sol: 1. DecryptionData struct, IChaumPedersenVerify interface, and both verifyProof call snippets were missing the sharedSecretYParity parameter added in the Solidity spec. 2. Both HKDF-SHA256 calls showed an empty info parameter ("") instead of the correct domain-separating info binding: abi.encodePacked(tempoPortal, ed.keyIndex, ed.encrypted.ephemeralPubkeyX) The info binding is security-relevant -- it ties the derived AES key to a specific portal, encryption key index, and ephemeral public key. Made-with: Cursor
1 parent 2714d4d commit 7750a4b

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

docs/pages/protocol/privacy/overview.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,8 @@ The zone can verify encrypted deposit decryption on-chain without the sequencer
12341234

12351235
```solidity
12361236
struct DecryptionData {
1237-
bytes32 sharedSecret; // ECDH shared secret (sequencerPriv * ephemeralPub)
1237+
bytes32 sharedSecret; // ECDH shared secret (x-coordinate of privSeq * ephemeralPub)
1238+
uint8 sharedSecretYParity; // Y coordinate parity of the shared secret point (0x02 or 0x03)
12381239
address to; // Decrypted recipient
12391240
bytes32 memo; // Decrypted memo
12401241
ChaumPedersenProof cpProof; // Proof of correct shared secret derivation
@@ -1268,6 +1269,7 @@ bool proofValid = IChaumPedersenVerify(CHAUM_PEDERSEN_VERIFY).verifyProof(
12681269
ed.encrypted.ephemeralPubX,
12691270
ed.encrypted.ephemeralPubYParity,
12701271
dec.sharedSecret,
1272+
dec.sharedSecretYParity,
12711273
seqPubX, // looked up on-chain, not from dec
12721274
seqPubYParity, // looked up on-chain, not from dec
12731275
dec.cpProof
@@ -1276,7 +1278,11 @@ if (!proofValid) revert InvalidSharedSecretProof();
12761278
12771279
// Step 3: Derive AES key using HKDF-SHA256 (in Solidity)
12781280
// Note: Encryption key validity is already validated on Tempo side in ZonePortal.depositEncrypted()
1279-
bytes32 aesKey = _hkdfSha256(dec.sharedSecret, "ecies-aes-key", "");
1281+
bytes32 aesKey = _hkdfSha256(
1282+
dec.sharedSecret,
1283+
"ecies-aes-key",
1284+
abi.encodePacked(tempoPortal, ed.keyIndex, ed.encrypted.ephemeralPubkeyX)
1285+
);
12801286
12811287
// Step 4: Try to decrypt using AES-GCM precompile
12821288
(bytes memory plaintext, bool valid) = IAesGcmDecrypt(AES_GCM_DECRYPT).decrypt(...);
@@ -1314,6 +1320,7 @@ interface IChaumPedersenVerify {
13141320
bytes32 ephemeralPubX,
13151321
uint8 ephemeralPubYParity,
13161322
bytes32 sharedSecret,
1323+
uint8 sharedSecretYParity,
13171324
bytes32 sequencerPubX,
13181325
uint8 sequencerPubYParity,
13191326
ChaumPedersenProof calldata proof
@@ -1357,6 +1364,7 @@ bool proofValid = IChaumPedersenVerify(CHAUM_PEDERSEN_VERIFY).verifyProof(
13571364
ed.encrypted.ephemeralPubX,
13581365
ed.encrypted.ephemeralPubYParity,
13591366
dec.sharedSecret,
1367+
dec.sharedSecretYParity,
13601368
seqPubX, // looked up on-chain, not from dec
13611369
seqPubYParity, // looked up on-chain, not from dec
13621370
dec.cpProof
@@ -1366,8 +1374,8 @@ if (!proofValid) revert InvalidSharedSecretProof();
13661374
// Step 3: Derive AES key from shared secret using HKDF-SHA256 (in Solidity)
13671375
bytes32 aesKey = _hkdfSha256(
13681376
dec.sharedSecret,
1369-
"ecies-aes-key", // salt
1370-
"" // info (empty)
1377+
"ecies-aes-key",
1378+
abi.encodePacked(tempoPortal, ed.keyIndex, ed.encrypted.ephemeralPubkeyX)
13711379
);
13721380
13731381
// Step 4: Decrypt using AES-256-GCM precompile

0 commit comments

Comments
 (0)