Skip to content

Commit

Permalink
_JS_ is done
Browse files Browse the repository at this point in the history
  • Loading branch information
skaunov committed Oct 19, 2023
1 parent fde8e40 commit 70a56f8
Show file tree
Hide file tree
Showing 4 changed files with 4,237 additions and 2,599 deletions.
105 changes: 49 additions & 56 deletions javascript/src/signals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,115 +16,108 @@ export enum PlumeVersion {
V2,
}

export function computeHashMPk(
export function computeHashToCurve(
message: Uint8Array,
publicKey: Uint8Array
pk: Uint8Array
): HashedPoint {
// Concatenate message and publicKey
const preimage = new Uint8Array(message.length + publicKey.length);
const preimage = new Uint8Array(message.length + pk.length);
preimage.set(message);
preimage.set(publicKey, message.length);
preimage.set(pk, message.length);
return hashToCurve(Array.from(preimage));
}

export function computeC_V2(
nullifier: Point,
gPowR: Point,
hashMPkPowR: Point
rPoint: Point,
hashedToCurveR: Point
) {
const nullifierBytes = nullifier.toRawBytes(true);
const gPowRBytes = gPowR.toRawBytes(true);
const hashMPkPowRBytes = hashMPkPowR.toRawBytes(true);
const preimage = concatUint8Arrays([
nullifierBytes,
gPowRBytes,
hashMPkPowRBytes,
rPoint.toRawBytes(true),
hashedToCurveR.toRawBytes(true),
]);
return sha256.create().update(preimage).hex();
}

export function computeC_V1(
publicKeyBytes: Uint8Array,
hashMPk: HashedPoint,
pkBytes: Uint8Array,
hashedToCurve: HashedPoint,
nullifier: Point,
gPowR: Point,
hashMPkPowR: Point
rPoint: Point,
hashedToCurveR: Point
) {
const gBytes = Point.BASE.toRawBytes(true);
const hashMPkBytes = new Point(
hexToBigInt(hashMPk.x.toString()),
hexToBigInt(hashMPk.y.toString())
).toRawBytes(true);
const nullifierBytes = nullifier.toRawBytes(true);
const gPowRBytes = gPowR.toRawBytes(true);
const hashMPkPowRBytes = hashMPkPowR.toRawBytes(true);
const preimage = concatUint8Arrays([
gBytes,
publicKeyBytes,
hashMPkBytes,
Point.BASE.toRawBytes(true),
pkBytes,
new Point(
hexToBigInt(hashedToCurve.x.toString()),
hexToBigInt(hashedToCurve.y.toString())
).toRawBytes(true),
nullifierBytes,
gPowRBytes,
hashMPkPowRBytes,
rPoint.toRawBytes(true),
hashedToCurveR.toRawBytes(true),
]);
return sha256.create().update(preimage).hex();
}

export function computeNullifer(hashMPk: HashedPoint, secretKey: Uint8Array) {
return multiplyPoint(hashMPk, secretKey);
export function computeNullifer(hashedToCurve: HashedPoint, sk: Uint8Array) {
return multiplyPoint(hashedToCurve, sk);
}

export function computeGPowR(r: Uint8Array) {
return Point.fromPrivateKey(r);
export function computeRPoint(rScalar: Uint8Array) {
return Point.fromPrivateKey(rScalar);
}

export function computeHashMPkPowR(hashMPk: HashedPoint, r: Uint8Array) {
return multiplyPoint(hashMPk, r);
export function computeHashToCurveR(hashedToCurve: HashedPoint, rScalar: Uint8Array) {
return multiplyPoint(hashedToCurve, rScalar);
}

export function computeS(r: Uint8Array, secretKey: Uint8Array, c: string) {
const skC = (uint8ArrayToBigInt(secretKey) * hexToBigInt(c)) % CURVE.n;
return ((skC + uint8ArrayToBigInt(r)) % CURVE.n).toString(16);
export function computeS(rScalar: Uint8Array, sk: Uint8Array, c: string) {
return (((uint8ArrayToBigInt(sk) * hexToBigInt(c)) % CURVE.n + uint8ArrayToBigInt(rScalar)) % CURVE.n).toString(16);
}

/**
* 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} secretKey - ECDSA secret key to sign with.
* @param {string| Uint8Array} r - Optional seed for randomness.
* @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.
*/
export function computeAllInputs(
message: string | Uint8Array,
secretKey: string | Uint8Array,
r?: string | Uint8Array,
sk: string | Uint8Array,
rScalar?: string | Uint8Array,
version: PlumeVersion = PlumeVersion.V2
) {
const secretKeyBytes =
typeof secretKey === "string" ? hexToUint8Array(secretKey) : secretKey;
const skBytes =
typeof sk === "string" ? hexToUint8Array(sk) : sk;
const messageBytes =
typeof message === "string" ? messageToUint8Array(message) : message;
const publicKeyBytes = getPublicKey(secretKeyBytes, true);
let rBytes;
if (r) {
rBytes = typeof r === "string" ? hexToUint8Array(r) : r;
const pkBytes = getPublicKey(skBytes, true);
let rScalarBytes;
if (rScalar) {
rScalarBytes = typeof rScalar === "string" ? hexToUint8Array(rScalar) : rScalar;
} else {
rBytes = utils.randomPrivateKey();
rScalarBytes = utils.randomPrivateKey();
}
const hashMPK = computeHashMPk(messageBytes, publicKeyBytes);
const nullifier = computeNullifer(hashMPK, secretKeyBytes);
const hashMPKPowR = computeHashMPkPowR(hashMPK, rBytes);
const gPowR = computeGPowR(rBytes);
const hashedToCurve = computeHashToCurve(messageBytes, pkBytes);
const nullifier = computeNullifer(hashedToCurve, skBytes);
const hashedToCurveR = computeHashToCurveR(hashedToCurve, rScalarBytes);
const rPoint = computeRPoint(rScalarBytes);
const c =
version == PlumeVersion.V1
? computeC_V1(publicKeyBytes, hashMPK, nullifier, gPowR, hashMPKPowR)
: computeC_V2(nullifier, gPowR, hashMPKPowR);
const s = computeS(rBytes, secretKeyBytes, c);
? computeC_V1(pkBytes, hashedToCurve, nullifier, rPoint, hashedToCurveR)
: computeC_V2(nullifier, rPoint, hashedToCurveR);
const s = computeS(rScalarBytes, skBytes, c);
return {
plume: nullifier,
s,
publicKey: publicKeyBytes,
pk: pkBytes,
c,
gPowR,
hashMPKPowR,
rPoint,
hashedToCurveR,
};
}
24 changes: 12 additions & 12 deletions javascript/test/signals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ describe("signals", () => {
});

it("generates all signals", () => {
const { plume, s, publicKey, c, gPowR, hashMPKPowR } = computeAllInputs(
const { plume, s, pk, c, rPoint, hashedToCurveR } = computeAllInputs(
testMessage,
testSecretKey,
testR,
PlumeVersion.V1,
);
expect(publicKey).toEqual(testPublicKey);
expect(gPowR.x.toString(16)).toEqual(
expect(pk).toEqual(testPublicKey);
expect(rPoint.x.toString(16)).toEqual(
"9d8ca4350e7e2ad27abc6d2a281365818076662962a28429590e2dc736fe9804"
);
expect(gPowR.y.toString(16)).toEqual(
expect(rPoint.y.toString(16)).toEqual(
"ff08c30b8afd4e854623c835d9c3aac6bcebe45112472d9b9054816a7670c5a1"
);
expect(plume.x.toString(16)).toEqual(
Expand All @@ -81,7 +81,7 @@ describe("signals", () => {
expect(plume.y.toString(16)).toEqual(
"6a2f41488d58f33ae46edd2188e111609f9f3ae67ea38fa891d6087fe59ecb73"
);
expect(hashMPKPowR.x.toString(16)).toEqual(
expect(hashedToCurveR.x.toString(16)).toEqual(
"6d017c6f63c59fa7a5b1e9a654e27d2869579f4d152131db270558fccd27b97c"
);
expect(c).toEqual(
Expand All @@ -90,7 +90,7 @@ describe("signals", () => {
expect(s).toEqual(
"e69f027d84cb6fe5f761e333d12e975fb190d163e8ea132d7de0bd6079ba28ca"
);
expect(hashMPKPowR.y.toString(16)).toEqual(
expect(hashedToCurveR.y.toString(16)).toEqual(
"586c43fb5c99818c564a8f80a88a65f83e3f44d3c6caf5a1a4e290b777ac56ed"
);
});
Expand Down Expand Up @@ -124,17 +124,17 @@ describe("signals", () => {
});

it("generates all signals", () => {
const { plume, s, publicKey, c, gPowR, hashMPKPowR } = computeAllInputs(
const { plume, s, pk, c, rPoint, hashedToCurveR } = computeAllInputs(
testMessage,
testSecretKey,
testR,
PlumeVersion.V2
);
expect(publicKey).toEqual(testPublicKey);
expect(gPowR.x.toString(16)).toEqual(
expect(pk).toEqual(testPublicKey);
expect(rPoint.x.toString(16)).toEqual(
"9d8ca4350e7e2ad27abc6d2a281365818076662962a28429590e2dc736fe9804"
);
expect(gPowR.y.toString(16)).toEqual(
expect(rPoint.y.toString(16)).toEqual(
"ff08c30b8afd4e854623c835d9c3aac6bcebe45112472d9b9054816a7670c5a1"
);
expect(plume.x.toString(16)).toEqual(
Expand All @@ -143,7 +143,7 @@ describe("signals", () => {
expect(plume.y.toString(16)).toEqual(
"6a2f41488d58f33ae46edd2188e111609f9f3ae67ea38fa891d6087fe59ecb73"
);
expect(hashMPKPowR.x.toString(16)).toEqual(
expect(hashedToCurveR.x.toString(16)).toEqual(
"6d017c6f63c59fa7a5b1e9a654e27d2869579f4d152131db270558fccd27b97c"
);
expect(c).toEqual(
Expand All @@ -152,7 +152,7 @@ describe("signals", () => {
expect(s).toEqual(
"528e8fbb6452f82200797b1a73b2947a92524bd611085a920f1177cb8098136b"
);
expect(hashMPKPowR.y.toString(16)).toEqual(
expect(hashedToCurveR.y.toString(16)).toEqual(
"586c43fb5c99818c564a8f80a88a65f83e3f44d3c6caf5a1a4e290b777ac56ed"
);
});
Expand Down
12 changes: 6 additions & 6 deletions javascript/test/test_consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { CURVE, getPublicKey, Point } from "@noble/secp256k1";
import {
computeC_V1,
computeC_V2,
computeGPowR,
computeHashMPk,
computeHashMPkPowR,
computeRPoint,
computeHashToCurve,
computeHashToCurveR,
computeNullifer,
computeS,
} from "../src/signals";
Expand All @@ -22,10 +22,10 @@ export const testR = hexToUint8Array(
);
export const testMessageString = "An example app message string";
export const testMessage = messageToUint8Array(testMessageString);
export const hashMPk = computeHashMPk(testMessage, Buffer.from(testPublicKey));
export const hashMPk = computeHashToCurve(testMessage, Buffer.from(testPublicKey));
export const nullifier = computeNullifer(hashMPk, testSecretKey);
export const hashMPkPowR = computeHashMPkPowR(hashMPk, testR);
export const gPowR = computeGPowR(testR);
export const hashMPkPowR = computeHashToCurveR(hashMPk, testR);
export const gPowR = computeRPoint(testR);
export const c_v1 = computeC_V1(
testPublicKey,
hashMPk,
Expand Down
Loading

0 comments on commit 70a56f8

Please sign in to comment.