in src/paillier.c [31:117]
void PAILLIER_KEY_PAIR(csprng *RNG, const octet *P, const octet* Q, PAILLIER_public_key *PUB, PAILLIER_private_key *PRIV)
{
char oct[FS_2048];
octet OCT = {0, FS_2048, oct};
BIG_1024_58 n[FFLEN_2048];
/* Private key */
if (RNG!=NULL)
{
// p
FF_2048_random(PRIV->p, RNG, HFLEN_2048);
while (FF_2048_lastbits(PRIV->p, 2) != 3)
{
FF_2048_inc(PRIV->p, 1, HFLEN_2048);
}
while (!FF_2048_prime(PRIV->p, RNG, HFLEN_2048))
{
FF_2048_inc(PRIV->p, 4, HFLEN_2048);
}
// q
FF_2048_random(PRIV->q, RNG, HFLEN_2048);
while (FF_2048_lastbits(PRIV->q, 2) != 3)
{
FF_2048_inc(PRIV->q, 1, HFLEN_2048);
}
while (!FF_2048_prime(PRIV->q, RNG, HFLEN_2048))
{
FF_2048_inc(PRIV->q, 4, HFLEN_2048);
}
}
else
{
FF_2048_fromOctet(PRIV->p, P, HFLEN_2048);
FF_2048_fromOctet(PRIV->q, Q, HFLEN_2048);
}
// lp = p-1, lq = q-1
FF_2048_copy(PRIV->lp, PRIV->p, HFLEN_2048);
FF_2048_copy(PRIV->lq, PRIV->q, HFLEN_2048);
FF_2048_dec(PRIV->lp, 1, HFLEN_2048);
FF_2048_dec(PRIV->lq, 1, HFLEN_2048);
/* Precomputations for Secret Key */
// p^{-1}, q^{-1} mod 2^m for division trick
FF_2048_zero(PRIV->invp, FFLEN_2048);
FF_2048_zero(PRIV->invq, FFLEN_2048);
FF_2048_invmod2m(PRIV->invp, PRIV->p, HFLEN_2048);
FF_2048_invmod2m(PRIV->invq, PRIV->q, HFLEN_2048);
// p^2, q^2
FF_2048_sqr(PRIV->p2, PRIV->p, HFLEN_2048);
FF_2048_sqr(PRIV->q2, PRIV->q, HFLEN_2048);
FF_2048_norm(PRIV->p2, FFLEN_2048);
FF_2048_norm(PRIV->q2, FFLEN_2048);
// mp = (((g^(p-1) mod p^2) -1) / p)^(-1) mod p
// Using g = n+1, g^(p-1) = 1 + n(p-1) mod p^2, i.e.
// mp = (n(p-1)/p)^(-1) = -q^(-1) mod p
// (-q)^(-1) mod p
FF_2048_invmodp(PRIV->mp, PRIV->q, PRIV->p, HFLEN_2048);
FF_2048_sub(PRIV->mp, PRIV->p, PRIV->mp, HFLEN_2048);
FF_2048_norm(PRIV->mp, HFLEN_2048);
// (-p)^(-1) mod q
// Also use this to precompute p^(-1) mod q
FF_2048_invmodp(PRIV->invpq, PRIV->p, PRIV->q, HFLEN_2048);
FF_2048_sub(PRIV->mq, PRIV->q, PRIV->invpq, HFLEN_2048);
FF_2048_norm(PRIV->mq, HFLEN_2048);
/* Public Key */
// n
FF_2048_mul(n, PRIV->p, PRIV->q, HFLEN_2048);
FF_2048_toOctet(&OCT, n, FFLEN_2048);
FF_4096_zero(PUB->n, FFLEN_4096);
FF_4096_fromOctet(PUB->n, &OCT, HFLEN_4096);
OCT_empty(&OCT);
// Precompute n^2 for public key
FF_4096_sqr(PUB->n2, PUB->n, HFLEN_4096);
FF_4096_norm(PUB->n2, FFLEN_4096);
}