zk-email/circuits
Installation
yarn add @zk-email/circuits
EmailVerifier Circuit
EmailVerifier
is the primary circuit exported from @zk-email/circuits
which is used for proving the signature of the input email is valid.
Usage:
Import to your circuit file like below.
include "@zk-email/circuits/email-verifier.circom";
-
Parameters:
maxHeadersLength
: Maximum length for the email header.maxBodyLength
: Maximum length for the email body.n
: Number of bits per chunk the RSA key is split into. Recommended to be 121.k
: Number of chunks the RSA key is split into. Recommended to be 17.ignoreBodyHashCheck
: Set 1 to skip body hash check in case data to prove/extract is only in the headers.enableHeaderMasking
: Set to 1 to enable masking of the email header.enableBodyMasking
: Set to 1 to enable masking of the email body.removeSoftLineBreaks
: Set to 1 to remove soft line breaks from the email body (=\r\n
).
Note
: We use these values for n and k because their product (n * k) needs to be more than 2048 (RSA constraint) and n has to be less than half of 255 to fit in a circom signal. -
Input Signals:
emailHeader[maxHeadersLength]
: Email headers that are signed (ones inDKIM-Signature
header) as ASCII int[], padded as per SHA-256 block size.emailHeaderLength
: Length of the email header including the SHA-256 padding.pubkey[k]
: RSA public key split into k chunks of n bits each.signature[k]
: RSA signature split into k chunks of n bits each.emailBody[maxBodyLength]
: Email body after the precomputed SHA as ASCII int[], padded as per SHA-256 block size.emailBodyLength
: Length of the email body including the SHA-256 padding.bodyHashIndex
: Index of the body hashbh
in theemailHeader
.precomputedSHA[32]
: Precomputed SHA-256 hash of the email body till the bodyHashIndex.
If
removeSoftLineBreaks
is enabled:decodedEmailBodyIn[maxBodyLength]
: The email body with soft line breaks removed, provided as input for validation.
If
enableHeaderMasking
is enabled:headerMask[maxHeadersLength]
: A mask array for the email header, where each element is1
(reveal) or0
(hide).
If
enableBodyMasking
is enabled:bodyMask[maxBodyLength]
: A mask array for the email body, where each element is1
(reveal) or0
(hide).
-
Output Signals:
pubkeyHash
: Poseidon hash of the pubkey - Poseidon(n/2)(n/2 chunks of pubkey with k*2 bits per chunk).
If
removeSoftLineBreaks
is enabled:decodedEmailBodyOut[maxBodyLength]
: The decoded email body with soft line breaks removed.
If
enableHeaderMasking
is enabled:maskedHeader[maxHeadersLength]
: The masked email header after applying theheaderMask
.
If
enableBodyMasking
is enabled:maskedBody[maxBodyLength]
: The masked email body after applying thebodyMask
.
Libraries
This section contains a template library located in the @zk-email/circuits/lib
directory. These templates are important for building your main circuit (EmailVerifier).
These templates are used in the EmailVerifier
circuit, and can also be used in a wide range of ZK projects, even those not directly related to ZK Email.
lib/rsa.circom
RSAVerifier65537: Verifies RSA signatures with exponent 65537.
- Source
- Parameters
n
: Number of bits per chunk the modulus is split into. Recommended to be 121.k
: Number of chunks the modulus is split into. Recommended to be 17.
- Inputs:
message[k]
: The message that was signed.signature[k]
: The signature to verify.modulus[k]
: The modulus of the RSA key (pubkey).
lib/sha.circom
Sha256Bytes: Computes the SHA256 hash of input bytes.
- Source
- Parameters
maxByteLength
: Maximum length of the input bytes.
- Inputs:
paddedIn[maxByteLength]
: Message to hash padded as per the SHA256 specification.paddedInLength
: Length of the message in bytes including padding.
- Output:
out[256]
: The 256-bit hash of the input message.
Sha256BytesPartial: Computes the SHA256 hash of input bytes with a precomputed state.
- Source
- Parameters
maxByteLength
: Maximum length of the input bytes.
- Inputs:
paddedIn[maxByteLength]
: Message to hash padded as per the SHA256 specification.paddedInLength
: Length of the message in bytes including padding.preHash[32]
: The precomputed state of the hash.
- Output:
out[256]
: The 256-bit hash of the input message.
lib/base64.circom
Base64Decode: Decodes a base64 encoded string into binary data.
- Source
- Inputs:
in
: The base64 encoded string to decode.N
: The expected length of the output binary data.
- Outputs:
out
: The decoded binary data.
Utils
This section provides an overview of utility circom templates available in the @zk-email/circuits/utils
directory. These templates assist in the construction of zk circuits for various applications beyond the core ZK Email functionalities.
utils/array.circom
AssertZeroPadding: Asserts that the input array is zero-padded from the given startIndex
.
- Source
- Parameters:
maxArrayLen
: The maximum number of elements in the input array.
- Inputs:
in
: The input array.startIndex
: The index from which the array should be zero-padded.
ItemAtIndex: Selects an item at a given index from the input array.
- Source
- Parameters:
maxArrayLen
: The number of elements in the array.
- Inputs:
in
: The input array.index
: The index of the element to select.
- Output:
out
: The selected element.
CalculateTotal: Calculates the sum of an array.
- Source
- Parameters:
n
: The number of elements in the array.
- Inputs:
nums
: The input array.
- Output:
sum
: The sum of the input array.
SelectSubArray: Selects a subarray from an array given a startIndex
and length
.
- Source
- Parameters:
maxArrayLen
: The maximum number of bytes in the input array.maxSubArrayLen
: The maximum number of integers in the output array.
- Inputs:
in
: The input byte array.startIndex
: The start index of the subarray.length
: The length of the subarray.
- Output:
out
: Array ofmaxSubArrayLen
size, items starting fromstartIndex
, and items afterlength
set to zero.
VarShiftLeft: Shifts input array by shift
indices to the left.
- Source
- Parameters:
maxArrayLen
: The maximum length of the input array.maxOutArrayLen
: The maximum length of the output array.
- Inputs:
in
: The input array.shift
: The number of indices to shift the array to the left.
- Output:
out
: Shifted subarray.
utils/bytes.circom
PackBytes: Packs an array of bytes to numbers that fit in the field.
- Source
- Inputs:
in
: The input byte array.maxBytes
: The maximum number of bytes in the input array.
- Outputs:
out
: The output integer array after packing.
PackByteSubArray: Selects a sub-array from the input array and packs it to numbers that fit in the field.
- Source
- Inputs:
in
: The input byte array.startIndex
: The start index of the sub-array.length
: The length of the sub-array.maxArrayLen
: The maximum number of elements in the input array.maxSubArrayLen
: The maximum number of elements in the sub-array.
- Outputs:
out
: The output integer array after packing the sub-array.
DigitBytesToInt: Converts a byte array representing digits to an integer.
- Source
- Inputs:
in
: The input byte array - big-endian digit string ofout
.n
: The number of bytes in the input array.
- Outputs:
out
: The output integer after conversion.
ByteMask: Applies a mask to a byte array to selectively reveal or hide bytes.
- Parameters:
maxArrayLen
: The maximum length of the input array.
- Inputs:
in[maxArrayLen]
: The input byte array.mask[maxArrayLen]
: The mask array, where each element is1
(reveal) or0
(hide).
- Output:
out[maxArrayLen]
: The masked byte array after applying the mask.
utils/constants.circom
Constants: Defines a set of constants used across various circom circuits for standardizing sizes and lengths of different data types.
- Source
- Constants:
EMAIL_ADDR_MAX_BYTES()
: Returns the maximum byte size for an email, defined as 256.DOMAIN_MAX_BYTES()
: Returns the maximum byte size for a domain, defined as 255.MAX_BYTES_IN_FIELD()
: Returns the maximum number of bytes that can fit in a field, defined as 31.
utils/functions.circom
log2Ceil: Calculates the ceiling of the base 2 logarithm of a given number.
- Source
- Inputs:
a
: The input number for which the base 2 logarithm ceiling is to be calculated.
- Outputs:
- Returns the smallest integer greater than or equal to the base 2 logarithm of the input number.
utils/hash.circom
PoseidonLarge: Circuit to calculate Poseidon hash of inputs more than 16.
- Source
- Inputs:
in[chunkSize]
: The input array of chunkSize elements.bytesPerChunk
: Number of bits in each chunk.chunkSize
: Number of chunks in input.
- Outputs:
out
: Poseidon hash of input where consecutive elements are merged.
utils/regex.circom
SelectRegexReveal: Selects the reveal part of a byte array that matches a regular expression.
- Source
- Inputs:
in
: The input byte array.startIndex
: The index of the start of the reveal part in the input array.maxArrayLen
: The maximum length of the input array.maxRevealLen
: The maximum length of the reveal part.
- Outputs:
out
: The revealed data array that matches the regular expression.
PackRegexReveal: Packs the reveal data from a regex match into an integer array.
- Source
- Inputs:
in
: The input byte array.startIndex
: The index of the start of the reveal part in the input array.maxArrayLen
: The maximum length of the input array.maxRevealLen
: The maximum length of the reveal part.
- Outputs:
out
: The packed integer array after processing the reveal data.
Helpers
This section contains helper circom templates in @zk-email/circuits/helpers
that you can use to build on top of ZK Email.
helpers/email-nullifier.circom
EmailNullifier: Calculates the email nullifier using Poseidon hash.
- Source
- Parameters:
bitPerChunk
: The number of bits per chunk the signature is split into.chunkSize
: The number of chunks the signature is split into.
- Inputs:
signature[chunkSize]
: The signature of the email.
- Output:
out
: The email nullifier.
helpers/remove-soft-line-breaks.circom
RemoveSoftLineBreaks: Removes soft line breaks from the email body.
- Parameters:
maxBodyLength
: The maximum length of the email body.
- Inputs:
encoded[maxBodyLength]
: The email body with potential soft line breaks.
- Outputs:
decoded[maxBodyLength]
: The email body with soft line breaks removed.isValid
: A signal indicating whether the decoding was successful (1
for valid,0
for invalid).
Additional Notes
- Constraint Counts: The inclusion of new functionalities like masking and soft line break removal may increase the number of constraints in the circuit. Be mindful of these when designing proofs and verifying performance.
- Padding Requirements: The circuit includes assertions to ensure that
maxHeadersLength
andmaxBodyLength
are multiples of 64, which aligns with SHA-256 padding requirements. - Security Considerations: When using masking and data processing features, ensure that they are applied correctly to maintain data integrity and privacy. Misuse could lead to unintended data exposure or verification failures.