Skip to content

Commit

Permalink
Started working on DSC circuit with new architure
Browse files Browse the repository at this point in the history
- cleanups
  • Loading branch information
0xturboblitz committed Jan 28, 2025
1 parent 1e42e60 commit 3acd769
Show file tree
Hide file tree
Showing 34 changed files with 284 additions and 546 deletions.
4 changes: 2 additions & 2 deletions app/src/screens/ProveScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Progress, Spinner, Text, XStack, YStack } from 'tamagui';

import {
DEVELOPMENT_MODE,
max_cert_bytes,
max_dsc_bytes,
} from '../../../common/src/constants/constants';
import {
DisclosureOptions,
Expand Down Expand Up @@ -193,7 +193,7 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
const cscaInputs = generateCircuitInputsDSC(
dscSecret as string,
passportData.dsc,
max_cert_bytes,
max_dsc_bytes,
selectedApp.devMode,
);
[dscProof, proof] = await Promise.all([
Expand Down
108 changes: 58 additions & 50 deletions circuits/circuits/dsc/dsc.circom
Original file line number Diff line number Diff line change
Expand Up @@ -9,70 +9,78 @@ include "@zk-kit/binary-merkle-root.circom/src/binary-merkle-root.circom";
include "../utils/passport/customHashers.circom";
include "../utils/passport/signatureAlgorithm.circom";
include "../utils/passport/signatureVerifier.circom";
include "../utils/crypto/utils/WordToBytes.circom";
include "../utils/passport/checkPubkeysEqual.circom";
// include "../utils/crypto/utils/WordToBytes.circom";
include "../utils/passport/constants.circom";
include "../utils/passport/dsc/StandardizePubKeyTo35Words.circom";
include "../utils/passport/dsc/ExtractPublicKey.circom";

///@input dsc_pubKey_bytes public key of the DSC in bytes padded to 525 bytes
///@input dsc_pubKey_offset offset of the DSC public key in the certificate
///@input dsc_pubkey_length_bytes length of the DSC public key in bytes. For ECDSA, it is x+y length
template DSC(signatureAlgorithm, n_csca, k_csca, max_cert_bytes, nLevels) {
var maxPubkeyBytesLength = getMaxDscPubKeyLength();

include "../utils/crypto/bitify/bytes.circom";
// include "../utils/crypto/bitify/splitWordsToBytes.circom";

template DSC(
signatureAlgorithm,
n_csca,
k_csca
) {
var MAX_CSCA_LENGTH = getMaxCSCALength();
var MAX_DSC_LENGTH = getMaxDSCLength();
var MAX_CSCA_PUBKEY_LENGTH = getMaxCSCAPubKeyLength();
var nLevels = getMaxCSCALevels();

// variables verification
assert(max_cert_bytes % 64 == 0);
// assert(n_csca * k_csca > max_cert_bytes);
assert(MAX_CSCA_LENGTH % 64 == 0); // it's 1664 currently
assert(MAX_DSC_LENGTH % 64 == 0); // it's 1664 currently
// assert(n_csca * k_csca > max_dsc_bytes); // not sure what this is for
assert(n_csca <= (255 \ 2));

var hashLength = getHashLength(signatureAlgorithm);
var kLengthFactor = getKLengthFactor(signatureAlgorithm);
var kScaled = k_csca * kLengthFactor;

signal input raw_dsc_cert[max_cert_bytes];
signal input raw_dsc_cert_padded_bytes;
var csca_pubkey_length_bytes = (getKeyLength(signatureAlgorithm) / 8) * kLengthFactor;

signal input raw_csca[MAX_CSCA_LENGTH];
signal input raw_csca_actual_length;
signal input csca_pubKey_offset;

signal input raw_dsc[MAX_DSC_LENGTH];
signal input raw_dsc_actual_length;

signal input csca_pubKey[kScaled];
signal input signature[kScaled];
signal input dsc_pubKey_bytes[maxPubkeyBytesLength];
signal input dsc_pubKey_offset;
signal input dsc_pubkey_length_bytes;
signal input merkle_root;
signal input path[nLevels];
signal input siblings[nLevels];
signal input salt;

// signal input merkle_root;
// signal input path[nLevels];
// signal input siblings[nLevels];

log("raw_csca_actual_length", raw_csca_actual_length);
log("csca_pubKey_offset", csca_pubKey_offset);
log("csca_pubkey_length_bytes", csca_pubkey_length_bytes);

log("raw_dsc_actual_length", raw_dsc_actual_length);

// check offsets refer to valid ranges
signal dscPubkeyOffsetInRange <== LessEqThan(14)([dsc_pubKey_offset + dsc_pubkey_length_bytes, raw_dsc_cert_padded_bytes]);
dscPubkeyOffsetInRange === 1;
signal csca_pubKey_offset_in_range <== LessEqThan(14)([ // TODO update this value with log2(MAX_CSCA_LENGTH)
csca_pubKey_offset + csca_pubkey_length_bytes,
raw_csca_actual_length
]);
csca_pubKey_offset_in_range === 1;

// leaf
signal leaf <== CustomHasher(kScaled)(csca_pubKey);
// compute leaf in the CSCA Merkle tree and verify inclusion
signal csca_tree_leaf <== PackBytesAndPoseidon(MAX_CSCA_LENGTH)(raw_csca);
// signal computed_merkle_root <== BinaryMerkleRoot(nLevels)(csca_tree_leaf, nLevels, path, siblings);
// merkle_root === computed_merkle_root;

signal computed_merkle_root <== BinaryMerkleRoot(nLevels)(leaf, nLevels, path, siblings);
merkle_root === computed_merkle_root;

// verify certificate signature
signal hashedCertificate[hashLength] <== ShaBytesDynamic(hashLength, max_cert_bytes)(raw_dsc_cert, raw_dsc_cert_padded_bytes);
// get CSCA public key from the certificate
signal extracted_csca_pubKey[MAX_CSCA_PUBKEY_LENGTH] <== SelectSubArray(MAX_CSCA_LENGTH, MAX_CSCA_PUBKEY_LENGTH)(raw_csca, csca_pubKey_offset, csca_pubkey_length_bytes);

// check if the CSCA public key is the same as the one in the certificate
// If we end up adding the pubkey in the CSCA leaf, we'll be able to remove this check
CheckPubkeysEqual(n_csca, kScaled, csca_pubkey_length_bytes, MAX_CSCA_PUBKEY_LENGTH)(csca_pubKey, extracted_csca_pubKey);

// verify DSC signature
signal hashedCertificate[hashLength] <== ShaBytesDynamic(hashLength, MAX_DSC_LENGTH)(raw_dsc, raw_dsc_actual_length);
SignatureVerifier(signatureAlgorithm, n_csca, k_csca)(hashedCertificate, csca_pubKey, signature);

//Extract certificate public key from certificate
component extractPubKey = ExtractPublicKey(max_cert_bytes, maxPubkeyBytesLength);
extractPubKey.raw_dsc_cert <== raw_dsc_cert;
extractPubKey.dsc_pubKey_offset <== dsc_pubKey_offset;
extractPubKey.dsc_pubkey_length_bytes <== dsc_pubkey_length_bytes;

//compare extracted public key with the one provided
for (var i=0; i<maxPubkeyBytesLength; i++) {
extractPubKey.out[i] === dsc_pubKey_bytes[i];
}

// Standardize public key to 35 words
signal standardizedDSCPubKey[35] <== StandardizePubKeyTo35Words(maxPubkeyBytesLength)(dsc_pubKey_bytes);

signal pubKey_dsc_hash <== CustomHasher(35)(standardizedDSCPubKey);
signal pubKey_csca_hash <== CustomHasher(kScaled)(csca_pubKey);


// Compute glue values
signal output glue <== Poseidon(4)([salt, dsc_pubkey_length_bytes, pubKey_dsc_hash, pubKey_csca_hash]);
// generate DSC leaf as poseidon(csca_hash, dsc_hash)
signal dsc_hash <== PackBytesAndPoseidon(MAX_DSC_LENGTH)(raw_dsc);
signal output dsc_tree_leaf <== Poseidon(2)([csca_tree_leaf, dsc_hash]);
}
2 changes: 1 addition & 1 deletion circuits/circuits/dsc/instances/dsc_sha1_rsa_3_4096.circom
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(33, 120, 35, 1664, 12);
component main { public [ merkle_root ] } = DSC(33, 120, 35);
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(11, 120, 35, 1664, 12);
component main { public [ merkle_root ] } = DSC(11, 120, 35);
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(32, 120, 35, 1664, 12);
component main { public [ merkle_root ] } = DSC(32, 120, 35);
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(10, 120, 35, 1664, 12);
// component main { public [ merkle_root ] } = DSC(10, 120, 35);
component main = DSC(10, 120, 35);
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(12, 120, 35, 1664, 12);
component main { public [ merkle_root ] } = DSC(12, 120, 35);
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(34, 120, 35, 1664, 12);
component main { public [ merkle_root ] } = DSC(34, 120, 35);
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pragma circom 2.1.9;

include "../dsc.circom";

component main { public [ merkle_root ] } = DSC(15, 120, 35, 1664, 12);
component main { public [ merkle_root ] } = DSC(15, 120, 35);

This file was deleted.

102 changes: 31 additions & 71 deletions circuits/circuits/register/register.circom
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,32 @@ include "../utils/crypto/bitify/bytes.circom";
/// @output commitment Commitment that will be added to the onchain registration tree
/// @output glue Used to link register and dsc proofs - the same is generated in the dsc circuit

template REGISTER(DG_HASH_ALGO, ECONTENT_HASH_ALGO, signatureAlgorithm, n, k, MAX_ECONTENT_PADDED_LEN, MAX_SIGNED_ATTR_PADDED_LEN) {
template REGISTER(
DG_HASH_ALGO,
ECONTENT_HASH_ALGO,
signatureAlgorithm,
n,
k,
MAX_ECONTENT_PADDED_LEN,
MAX_SIGNED_ATTR_PADDED_LEN
) {
var kLengthFactor = getKLengthFactor(signatureAlgorithm);
var kScaled = k * kLengthFactor;
var HASH_LEN_BITS = getHashLength(signatureAlgorithm);
var HASH_LEN_BYTES = HASH_LEN_BITS / 8;

var ECONTENT_HASH_ALGO_BYTES = ECONTENT_HASH_ALGO / 8;

var maxDscPubkeyBytesLength = getMaxDscPubKeyLength();
var dsc_pubkey_length_bytes = (getKeyLength(signatureAlgorithm) / 8) * kLengthFactor;

// signal input raw_dsc[MAX_DSC_LENGTH];
// signal input raw_dsc_actual_length;

// signal input dsc_pubKey_bytes[maxPubkeyBytesLength];
// signal input dsc_pubKey_offset;
// signal input dsc_pubkey_length_bytes;

signal input dg1[93];
signal input dg1_hash_offset;
signal input eContent[MAX_ECONTENT_PADDED_LEN];
Expand All @@ -57,8 +75,6 @@ template REGISTER(DG_HASH_ALGO, ECONTENT_HASH_ALGO, signatureAlgorithm, n, k, MA
signal input secret;
signal input salt;

signal dsc_pubkey_length_bytes_temp <== GetKLengthBytes(signatureAlgorithm)();
signal dsc_pubkey_length_bytes <== dsc_pubkey_length_bytes_temp * kLengthFactor;

// This means the attestation is a passport
signal attestation_id <== 1;
Expand Down Expand Up @@ -92,75 +108,19 @@ template REGISTER(DG_HASH_ALGO, ECONTENT_HASH_ALGO, signatureAlgorithm, n, k, MA
signal pubKey_dsc_hash_commitement <== CustomHasher(kScaled)(pubKey_dsc);

//convert DSC public key to 35 words of 120 bits each
component standardizedDSCPubKey = StandardizeDSCPubKey(n, k, kLengthFactor);
standardizedDSCPubKey.pubKey_dsc <== pubKey_dsc;
// component standardizedDSCPubKey = StandardizeDSCPubKey(n, k, kLengthFactor);
// standardizedDSCPubKey.pubKey_dsc <== pubKey_dsc;

signal pubKey_dsc_hash <== CustomHasher(35)(standardizedDSCPubKey.out);
// signal pubKey_dsc_hash <== CustomHasher(35)(standardizedDSCPubKey.out);

signal output commitment <== Poseidon(6)([
secret,
attestation_id,
dg1_packed_hash,
eContent_shaBytes_packed_hash,
pubKey_dsc_hash_commitement,
pubKey_csca_hash
]);
// signal output commitment <== Poseidon(6)([
// secret,
// attestation_id,
// dg1_packed_hash,
// eContent_shaBytes_packed_hash,
// pubKey_dsc_hash_commitement,
// pubKey_csca_hash
// ]);

signal output glue <== Poseidon(4)([salt, dsc_pubkey_length_bytes, pubKey_dsc_hash, pubKey_csca_hash]);
}

/// @notice Converts DSC public key into standardized 35 words of 120 bits each
/// @param n Number of bits per input word
/// @param k Number of input words
/// @param kLengthFactor Indicates if key needs to be split (2 for ECDSA)
/// @input pubKey_dsc Input DSC public key words
/// @output out 35 standardized words
template StandardizeDSCPubKey(n, k, kLengthFactor) {
signal input pubKey_dsc[k * kLengthFactor];
signal output out[35];

var maxPubkeyBytesLength = getMaxDscPubKeyLength();

if (kLengthFactor == 1) {
// RSA case

//In our case we always have 35 words of 120 bits each for RSA keys,
//So not converting to 8 bits. This is why we have the assert below.
assert(k == 35);
assert(n == 120);
component dsc_bytes = WordsToBytes(n, k, maxPubkeyBytesLength);
dsc_bytes.words <== pubKey_dsc;

component splitToWords = SplitBytesToWords(maxPubkeyBytesLength, 120, 35);
splitToWords.in <== dsc_bytes.bytes;

for (var i=0; i < 35; i++) {
out[i] <== splitToWords.out[i];
}

} else if (kLengthFactor == 2) {
// ECDSA case
component dsc_bytes_x = WordsToBytes(n, k, (n * k) / 8);
component dsc_bytes_y = WordsToBytes(n, k, (n * k) / 8);

for (var i=0; i < k; i++) {
dsc_bytes_y.words[i] <== pubKey_dsc[i];
dsc_bytes_x.words[i] <== pubKey_dsc[i + k];
}

component splitToWords = SplitBytesToWords(maxPubkeyBytesLength, 120, 35);
for (var i=0; i < 525; i++) {
if (i < n * k / 8) {
splitToWords.in[i] <== dsc_bytes_x.bytes[i];
} else if (i < n * k / 4) {
splitToWords.in[i] <== dsc_bytes_y.bytes[i - n * k / 8];
} else {
splitToWords.in[i] <== 0;
}
}

for (var i=0; i < 35; i++) {
out[i] <== splitToWords.out[i];
}
}
// signal output glue <== Poseidon(4)([salt, dsc_pubkey_length_bytes, pubKey_dsc_hash, pubKey_csca_hash]);
}
37 changes: 0 additions & 37 deletions circuits/circuits/tests/others/test_glue.circom

This file was deleted.

22 changes: 0 additions & 22 deletions circuits/circuits/tests/others/test_glue_120_35.circom

This file was deleted.

Loading

0 comments on commit 3acd769

Please sign in to comment.