UNPKG

@reclaimprotocol/zk-symmetric-crypto

Version:

JS Wrappers for Various ZK Snark Circuits

215 lines (214 loc) 6.51 kB
export type EncryptionAlgorithm = 'aes-256-ctr' | 'aes-128-ctr' | 'chacha20'; export type ZKEngine = 'snarkjs' | 'gnark' | 'expander'; export type UintArray = Uint32Array; export type Proof = { algorithm: EncryptionAlgorithm; /** serialised proof */ proofData: ZKProof; /** * the plaintext obtained as an output * of the ZK circuit */ plaintext: Uint8Array; }; export type FileFetch = { fetch(engine: ZKEngine, filename: string, logger?: Logger): Promise<Uint8Array>; }; export type MakeZKOperatorOpts<T> = { algorithm: EncryptionAlgorithm; fetcher: FileFetch; options?: T; }; export type MakeZKOperator<T> = (opts: MakeZKOperatorOpts<T>) => ZKOperator; export type MakeOPRFOperator<T> = (opts: MakeZKOperatorOpts<T>) => OPRFOperator; /** * provide Uint8array for file data loaded into memory * or string, that is the path to load said file * */ type ZKInput = Uint8Array | string; export type VerificationKey = { /** binary data for .zkey file */ data: ZKInput; json?: unknown; }; export type CircuitWasm = Uint8Array | string; export type GenerateWitnessOpts = { /** * the algorithm to use for the encryption * circuit. Used to correctly slice the * IV, counters etc. */ algorithm: EncryptionAlgorithm; /** * private input to the circuit (i.e. key) */ privateInput: PrivateInput; /** * public input to the circuit, * i.e. the ciphertext to decrypt */ publicInput: PublicInput; } & ({ mask: ZKInputItem; toprf: ZKTOPRFPublicSignals; } | {}); export type GenerateProofOpts = GenerateWitnessOpts & { /** * Operator to use for proving the circuit */ operator: ZKOperator | OPRFOperator; logger?: Logger; }; export type GetPublicSignalsOpts = { /** * JSON proof generated by "generateProof" fn * with the plaintext * */ proof: Proof; publicInput: PublicInput; }; export type VerifyProofOpts = GetPublicSignalsOpts & ({ operator: ZKOperator; logger?: Logger; } | { operator: OPRFOperator; logger?: Logger; toprf: ZKTOPRFPublicSignals; }); export type AlgorithmConfig = { index: number; /** * Chunk size in words (of the algorithm) * eg. chacha20 has 32-bit words, aes-256-ctr has 8-bit words */ chunkSize: number; bitsPerWord: number; keySizeBytes: number; ivSizeBytes: number; startCounter: number; blocksPerChunk: number; isLittleEndian: boolean; uint8ArrayToBits: (arr: Uint8Array) => number[]; bitsToUint8Array: (bits: number[]) => Uint8Array; /** * Encrypt some ciphertext with the given key and IV */ encrypt(opts: { key: Uint8Array; iv: Uint8Array; in: Uint8Array; }): Promise<Uint8Array> | Uint8Array; }; type ZKProof = string | Uint8Array; type ZKProofOutput = { proof: ZKProof; }; type ZKInputItem = Uint8Array; export type ZKTOPRFResponsePublicSignals = { publicKeyShare: ZKInputItem; evaluated: ZKInputItem; c: ZKInputItem; r: ZKInputItem; }; export type ZKTOPRFPublicSignals = { pos: number; len: number; domainSeparator: string; output: ZKInputItem; responses: ZKTOPRFResponsePublicSignals[]; }; export type ZKProofPublicSignals = { nonce: ZKInputItem; counter: number; in: ZKInputItem; out: ZKInputItem; }; export type ZKProofPublicSignalsOPRF = ZKProofPublicSignals & { toprf: ZKTOPRFPublicSignals; }; export type ZKProofInput = { key: ZKInputItem; } & ZKProofPublicSignals; export type ZKProofInputOPRF = { key: ZKInputItem; mask: ZKInputItem; } & ZKProofPublicSignalsOPRF; export type OPRFRequestData = { mask: Uint8Array; maskedData: Uint8Array; secretElements: Uint8Array[]; }; type OPRFResponse = { evaluated: Uint8Array; c: Uint8Array; r: Uint8Array; }; export type OPRFResponseData = OPRFResponse & { publicKeyShare: Uint8Array; }; export type KeyShare = { index: number; publicKey: Uint8Array; privateKey: Uint8Array; }; export type KeygenResult = { publicKey: Uint8Array; privateKey: Uint8Array; shares: KeyShare[]; }; /** * the operator to use for proving and verifying the groth16 * proof of the ChaCha20 circuit * * this generic interface is allow * for different implementations */ export type ZKOperator = { generateWitness(input: ZKProofInput, logger?: Logger): Promise<Uint8Array> | Uint8Array; groth16Prove(witness: Uint8Array, logger?: Logger): Promise<ZKProofOutput>; groth16Verify(publicSignals: ZKProofPublicSignals, proof: ZKProof, logger?: Logger): Promise<boolean>; /** * Release any used resources. The operator * should still be usable after this call. * * This is useful for releasing any resources * in case ZK operations are not going to be * used for a while. */ release?(): void; }; export type OPRFOperator = { generateWitness(input: ZKProofInputOPRF, logger?: Logger): Promise<Uint8Array>; groth16Prove(witness: Uint8Array, logger?: Logger): Promise<ZKProofOutput>; groth16Verify(publicSignals: ZKProofPublicSignalsOPRF, proof: ZKProof, logger?: Logger): Promise<boolean>; generateThresholdKeys(total: number, threshold: number, logger?: Logger): Promise<KeygenResult>; generateOPRFRequestData(data: Uint8Array, domainSeparator: string, logger?: Logger): Promise<OPRFRequestData>; finaliseOPRF(serverPublicKey: Uint8Array, request: OPRFRequestData, responses: OPRFResponseData[], logger?: Logger): Promise<Uint8Array>; evaluateOPRF(serverPrivateKey: Uint8Array, request: Uint8Array, logger?: Logger): Promise<OPRFResponse>; /** * Release any used resources. The operator * should still be usable after this call. * * This is useful for releasing any resources * in case ZK operations are not going to be * used for a while. */ release?(): void; }; export type PrivateInput = { /** 256 bit ChaCha20 key to decrypt ciphertext */ key: Uint8Array; }; export type PublicInput = { /** the ciphertext to decrypt */ ciphertext: Uint8Array; /** 192 bit IV for the ciphertext decryption */ iv: Uint8Array; /** * If the passed ciphertext is a slice of the original ciphertext, * what offset (in bytes) does this slice start from? * */ offsetBytes?: number; }; export type Logger = Pick<typeof console, 'info' | 'trace' | 'debug' | 'error' | 'warn'>; export {};