"use strict";
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 PrivateKey_js_1 = __importDefault(require("./PrivateKey.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 = PrivateKey_js_1.default.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