Skip to content

Commit

Permalink
fix bits accumulator
Browse files Browse the repository at this point in the history
  • Loading branch information
RajeshRk18 committed Nov 23, 2023
1 parent 88f8864 commit c17de76
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 3 deletions.
6 changes: 3 additions & 3 deletions circuits/verify_nullifier.circom
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,15 @@ template sha256_12_coordinates(n, k) {
}

// preimage bit length accumulator
var preimage_bit_len = 0;
var preimage_bytes_length = 0;

// decompose coordinates inputs into binary
component binary[6*33];
for (var i = 0; i < 6; i++) { // for each compressor
for (var j = 0; j < 33; j++) { // for each byte
binary[33*i + j] = Num2Bits(8);
binary[33*i + j].in <== compressors[i].compressed[j];
preimage_bit_len += 1;
preimage_bytes_length += 1;
}
}

Expand All @@ -284,7 +284,7 @@ template sha256_12_coordinates(n, k) {
// check whether the preimage bit length is equal to the message bits
component is_eq = IsEqual();
is_equal.in[0] <== message_bits;
is_equal.in[1] <== preimage_bit_len;
is_equal.in[1] <== preimage_bytes_length * 8; //converting bytes length to bits length
is_equal.out === 1;

var total_bits = (message_bits \ 512) * 512;
Expand Down
101 changes: 101 additions & 0 deletions javascript/src/signals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeAllInputs = exports.computeS = exports.computeHashToCurveR = exports.computeRPoint = exports.computeNullifer = exports.computeC_V1 = exports.computeC_V2 = exports.computeHashToCurve = exports.PlumeVersion = void 0;
var secp256k1_1 = require("@noble/secp256k1");
var encoding_1 = require("./utils/encoding");
var hashToCurve_1 = require("./utils/hashToCurve");
var curve_1 = require("./utils/curve");
var js_sha256_1 = require("js-sha256");
// PLUME version
var PlumeVersion;
(function (PlumeVersion) {
PlumeVersion[PlumeVersion["V1"] = 1] = "V1";
PlumeVersion[PlumeVersion["V2"] = 2] = "V2";
})(PlumeVersion || (exports.PlumeVersion = PlumeVersion = {}));
function computeHashToCurve(message, pk) {
// Concatenate message and publicKey
var preimage = new Uint8Array(message.length + pk.length);
preimage.set(message);
preimage.set(pk, message.length);
return (0, hashToCurve_1.default)(Array.from(preimage));
}
exports.computeHashToCurve = computeHashToCurve;
function computeC_V2(nullifier, rPoint, hashedToCurveR) {
var nullifierBytes = nullifier.toRawBytes(true);
var preimage = (0, encoding_1.concatUint8Arrays)([
nullifierBytes,
rPoint.toRawBytes(true),
hashedToCurveR.toRawBytes(true),
]);
return js_sha256_1.sha256.create().update(preimage).hex();
}
exports.computeC_V2 = computeC_V2;
function computeC_V1(pkBytes, hashedToCurve, nullifier, rPoint, hashedToCurveR) {
var nullifierBytes = nullifier.toRawBytes(true);
var preimage = (0, encoding_1.concatUint8Arrays)([
secp256k1_1.Point.BASE.toRawBytes(true),
pkBytes,
new secp256k1_1.Point((0, encoding_1.hexToBigInt)(hashedToCurve.x.toString()), (0, encoding_1.hexToBigInt)(hashedToCurve.y.toString())).toRawBytes(true),
nullifierBytes,
rPoint.toRawBytes(true),
hashedToCurveR.toRawBytes(true),
]);
return js_sha256_1.sha256.create().update(preimage).hex();
}
exports.computeC_V1 = computeC_V1;
function computeNullifer(hashedToCurve, sk) {
return (0, curve_1.multiplyPoint)(hashedToCurve, sk);
}
exports.computeNullifer = computeNullifer;
function computeRPoint(rScalar) {
return secp256k1_1.Point.fromPrivateKey(rScalar);
}
exports.computeRPoint = computeRPoint;
function computeHashToCurveR(hashedToCurve, rScalar) {
return (0, curve_1.multiplyPoint)(hashedToCurve, rScalar);
}
exports.computeHashToCurveR = computeHashToCurveR;
function computeS(rScalar, sk, c) {
return (((((0, encoding_1.uint8ArrayToBigInt)(sk) * (0, encoding_1.hexToBigInt)(c)) % secp256k1_1.CURVE.n) +
(0, encoding_1.uint8ArrayToBigInt)(rScalar)) %
secp256k1_1.CURVE.n).toString(16);
}
exports.computeS = computeS;
/**
* Computes and returns the Plume and other signals for the prover.
* @param {string | Uint8Array} message - Message to sign, in either string or UTF-8 array format.
* @param {string | Uint8Array} sk - ECDSA secret key to sign with.
* @param {string| Uint8Array} rScalar - Optional seed for randomness.
* @returns Object containing Plume and other signals - public key, s, c, gPowR, and hashMPKPowR.
*/
function computeAllInputs(message, sk, rScalar, version) {
if (version === void 0) { version = PlumeVersion.V2; }
var skBytes = typeof sk === "string" ? (0, encoding_1.hexToUint8Array)(sk) : sk;
var messageBytes = typeof message === "string" ? (0, encoding_1.messageToUint8Array)(message) : message;
var pkBytes = (0, secp256k1_1.getPublicKey)(skBytes, true);
var rScalarBytes;
if (rScalar) {
rScalarBytes =
typeof rScalar === "string" ? (0, encoding_1.hexToUint8Array)(rScalar) : rScalar;
}
else {
rScalarBytes = secp256k1_1.utils.randomPrivateKey();
}
var hashedToCurve = computeHashToCurve(messageBytes, pkBytes);
var nullifier = computeNullifer(hashedToCurve, skBytes);
var hashedToCurveR = computeHashToCurveR(hashedToCurve, rScalarBytes);
var rPoint = computeRPoint(rScalarBytes);
var c = version == PlumeVersion.V1
? computeC_V1(pkBytes, hashedToCurve, nullifier, rPoint, hashedToCurveR)
: computeC_V2(nullifier, rPoint, hashedToCurveR);
var s = computeS(rScalarBytes, skBytes, c);
return {
plume: nullifier,
s: s,
pk: pkBytes,
c: c,
rPoint: rPoint,
hashedToCurveR: hashedToCurveR,
};
}
exports.computeAllInputs = computeAllInputs;
10 changes: 10 additions & 0 deletions javascript/src/utils/curve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.multiplyPoint = void 0;
var secp256k1_1 = require("@noble/secp256k1");
var encoding_1 = require("./encoding");
function multiplyPoint(h, secretKey) {
var hashPoint = new secp256k1_1.Point(BigInt("0x" + h.x.toString()), BigInt("0x" + h.y.toString()));
return hashPoint.multiply(BigInt("0x" + (0, encoding_1.uint8ArrayToHex)(secretKey)));
}
exports.multiplyPoint = multiplyPoint;
52 changes: 52 additions & 0 deletions javascript/src/utils/encoding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.concatUint8Arrays = exports.asciitobytes = exports.uint8ArrayToBigInt = exports.hexToBigInt = exports.uint8ArrayToHex = exports.hexToUint8Array = exports.messageToUint8Array = void 0;
var utf8Encoder = new TextEncoder();
function messageToUint8Array(message) {
return utf8Encoder.encode(message);
}
exports.messageToUint8Array = messageToUint8Array;
function hexToUint8Array(hexString) {
// Source: https://stackoverflow.com/questions/38987784/how-to-convert-a-hexadecimal-string-to-uint8array-and-back-in-javascript/50868276#50868276
return Uint8Array.from(hexString.match(/.{1,2}/g).map(function (byte) { return parseInt(byte, 16); }));
}
exports.hexToUint8Array = hexToUint8Array;
function uint8ArrayToHex(uint8Array) {
// Source: https://stackoverflow.com/questions/38987784/how-to-convert-a-hexadecimal-string-to-uint8array-and-back-in-javascript/50868276#50868276
return uint8Array.reduce(function (str, byte) { return str + byte.toString(16).padStart(2, "0"); }, "");
}
exports.uint8ArrayToHex = uint8ArrayToHex;
function hexToBigInt(hex) {
return BigInt("0x" + hex);
}
exports.hexToBigInt = hexToBigInt;
function uint8ArrayToBigInt(buffer) {
return hexToBigInt(uint8ArrayToHex(buffer));
}
exports.uint8ArrayToBigInt = uint8ArrayToBigInt;
function asciitobytes(s) {
var b = [];
for (var i = 0; i < s.length; i++) {
b.push(s.charCodeAt(i));
}
return b;
}
exports.asciitobytes = asciitobytes;
function concatUint8Arrays(arrays) {
// sum of individual array lengths
var totalLength = arrays.reduce(function (acc, value) { return acc + value.length; }, 0);
var result = new Uint8Array(totalLength);
if (!arrays.length) {
return result;
}
// for each array - copy it over result
// next array is copied right after the previous one
var length = 0;
for (var _i = 0, arrays_1 = arrays; _i < arrays_1.length; _i++) {
var array = arrays_1[_i];
result.set(array, length);
length += array.length;
}
return result;
}
exports.concatUint8Arrays = concatUint8Arrays;
47 changes: 47 additions & 0 deletions javascript/src/utils/hashToCurve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var amcl_js_1 = require("amcl-js");
var encoding_1 = require("./encoding");
// Refactored from miracl-core
var ctx = new amcl_js_1.CTX("SECP256K1");
var ro = "QUUX-V01-CS02-with-secp256k1_XMD:SHA-256_SSWU_RO_";
var hlen = ctx.ECP.HASH_TYPE;
function ceil(a, b) {
return Math.floor((a - 1) / b + 1);
}
function hashToField(ctx, hash, hlen, DST, M, ctr) {
var u = [];
var q = new ctx.BIG(0);
q.rcopy(ctx.ROM_FIELD.Modulus);
var k = q.nbits();
var r = new ctx.BIG(0);
r.rcopy(ctx.ROM_CURVE.CURVE_Order);
var m = r.nbits();
var L = ceil(k + ceil(m, 2), 8);
var OKM = ctx.HMAC.XMD_Expand(hash, hlen, L * ctr, DST, M);
var fd = [];
for (var i = 0; i < ctr; i++) {
for (var j = 0; j < L; j++) {
fd[j] = OKM[i * L + j];
}
var dx = ctx.DBIG.fromBytes(fd);
var w = new ctx.FP(dx.mod(q));
u[i] = new ctx.FP(w);
}
return u;
}
// Taken from https://github.com/miracl/core/blob/master/javascript/examples/node/TestHTP.js#L37
function hashToPairing(ctx, M, ro, hlen) {
var DSTRO = (0, encoding_1.asciitobytes)(ro);
var u = hashToField(ctx, ctx.HMAC.MC_SHA2, hlen, DSTRO, M, 2);
var P = ctx.ECP.map2point(u[0]);
var P1 = ctx.ECP.map2point(u[1]);
P.add(P1);
P.cfp();
P.affine();
return P;
}
function hashToCurve(bytes) {
return hashToPairing(ctx, bytes, ro, hlen);
}
exports.default = hashToCurve;
20 changes: 20 additions & 0 deletions javascript/test/consts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.s_v2 = exports.c_v2 = exports.s_v1 = exports.c_v1 = exports.rPoint = exports.hashedToCurveR = exports.nullifier = exports.hashMPk = exports.testMessage = exports.testMessageString = exports.testR = exports.testPublicKey = exports.testPublicKeyPoint = exports.testSecretKey = void 0;
var secp256k1_1 = require("@noble/secp256k1");
var signals_1 = require("../src/signals");
var encoding_1 = require("../src/utils/encoding");
exports.testSecretKey = (0, encoding_1.hexToUint8Array)("519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464");
exports.testPublicKeyPoint = secp256k1_1.Point.fromPrivateKey(exports.testSecretKey);
exports.testPublicKey = (0, secp256k1_1.getPublicKey)(exports.testSecretKey, true);
exports.testR = (0, encoding_1.hexToUint8Array)("93b9323b629f251b8f3fc2dd11f4672c5544e8230d493eceea98a90bda789808");
exports.testMessageString = "An example app message string";
exports.testMessage = (0, encoding_1.messageToUint8Array)(exports.testMessageString);
exports.hashMPk = (0, signals_1.computeHashToCurve)(exports.testMessage, Buffer.from(exports.testPublicKey));
exports.nullifier = (0, signals_1.computeNullifer)(exports.hashMPk, exports.testSecretKey);
exports.hashedToCurveR = (0, signals_1.computeHashToCurveR)(exports.hashMPk, exports.testR);
exports.rPoint = (0, signals_1.computeRPoint)(exports.testR);
exports.c_v1 = (0, signals_1.computeC_V1)(exports.testPublicKey, exports.hashMPk, exports.nullifier, exports.rPoint, exports.hashedToCurveR);
exports.s_v1 = (0, signals_1.computeS)(exports.testR, exports.testSecretKey, exports.c_v1);
exports.c_v2 = (0, signals_1.computeC_V2)(exports.nullifier, exports.rPoint, exports.hashedToCurveR);
exports.s_v2 = (0, signals_1.computeS)(exports.testR, exports.testSecretKey, exports.c_v2);

0 comments on commit c17de76

Please sign in to comment.