@waku/rln
Version:
RLN (Rate Limiting Nullifier) implementation for Waku
77 lines (74 loc) • 3.15 kB
JavaScript
import { EC as EC$1 } from './elliptic.js';
import { splitSignature, arrayify, hexlify, hexDataLength, hexZeroPad } from '../../bytes/lib.esm/index.js';
import { defineReadOnly } from '../../properties/lib.esm/index.js';
import { Logger } from '../../logger/lib.esm/index.js';
import { version } from './_version.js';
const logger = new Logger(version);
let _curve = null;
function getCurve() {
if (!_curve) {
_curve = new EC$1("secp256k1");
}
return _curve;
}
class SigningKey {
constructor(privateKey) {
defineReadOnly(this, "curve", "secp256k1");
defineReadOnly(this, "privateKey", hexlify(privateKey));
if (hexDataLength(this.privateKey) !== 32) {
logger.throwArgumentError("invalid private key", "privateKey", "[[ REDACTED ]]");
}
const keyPair = getCurve().keyFromPrivate(arrayify(this.privateKey));
defineReadOnly(this, "publicKey", "0x" + keyPair.getPublic(false, "hex"));
defineReadOnly(this, "compressedPublicKey", "0x" + keyPair.getPublic(true, "hex"));
defineReadOnly(this, "_isSigningKey", true);
}
_addPoint(other) {
const p0 = getCurve().keyFromPublic(arrayify(this.publicKey));
const p1 = getCurve().keyFromPublic(arrayify(other));
return "0x" + p0.pub.add(p1.pub).encodeCompressed("hex");
}
signDigest(digest) {
const keyPair = getCurve().keyFromPrivate(arrayify(this.privateKey));
const digestBytes = arrayify(digest);
if (digestBytes.length !== 32) {
logger.throwArgumentError("bad digest length", "digest", digest);
}
const signature = keyPair.sign(digestBytes, { canonical: true });
return splitSignature({
recoveryParam: signature.recoveryParam,
r: hexZeroPad("0x" + signature.r.toString(16), 32),
s: hexZeroPad("0x" + signature.s.toString(16), 32),
});
}
computeSharedSecret(otherKey) {
const keyPair = getCurve().keyFromPrivate(arrayify(this.privateKey));
const otherKeyPair = getCurve().keyFromPublic(arrayify(computePublicKey(otherKey)));
return hexZeroPad("0x" + keyPair.derive(otherKeyPair.getPublic()).toString(16), 32);
}
static isSigningKey(value) {
return !!(value && value._isSigningKey);
}
}
function recoverPublicKey(digest, signature) {
const sig = splitSignature(signature);
const rs = { r: arrayify(sig.r), s: arrayify(sig.s) };
return "0x" + getCurve().recoverPubKey(arrayify(digest), rs, sig.recoveryParam).encode("hex", false);
}
function computePublicKey(key, compressed) {
const bytes = arrayify(key);
if (bytes.length === 32) {
const signingKey = new SigningKey(bytes);
return signingKey.publicKey;
}
else if (bytes.length === 33) {
return "0x" + getCurve().keyFromPublic(bytes).getPublic(false, "hex");
}
else if (bytes.length === 65) {
{
return hexlify(bytes);
}
}
return logger.throwArgumentError("invalid public or private key", "key", "[REDACTED]");
}
export { SigningKey, computePublicKey, recoverPublicKey };