void PAILLIER_DECRYPT()

in src/paillier.c [185:245]


void PAILLIER_DECRYPT(PAILLIER_private_key *PRIV, const octet* CT, octet* PT)
{
    // Chiphertext
    BIG_1024_58 ct[2 * FFLEN_2048];

    // Plaintext
    BIG_1024_58 pt[FFLEN_2048];
    BIG_1024_58 ptp[HFLEN_2048];
    BIG_1024_58 ptq[HFLEN_2048];

    // Work space
    BIG_1024_58 ws[FFLEN_2048];
    BIG_1024_58 dws[2 * FFLEN_2048];

    FF_2048_fromOctet(ct, CT, 2 * FFLEN_2048);

    /* Decryption modulo p */

    FF_2048_dmod(ws, ct, PRIV->p2, FFLEN_2048);

    // Compute ws = (ct^lp mod p2 - 1)
    FF_2048_ct_pow(ws, ws, PRIV->lp, PRIV->p2, FFLEN_2048, HFLEN_2048);
    FF_2048_dec(ws, 1, FFLEN_2048);

    // dws = ws / p
    // Division by p using the inverse mod 2^m trick
    FF_2048_mul(dws, ws, PRIV->invp, FFLEN_2048);

    // ptp = dws * mp mod p
    FF_2048_mul(ws, dws, PRIV->mp, HFLEN_2048);
    FF_2048_dmod(ptp, ws, PRIV->p, HFLEN_2048);

    /* Decryption modulo q */

    FF_2048_dmod(ws, ct, PRIV->q2, FFLEN_2048);

    // Compute ws = (ct^lq mod q2 - 1)
    FF_2048_ct_pow(ws, ws, PRIV->lq, PRIV->q2, FFLEN_2048, HFLEN_2048);
    FF_2048_dec(ws, 1, FFLEN_2048);

    // dws = ws / q
    // Division by q using the inverse mod 2^m trick
    FF_2048_mul(dws, ws, PRIV->invq, FFLEN_2048);

    // ptq = dws * mq mod q
    FF_2048_mul(ws, dws, PRIV->mq, HFLEN_2048);
    FF_2048_dmod(ptq, ws, PRIV->q, HFLEN_2048);

    /* Combine results using CRT */
    FF_2048_mul(ws, PRIV->p, PRIV->q, HFLEN_2048);
    FF_2048_crt(pt, ptp, ptq, PRIV->p, PRIV->invpq, ws, HFLEN_2048);

    // Output
    FF_2048_toOctet(PT, pt, FFLEN_2048);

    // Clean memory
    FF_2048_zero(pt,  FFLEN_2048);
    FF_2048_zero(ptp, HFLEN_2048);
    FF_2048_zero(ptq, HFLEN_2048);
    FF_2048_zero(dws, 2 * FFLEN_2048);
}