@bsv/sdk
Version:
BSV Blockchain Software Development Kit
98 lines • 3.85 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const BigNumber_js_1 = __importDefault(require("./BigNumber.js"));
const Curve_js_1 = __importDefault(require("./Curve.js"));
const Hash_js_1 = require("./Hash.js");
const index_js_1 = require("./index.js");
/**
* Class representing the Schnorr Zero-Knowledge Proof (ZKP) protocol.
*
* This class provides methods to generate and verify proofs that demonstrate knowledge of a secret without revealing it.
* Specifically, it allows one party to prove to another that they know the private key corresponding to a public key
* and have correctly computed a shared secret, without disclosing the private key itself.
*
* The protocol involves two main methods:
* - `generateProof`: Generates a proof linking a public key `A` and a shared secret `S`, proving knowledge of the corresponding private key `a`.
* - `verifyProof`: Verifies the provided proof, ensuring its validity without revealing any secret information.
*
* The class utilizes elliptic curve cryptography (ECC) and the SHA-256 hash function to compute challenges within the proof.
*
* @example
* ```typescript
* const schnorr = new Schnorr();
* const a = PrivateKey.fromRandom(); // Prover's private key
* const A = a.toPublicKey(); // Prover's public key
* const b = PrivateKey.fromRandom(); // Other party's private key
* const B = b.toPublicKey(); // Other party's public key
* const S = B.mul(a); // Shared secret
*
* // Prover generates the proof
* const proof = schnorr.generateProof(a, A, B, S);
*
* // Verifier verifies the proof
* const isValid = schnorr.verifyProof(A.point, B.point, S.point, proof);
* console.log(`Proof is valid: ${isValid}`);
* ```
*/
class Schnorr {
constructor() {
this.curve = new Curve_js_1.default();
}
/**
* Generates a proof that demonstrates the link between public key A and shared secret S
* @param a Private key corresponding to public key A
* @param A Public key
* @param B Other party's public key
* @param S Shared secret
* @returns Proof (R, S', z)
*/
generateProof(aArg, AArg, BArg, S) {
const r = index_js_1.PrivateKey.fromRandom();
const R = r.toPublicKey();
const SPrime = BArg.mul(r);
const e = this.computeChallenge(AArg, BArg, S, SPrime, R);
const z = r.add(e.mul(aArg)).umod(this.curve.n);
return { R, SPrime, z };
}
/**
* Verifies the proof of the link between public key A and shared secret S
* @param A Public key
* @param B Other party's public key
* @param S Shared secret
* @param proof Proof (R, S', z)
* @returns True if the proof is valid, false otherwise
*/
verifyProof(A, B, S, proof) {
const { R, SPrime, z } = proof;
const e = this.computeChallenge(A, B, S, SPrime, R);
// Check zG = R + eA
const zG = this.curve.g.mul(z);
const RpluseA = R.add(A.mul(e));
if (!zG.eq(RpluseA)) {
return false;
}
// Check zB = S' + eS
const zB = B.mul(z);
const SprimeeS = SPrime.add(S.mul(e));
if (!zB.eq(SprimeeS)) {
return false;
}
return true;
}
computeChallenge(A, B, S, SPrime, R) {
const message = [
...A.encode(true),
...B.encode(true),
...S.encode(true),
...SPrime.encode(true),
...R.encode(true)
];
const hash = (0, Hash_js_1.sha256)(message);
return new BigNumber_js_1.default(hash).umod(this.curve.n);
}
}
exports.default = Schnorr;
//# sourceMappingURL=Schnorr.js.map