@zkpersona/noir-ring-signatures
Version:
Implementation of Ring Signatures in Noir
106 lines (103 loc) • 19.5 kB
JavaScript
import { Grumpkin, GrumpkinScalar } from '@aztec/aztec.js';
import { pedersenHash } from '@aztec/foundation/crypto';
import { Field, BoundedVec, Bool } from '@zkpersona/noir-helpers';
// src/sag/index.ts
var mod = (value, modulus = GrumpkinScalar.MODULUS) => {
const result = value % modulus;
return result >= 0n ? result : result + modulus;
};
var randomScalar = () => GrumpkinScalar.random();
var hashToScalar = async (input) => {
const hash = await pedersenHash(input);
return GrumpkinScalar.fromBuffer(hash.toBuffer());
};
var sagToNoirInputs = (signature, messageFr, maxRingSize) => {
const c0 = new Field(signature.c0.toBigInt());
const s = new BoundedVec(
maxRingSize,
new Field(0),
signature.s.map((x) => new Field(x.toBigInt()))
);
const Default = {
x: new Field(0),
y: new Field(0),
is_infinite: new Bool(false)
};
const ring = new BoundedVec(
maxRingSize,
Default,
signature.publicKeys.map((p) => ({
x: new Field(p.x.toBigInt()),
y: new Field(p.y.toBigInt()),
is_infinite: new Bool(false)
}))
);
const sig = { c0, s };
const hashedMessage = new Field(messageFr.toBigInt());
return {
signature: sig,
hashed_message: hashedMessage,
ring
};
};
// src/sag/index.ts
var G = Grumpkin.generator;
var sign = async (hashedMessage, publicKeys, privateKey, signerIndex) => {
const Curve = new Grumpkin();
const ringSize = publicKeys.length;
const s = new Array(ringSize);
const c = new Array(ringSize);
const a = randomScalar();
const aG = await Curve.mul(G, a);
c[(signerIndex + 1) % ringSize] = await hashToScalar([
aG.x,
aG.y,
hashedMessage
]);
for (let i = (signerIndex + 1) % ringSize; i !== signerIndex; i = (i + 1) % ringSize) {
const K = publicKeys[i];
const r = randomScalar();
const rG = await Curve.mul(G, r);
const cK = await Curve.mul(K, c[i]);
const rG_cK = await Curve.add(cK, rG);
s[i] = r;
c[(i + 1) % ringSize] = await hashToScalar([
rG_cK.x,
rG_cK.y,
hashedMessage
]);
}
const res = mod(
a.toBigInt() - privateKey.toBigInt() * c[signerIndex].toBigInt()
);
s[signerIndex] = GrumpkinScalar.fromString(res.toString());
return {
c0: c[0],
s,
publicKeys
};
};
var verify = async (hashedMessage, signature) => {
const Curve = new Grumpkin();
const { c0, s, publicKeys } = signature;
const ringSize = publicKeys.length;
const C = new Array(ringSize);
C[0] = c0;
for (let i = 0; i < ringSize; i++) {
const K = publicKeys[i];
const r = s[i];
const c = C[i];
const rG = await Curve.mul(G, r);
const cK = await Curve.mul(K, c);
const cK_rG = await Curve.add(cK, rG);
C[(i + 1) % ringSize] = await hashToScalar([
cK_rG.x,
cK_rG.y,
hashedMessage
]);
}
return c0.equals(C[0]);
};
export { sagToNoirInputs, sign, verify };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oZWxwZXJzLnRzIiwiLi4vLi4vc3JjL3NhZy9oZWxwZXJzLnRzIiwiLi4vLi4vc3JjL3NhZy9pbmRleC50cyJdLCJuYW1lcyI6WyJHcnVtcGtpbiIsIkdydW1wa2luU2NhbGFyIl0sIm1hcHBpbmdzIjoiOzs7OztBQVlPLElBQU0sR0FBTSxHQUFBLENBQ2pCLEtBQ0EsRUFBQSxPQUFBLEdBQVUsZUFBZSxPQUNkLEtBQUE7QUFDWCxFQUFBLE1BQU0sU0FBUyxLQUFRLEdBQUEsT0FBQTtBQUN2QixFQUFPLE9BQUEsTUFBQSxJQUFVLEVBQUssR0FBQSxNQUFBLEdBQVMsTUFBUyxHQUFBLE9BQUE7QUFDMUMsQ0FBQTtBQVFPLElBQU0sWUFBQSxHQUFlLE1BQU0sY0FBQSxDQUFlLE1BQU8sRUFBQTtBQXdCakQsSUFBTSxZQUFBLEdBQWUsT0FDMUIsS0FDNEIsS0FBQTtBQUM1QixFQUFNLE1BQUEsSUFBQSxHQUFPLE1BQU0sWUFBQSxDQUFhLEtBQUssQ0FBQTtBQUNyQyxFQUFBLE9BQU8sY0FBZSxDQUFBLFVBQUEsQ0FBVyxJQUFLLENBQUEsUUFBQSxFQUFVLENBQUE7QUFDbEQsQ0FBQTtBQzdCTyxJQUFNLGVBQWtCLEdBQUEsQ0FDN0IsU0FDQSxFQUFBLFNBQUEsRUFDQSxXQUNHLEtBQUE7QUFFSCxFQUFBLE1BQU0sS0FBSyxJQUFJLEtBQUEsQ0FBTSxTQUFVLENBQUEsRUFBQSxDQUFHLFVBQVUsQ0FBQTtBQUc1QyxFQUFBLE1BQU0sSUFBSSxJQUFJLFVBQUE7QUFBQSxJQUNaLFdBQUE7QUFBQSxJQUNBLElBQUksTUFBTSxDQUFDLENBQUE7QUFBQSxJQUNYLFNBQUEsQ0FBVSxDQUFFLENBQUEsR0FBQSxDQUFJLENBQUMsQ0FBQSxLQUFNLElBQUksS0FBTSxDQUFBLENBQUEsQ0FBRSxRQUFTLEVBQUMsQ0FBQztBQUFBLEdBQ2hEO0FBR0EsRUFBQSxNQUFNLE9BQVUsR0FBQTtBQUFBLElBQ2QsQ0FBQSxFQUFHLElBQUksS0FBQSxDQUFNLENBQUMs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Q3BDLElBQUEsQ0FBQSxDQUFBLENBQUcsQ0FBSSxHQUFBLENBQUEsSUFBSyxRQUFRLENBQUEsR0FBSSxNQUFNLFlBQWEsQ0FBQTtBQUFBLE1BQ3pDLEtBQU0sQ0FBQSxDQUFBO0FBQUEsTUFDTixLQUFNLENBQUEsQ0FBQTtBQUFBLE1BQ047QUFBQSxLQUNELENBQUE7QUFBQTtBQUlILEVBQUEsT0FBTyxFQUFHLENBQUEsTUFBQSxDQUFPLENBQUUsQ0FBQSxDQUFDLENBQUMsQ0FBQTtBQUN2QiIsImZpbGUiOiJpbmRleC5tanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBHcnVtcGtpbiwgR3J1bXBraW5TY2FsYXIgfSBmcm9tICdAYXp0ZWMvYXp0ZWMuanMnO1xuaW1wb3J0IHsgcGVkZXJzZW5IYXNoIH0gZnJvbSAnQGF6dGVjL2ZvdW5kYXRpb24vY3J5cHRvJztcbmltcG9ydCB0eXBlIHsgRmllbGRhYmxlIH0gZnJvbSAnQGF6dGVjL2ZvdW5kYXRpb24vc2VyaWFsaXplJztcblxuLyoqXG4gKiBDb21wdXRlcyB0aGUgbW9kdWxvIG9wZXJhdGlvbiBvbiBhIGJpZ2ludCB2YWx1ZSB3aXRoIGEgc3BlY2lmaWVkIG1vZHVsdXMuXG4gKiBFbnN1cmVzIHRoZSByZXN1bHQgaXMgYWx3YXlzIG5vbi1uZWdhdGl2ZSBhbmQgd2l0aGluIHRoZSByYW5nZSBbMCwgbW9kdWx1cykuXG4gKlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGNvbXB1dGUgbW9kdWxvIG9uXG4gKiBAcGFyYW0gbW9kdWx1cyAtIFRoZSBtb2R1bHVzIHRvIHVzZSAoZGVmYXVsdHMgdG8gR3J1bXBraW5TY2FsYXIuTU9EVUxVUylcbiAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgdmFsdWUgbW9kIG1vZHVsdXMsIGd1YXJhbnRlZWQgdG8gYmUgbm9uLW5lZ2F0aXZlXG4gKi9cbmV4cG9ydCBjb25zdCBtb2QgPSAoXG4gIHZhbHVlOiBiaWdpbnQsXG4gIG1vZHVsdXMgPSBHcnVtcGtpblNjYWxhci5NT0RVTFVTXG4pOiBiaWdpbnQgPT4ge1xuICBjb25zdCByZXN1bHQgPSB2YWx1ZSAlIG1vZHVsdXM7XG4gIHJldHVybiByZXN1bHQgPj0gMG4gPyByZXN1bHQgOiByZXN1bHQgKyBtb2R1bHVzO1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gc2NhbGFyIHZhbHVlIG9uIHRoZSBHcnVtcGtpbiBjdXJ2ZS5cbiAqIFRoaXMgaXMgdXNlZnVsIGZvciBjcmVhdGluZyBwcml2YXRlIGtleXMgYW5kIHJhbmRvbSB2YWx1ZXMgaW4gY3J5cHRvZ3JhcGhpYyBvcGVyYXRpb25zLlxuICpcbiAqIEByZXR1cm5zIEEgcmFuZG9tIEdydW1wa2luU2NhbGFyIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCByYW5kb21TY2FsYXIgPSAoKSA9PiBHcnVtcGtpblNjYWxhci5yYW5kb20oKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBuZXcga2V5IHBhaXIgZm9yIHRoZSBHcnVtcGtpbiBjdXJ2ZS5cbiAqIFRoZSBrZXkgcGFpciBjb25zaXN0cyBvZiBhIHByaXZhdGUga2V5IChzY2FsYXIpIGFuZCBpdHMgY29ycmVzcG9uZGluZyBwdWJsaWMga2V5IChwb2ludCkuXG4gKlxuICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmc6XG4gKiAgIC0gcHJpdmF0ZUtleTogQSByYW5kb20gR3J1bXBraW5TY2FsYXIgdmFsdWVcbiAqICAgLSBwdWJsaWNLZXk6IFRoZSBjb3JyZXNwb25kaW5nIHB1YmxpYyBrZXkgcG9pbnQgb24gdGhlIEdydW1wa2luIGN1cnZlXG4gKi9cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZUtleVBhaXIgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnN0IHByaXZhdGVLZXkgPSBHcnVtcGtpblNjYWxhci5yYW5kb20oKTtcbiAgY29uc3QgQ3VydmUgPSBuZXcgR3J1bXBraW4oKTtcbiAgY29uc3QgcHVibGljS2V5ID0gYXdhaXQgQ3VydmUubXVsKEdydW1wa2luLmdlbmVyYXRvciwgcHJpdmF0ZUtleSk7XG4gIHJldHVybiB7IHByaXZhdGVLZXksIHB1YmxpY0tleSB9O1xufTtcblxuLyoqXG4gKiBIYXNoZXMgYW4gYXJyYXkgb2YgZmllbGQgZWxlbWVudHMgdG8gYSBzY2FsYXIgdmFsdWUgb24gdGhlIEdydW1wa2luIGN1cnZlLlxuICogVGhpcyBpcyB1c2VmdWwgZm9yIGNvbnZlcnRpbmcgYXJiaXRyYXJ5IGRhdGEgaW50byBhIHNjYWxhciB2YWx1ZSBmb3IgY3J5cHRvZ3JhcGhpYyBvcGVyYXRpb25zLlxuICpcbiAqIEBwYXJhbSBpbnB1dCAtIEFuIGFycmF5IG9mIGZpZWxkIGVsZW1lbnRzIHRvIGhhc2hcbiAqIEByZXR1cm5zIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgR3J1bXBraW5TY2FsYXIgdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IGhhc2hUb1NjYWxhciA9IGFzeW5jIChcbiAgaW5wdXQ6IEZpZWxkYWJsZVtdXG4pOiBQcm9taXNlPEdydW1wa2luU2NhbGFyPiA9PiB7XG4gIGNvbnN0IGhhc2ggPSBhd2FpdCBwZWRlcnNlbkhhc2goaW5wdXQpO1xuICByZXR1cm4gR3J1bXBraW5TY2FsYXIuZnJvbUJ1ZmZlcihoYXNoLnRvQnVmZmVyKCkpO1xufTtcbiIsImltcG9ydCB0eXBlIHsgRnIgfSBmcm9tICdAYXp0ZWMvYXp0ZWMuanMnO1xuaW1wb3J0IHsgQm9vbCwgQm91bmRlZFZlYywgRmllbGQgfSBmcm9tICdAemtwZXJzb25hL25vaXItaGVscGVycyc7XG5pbXBvcnQgdHlwZSB7IFJpbmdTaWduYXR1cmUgfSBmcm9tICcuLi90eXBlcyc7XG5cbi8qKlxuICogQ29udmVydHMgYSBTQUcgKFNpZ25hdHVyZSBvZiBBbm9ueW1vdXMgR3JvdXApIHJpbmcgc2lnbmF0dXJlIHRvIHRoZSBmb3JtYXQgcmVxdWlyZWRcbiAqIGJ5IHRoZSBOb2lyIGNpcmN1aXQgZm9yIHZlcmlmaWNhdGlvbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGhhbmRsZXMgdGhlIGNvbnZlcnNpb24gb2Y6XG4gKiAtIFRoZSBpbml0aWFsIGNoYWxsZW5nZSB2YWx1ZSAoYzApXG4gKiAtIFRoZSByZXNwb25zZSB2YWx1ZXMgKHMpIGZvciBlYWNoIHJpbmcgbWVtYmVyXG4gKiAtIFRoZSBwdWJsaWMga2V5cyBmb3JtaW5nIHRoZSByaW5nXG4gKiAtIFRoZSBoYXNoZWQgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSBzaWduYXR1cmUgLSBUaGUgU0FHIHJpbmcgc2lnbmF0dXJlIHRvIGNvbnZlcnQsIGNvbnRhaW5pbmc6XG4gKiAgIC0gYzA6IFRoZSBpbml0aWFsIGNoYWxsZW5nZSB2YWx1ZVxuICogICAtIHM6IEFycmF5IG9mIHJlc3BvbnNlIHZhbHVlcyBmb3IgZWFjaCByaW5nIG1lbWJlclxuICogICAtIHB1YmxpY0tleXM6IEFycmF5IG9mIHB1YmxpYyBrZXlzIGZvcm1pbmcgdGhlIHJpbmdcbiAqIEBwYXJhbSBtZXNzYWdlRnIgLSBUaGUgaGFzaGVkIG1lc3NhZ2UgYXMgYSBmaWVsZCBlbGVtZW50XG4gKiBAcGFyYW0gbWF4UmluZ1NpemUgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgcHVibGljIGtleXMgdGhhdCBjYW4gYmUgaW4gdGhlIHJpbmdcbiAqXG4gKiBAcmV0dXJucyBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgY29udmVydGVkIGlucHV0cyBmb3IgdGhlIE5vaXIgY2lyY3VpdDpcbiAqICAgLSBzaWduYXR1cmU6IFRoZSBjb252ZXJ0ZWQgc2lnbmF0dXJlIHdpdGggYzAgYW5kIHMgdmFsdWVzXG4gKiAgIC0gaGFzaGVkX21lc3NhZ2U6IFRoZSBjb252ZXJ0ZWQgaGFzaGVkIG1lc3NhZ2VcbiAqICAgLSByaW5nOiBUaGUgY29udmVydGVkIGFycmF5IG9mIHB1YmxpYyBrZXlzXG4gKi9cbmV4cG9ydCBjb25zdCBzYWdUb05vaXJJbnB1dHMgPSAoXG4gIHNpZ25hdHVyZTogUmluZ1NpZ25hdHVyZSxcbiAgbWVzc2FnZUZyOiBGcixcbiAgbWF4UmluZ1NpemU6IG51bWJlclxuKSA9PiB7XG4gIC8vIENvbnZlcnQgdGhlIGluaXRpYWwgY2hhbGxlbmdlIHZhbHVlIHRvIGEgTm9pciBGaWVsZFxuICBjb25zdCBjMCA9IG5ldyBGaWVsZChzaWduYXR1cmUuYzAudG9CaWdJbnQoKSk7XG5cbiAgLy8gQ29udmVydCB0aGUgcmVzcG9uc2UgdmFsdWVzIHRvIGEgTm9pciBCb3VuZGVkVmVjIG9mIEZpZWxkc1xuICBjb25zdCBzID0gbmV3IEJvdW5kZWRWZWMoXG4gICAgbWF4UmluZ1NpemUsXG4gICAgbmV3IEZpZWxkKDApLFxuICAgIHNpZ25hdHVyZS5zLm1hcCgoeCkgPT4gbmV3IEZpZWxkKHgudG9CaWdJbnQoKSkpXG4gICk7XG5cbiAgLy8gRGVmaW5lIHRoZSBkZWZhdWx0IHBvaW50IHN0cnVjdHVyZSBmb3IgdGhlIHJpbmdcbiAgY29uc3QgRGVmYXVsdCA9IHtcbiAgICB4OiBuZXcgRmllbGQoMCksXG4gICAgeTogbmV3IEZpZWxkKDApLFxuICAgIGlzX2luZmluaXRlOiBuZXcgQm9vbChmYWxzZSksXG4gIH07XG5cbiAgLy8gQ29udmVydCB0aGUgcHVibGljIGtleXMgdG8gYSBOb2lyIEJvdW5kZWRWZWMgb2YgcG9pbnRzXG4gIGNvbnN0IHJpbmcgPSBuZXcgQm91bmRlZFZlYyhcbiAgICBtYXhSaW5nU2l6ZSxcbiAgICBEZWZhdWx0LFxuICAgIHNpZ25hdHVyZS5wdWJsaWNLZXlzLm1hcCgocCkgPT4gKHtcbiAgICAgIHg6IG5ldyBGaWVsZChwLngudG9CaWdJbnQoKSksXG4gICAgICB5OiBuZXcgRmllbGQocC55LnRvQmlnSW50KCkpLFxuICAgICAgaXNfaW5maW5pdGU6IG5ldyBCb29sKGZhbHNlKSxcbiAgICB9KSlcbiAgKTtcblxuICAvLyBDcmVhdGUgdGhlIHNpZ25hdHVyZSBvYmplY3Qgd2l0aCBjb252ZXJ0ZWQgdmFsdWVzXG4gIGNvbnN0IHNpZyA9IHsgYzAsIHMgfTtcblxuICAvLyBDb252ZXJ0IHRoZSBoYXNoZWQgbWVzc2FnZSB0byBhIE5vaXIgRmllbGRcbiAgY29uc3QgaGFzaGVkTWVzc2FnZSA9IG5ldyBGaWVsZChtZXNzYWdlRnIudG9CaWdJbnQoKSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzaWduYXR1cmU6IHNpZyxcbiAgICBoYXNoZWRfbWVzc2FnZTogaGFzaGVkTWVzc2FnZSxcbiAgICByaW5nLFxuICB9O1xufTtcbiIsIi8qKlxuICogSW1wbGVtZW50YXRpb24gb2YgdGhlIFNBRyAoU3BvbnRhbmVvdXMgQW5vbnltb3VzIEdyb3VwKSByaW5nIHNpZ25hdHVyZSBzY2hlbWVcbiAqIHVzaW5nIHRoZSBHcnVtcGtpbiBjdXJ2ZSBhbmQgUGVkZXJzZW4gaGFzaCBmdW5jdGlvbi5cbiAqXG4gKiBUaGlzIGltcGxlbWVudGF0aW9uIHByb3ZpZGVzIGEgd2F5IHRvIGNyZWF0ZSBhbmQgdmVyaWZ5IHJpbmcgc2lnbmF0dXJlcyxcbiAqIHdoaWNoIGFsbG93IGEgbWVtYmVyIG9mIGEgZ3JvdXAgdG8gc2lnbiBhIG1lc3NhZ2Ugb24gYmVoYWxmIG9mIHRoZSBncm91cFxuICogd2l0aG91dCByZXZlYWxpbmcgd2hpY2ggc3BlY2lmaWMgbWVtYmVyIGNyZWF0ZWQgdGhlIHNpZ25hdHVyZS5cbiAqXG4gKiBAbW9kdWxlIHNhZ1xuICovXG5cbmltcG9ydCB7IHR5cGUgRnIsIEdydW1wa2luLCBHcnVtcGtpblNjYWxhciwgdHlwZSBQb2ludCB9IGZyb20gJ0BhenRlYy9henRlYy5qcyc7XG5pbXBvcnQgeyBoYXNoVG9TY2FsYXIsIG1vZCwgcmFuZG9tU2NhbGFyIH0gZnJvbSAnLi4vaGVscGVycyc7XG5pbXBvcnQgdHlwZSB7IFJpbmdTaWduYXR1cmUgfSBmcm9tICcuLi90eXBlcyc7XG5cbi8qKiBHZW5lcmF0b3IgcG9pbnQgb2YgdGhlIEdydW1wa2luIGN1cnZlICovXG5jb25zdCBHID0gR3J1bXBraW4uZ2VuZXJhdG9yO1xuXG4vKipcbiAqIENyZWF0ZXMgYSByaW5nIHNpZ25hdHVyZSBmb3IgYSBnaXZlbiBtZXNzYWdlIHVzaW5nIHRoZSBTQUcgc2NoZW1lLlxuICpcbiAqIFRoZSBzaWduaW5nIHByb2Nlc3MgaW52b2x2ZXM6XG4gKiAxLiBHZW5lcmF0aW5nIGEgcmFuZG9tIHNjYWxhciAnYScgYW5kIGNvbXB1dGluZyBhR1xuICogMi4gQ3JlYXRpbmcgYSBjaGFpbiBvZiBjb21taXRtZW50cyB1c2luZyB0aGUgcHVibGljIGtleXMgaW4gdGhlIHJpbmdcbiAqIDMuIENvbXB1dGluZyB0aGUgc2lnbmF0dXJlIGNvbXBvbmVudHMgKHMgdmFsdWVzKSBmb3IgZWFjaCByaW5nIG1lbWJlclxuICogNC4gVXNpbmcgdGhlIHNpZ25lcidzIHByaXZhdGUga2V5IHRvIGNsb3NlIHRoZSByaW5nXG4gKlxuICogQHBhcmFtIGhhc2hlZE1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBzaWduZWQsIGFscmVhZHkgaGFzaGVkIHRvIGEgZmllbGQgZWxlbWVudFxuICogQHBhcmFtIHB1YmxpY0tleXMgLSBBcnJheSBvZiBwdWJsaWMga2V5cyBmb3JtaW5nIHRoZSByaW5nXG4gKiBAcGFyYW0gcHJpdmF0ZUtleSAtIFByaXZhdGUga2V5IG9mIHRoZSBhY3R1YWwgc2lnbmVyXG4gKiBAcGFyYW0gc2lnbmVySW5kZXggLSBJbmRleCBvZiB0aGUgc2lnbmVyJ3MgcHVibGljIGtleSBpbiB0aGUgcmluZ1xuICogQHJldHVybnMgQSByaW5nIHNpZ25hdHVyZSBjb250YWluaW5nIHRoZSBjaGFsbGVuZ2UgYzAsIHNpZ25hdHVyZSBjb21wb25lbnRzIHMsIGFuZCBwdWJsaWMga2V5c1xuICovXG5leHBvcnQgY29uc3Qgc2lnbiA9IGFzeW5jIChcbiAgaGFzaGVkTWVzc2FnZTogRnIsXG4gIHB1YmxpY0tleXM6IFBvaW50W10sXG4gIHByaXZhdGVLZXk6IEdydW1wa2luU2NhbGFyLFxuICBzaWduZXJJbmRleDogbnVtYmVyXG4pOiBQcm9taXNlPFJpbmdTaWduYXR1cmU+ID0+IHtcbiAgY29uc3QgQ3VydmUgPSBuZXcgR3J1bXBraW4oKTtcbiAgY29uc3QgcmluZ1NpemUgPSBwdWJsaWNLZXlzLmxlbmd0aDtcbiAgY29uc3QgczogR3J1bXBraW5TY2FsYXJbXSA9IG5ldyBBcnJheShyaW5nU2l6ZSk7XG4gIGNvbnN0IGM6IEdydW1wa2luU2NhbGFyW10gPSBuZXcgQXJyYXkocmluZ1NpemUpO1xuXG4gIC8vIFN0ZXAgMTogR2VuZXJhdGUgcmFuZG9tIHNjYWxhciAnYScgYW5kIGNvbXB1dGUgYUdcbiAgY29uc3QgYSA9IHJhbmRvbVNjYWxhcigpO1xuICBjb25zdCBhRyA9IGF3YWl0IEN1cnZlLm11bChHLCBhKTtcblxuICAvLyBTdGVwIDI6IENvbXB1dGUgZmlyc3QgY2hhbGxlbmdlIGFmdGVyIHNpZ25lcidzIHBvc2l0aW9uXG4gIGNbKHNpZ25lckluZGV4ICsgMSkgJSByaW5nU2l6ZV0gPSBhd2FpdCBoYXNoVG9TY2FsYXIoW1xuICAgIGFHLngsXG4gICAgYUcueSxcbiAgICBoYXNoZWRNZXNzYWdlLFxuICBdKTtcblxuICAvLyBTdGVwIDM6IENyZWF0ZSBjaGFpbiBvZiBjb21taXRtZW50cyBmb3IgYWxsIHJpbmcgbWVtYmVycyBleGNlcHQgdGhlIHNpZ25lclxuICBmb3IgKFxuICAgIGxldCBpID0gKHNpZ25lckluZGV4ICsgMSkgJSByaW5nU2l6ZTtcbiAgICBpICE9PSBzaWduZXJJbmRleDtcbiAgICBpID0gKGkgKyAxKSAlIHJpbmdTaXplXG4gICkge1xuICAgIGNvbnN0IEsgPSBwdWJsaWNLZXlzW2ldITtcbiAgICBjb25zdCByID0gcmFuZG9tU2NhbGFyKCk7XG4gICAgY29uc3QgckcgPSBhd2FpdCBDdXJ2ZS5tdWwoRywgcik7XG4gICAgY29uc3QgY0sgPSBhd2FpdCBDdXJ2ZS5tdWwoSywgY1tpXSEpO1xuICAgIGNvbnN0IHJHX2NLID0gYXdhaXQgQ3VydmUuYWRkKGNLLCByRyk7XG4gICAgc1tpXSA9IHI7XG4gICAgY1soaSArIDEpICUgcmluZ1NpemVdID0gYXdhaXQgaGFzaFRvU2NhbGFyKFtcbiAgICAgIHJHX2NLLngsXG4gICAgICByR19jSy55LFxuICAgICAgaGFzaGVkTWVzc2FnZSxcbiAgICBdKTtcbiAgfVxuXG4gIC8vIFN0ZXAgNDogQ29tcHV0ZSBzaWduZXIncyBzaWduYXR1cmUgY29tcG9uZW50IHVzaW5nIHByaXZhdGUga2V5XG4gIGNvbnN0IHJlcyA9IG1vZChcbiAgICBhLnRvQmlnSW50KCkgLSBwcml2YXRlS2V5LnRvQmlnSW50KCkgKiBjW3NpZ25lckluZGV4XSEudG9CaWdJbnQoKVxuICApO1xuXG4gIHNbc2lnbmVySW5kZXhdID0gR3J1bXBraW5TY2FsYXIuZnJvbVN0cmluZyhyZXMudG9TdHJpbmcoKSk7XG5cbiAgcmV0dXJuIHtcbiAgICBjMDogY1swXSEsXG4gICAgcyxcbiAgICBwdWJsaWNLZXlzLFxuICB9O1xufTtcblxuLyoqXG4gKiBWZXJpZmllcyBhIHJpbmcgc2lnbmF0dXJlIGFnYWluc3QgYSBnaXZlbiBtZXNzYWdlLlxuICpcbiAqIFRoZSB2ZXJpZmljYXRpb24gcHJvY2VzcyBpbnZvbHZlczpcbiAqIDEuIFJlY29uc3RydWN0aW5nIHRoZSBjaGFpbiBvZiBjb21taXRtZW50cyB1c2luZyB0aGUgc2lnbmF0dXJlIGNvbXBvbmVudHNcbiAqIDIuIENoZWNraW5nIGlmIHRoZSBmaW5hbCBjaGFsbGVuZ2UgbWF0Y2hlcyB0aGUgaW5pdGlhbCBjaGFsbGVuZ2UgKGMwKVxuICpcbiAqIEBwYXJhbSBoYXNoZWRNZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gdmVyaWZ5LCBhbHJlYWR5IGhhc2hlZCB0byBhIGZpZWxkIGVsZW1lbnRcbiAqIEBwYXJhbSBzaWduYXR1cmUgLSBUaGUgcmluZyBzaWduYXR1cmUgdG8gdmVyaWZ5XG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBzaWduYXR1cmUgaXMgdmFsaWQsIGZhbHNlIG90aGVyd2lzZVxuICovXG5leHBvcnQgY29uc3QgdmVyaWZ5ID0gYXN5bmMgKFxuICBoYXNoZWRNZXNzYWdlOiBGcixcbiAgc2lnbmF0dXJlOiBSaW5nU2lnbmF0dXJlXG4pOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgY29uc3QgQ3VydmUgPSBuZXcgR3J1bXBraW4oKTtcbiAgY29uc3QgeyBjMCwgcywgcHVibGljS2V5cyB9ID0gc2lnbmF0dXJlO1xuICBjb25zdCByaW5nU2l6ZSA9IHB1YmxpY0tleXMubGVuZ3RoO1xuICBjb25zdCBDOiBHcnVtcGtpblNjYWxhcltdID0gbmV3IEFycmF5KHJpbmdTaXplKTtcblxuICBDWzBdID0gYzA7XG5cbiAgLy8gUmVjb25zdHJ1Y3QgdGhlIGNoYWluIG9mIGNvbW1pdG1lbnRzXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmluZ1NpemU7IGkrKykge1xuICAgIGNvbnN0IEsgPSBwdWJsaWNLZXlzW2ldITtcbiAgICBjb25zdCByID0gc1tpXSE7XG4gICAgY29uc3QgYyA9IENbaV0hO1xuICAgIGNvbnN0IHJHID0gYXdhaXQgQ3VydmUubXVsKEcsIHIpO1xuICAgIGNvbnN0IGNLID0gYXdhaXQgQ3VydmUubXVsKEssIGMpO1xuICAgIGNvbnN0IGNLX3JHID0gYXdhaXQgQ3VydmUuYWRkKGNLLCByRyk7XG4gICAgQ1soaSArIDEpICUgcmluZ1NpemVdID0gYXdhaXQgaGFzaFRvU2NhbGFyKFtcbiAgICAgIGNLX3JHLngsXG4gICAgICBjS19yRy55LFxuICAgICAgaGFzaGVkTWVzc2FnZSxcbiAgICBdKTtcbiAgfVxuXG4gIC8vIFZlcmlmeSB0aGF0IHRoZSBjaGFpbiBjbG9zZXMgY29ycmVjdGx5XG4gIHJldHVybiBjMC5lcXVhbHMoQ1swXSk7XG59O1xuXG5leHBvcnQgKiBmcm9tICcuL2hlbHBlcnMnO1xuIl19