import { generate_prime } from "./random_primes.js";
import { mod_exp, mod_inv } from "./math.js";

export class RsaPubKey {
    constructor(n, e) {
        this.n = n;
        this.e = e;
    }

    encrypt(m) {
        return mod_exp(m, this.e, this.n);
    }

    toJSON() {
        return {
            n: "0x" + this.n.toString(16),
            e: "0x" + this.e.toString(16),
        };
    }

    static fromJSON(data) {
        return new RsaPubKey(BigInt(data.n), BigInt(data.e));
    }
}

class RsaPrivKey {
    constructor(p, q) {
        this.n = p * q;
        this.d = mod_inv(65537n, (q - 1n) * (p - 1n));
    }

    decrypt(c) {
        return mod_exp(c, this.d, this.n);
    }
}

export function generate_rsa_keypair() {
    let p, q, pubKey, privKey;

    if (window.sessionStorage.getItem("rsa_p") === null) {
        p = generate_prime();
        window.sessionStorage.setItem("rsa_p", p);
    } else {
        p = BigInt(window.sessionStorage.getItem("rsa_p"));
    }

    if (window.sessionStorage.getItem("rsa_q") === null) {
        q = generate_prime();
        window.sessionStorage.setItem("rsa_q", q);
    } else {
        q = BigInt(window.sessionStorage.getItem("rsa_q"));
    }

    pubKey = new RsaPubKey(p * q, 65537n);
    privKey = new RsaPrivKey(p, q);

    return { pubKey, privKey };
}
