Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Use new trick in paillier ecnryption and keygen #77

Merged
merged 2 commits into from Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions examples/example_paillier.c
Expand Up @@ -107,9 +107,6 @@ int paillier(csprng *RNG)
printf("N: ");
FF_4096_output(PUB.n, HFLEN_4096);
printf("\n");
printf("G: ");
FF_4096_output(PUB.g, FFLEN_4096);
printf("\n");

printf("Secret Key \n");
printf("L_p: ");
Expand Down
26 changes: 8 additions & 18 deletions include/ff.h.in
Expand Up @@ -291,24 +291,14 @@ extern void FF_WWW_skpow3(BIG_XXX *r,BIG_XXX *x, BIG_XXX *e, BIG_XXX *y, BIG_XXX
extern void FF_WWW_power(BIG_XXX *r,BIG_XXX *x,int e,BIG_XXX *p,int n);
/** @brief Calculate r=x^e mod p
*
@param r FF instance, on exit = x^e mod p
@param x FF instance
@param e FF exponent
@param p FF modulus
@param n size of FF in BIGs
*/
extern void FF_WWW_pow(BIG_XXX *r,BIG_XXX *x,BIG_XXX *e,BIG_XXX *p,int n);
/** @brief Calculate r=x^e.y^f mod m
*
@param r FF instance, on exit = x^e.y^f mod p
@param x FF instance
@param e BIG exponent
@param y FF instance
@param f BIG exponent
@param m FF modulus
@param n size of FF in BIGs
@param r FF instance, on exit = x^e mod p
@param x FF instance
@param e FF exponent
@param p FF modulus
@param n size of base in BIGs
@param en size of exponent in BIGs
*/
extern void FF_WWW_pow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX e,BIG_XXX *y,BIG_XXX f,BIG_XXX *m,int n);
extern void FF_WWW_pow(BIG_XXX *r, BIG_XXX *x, BIG_XXX *e, BIG_XXX *p, int n, int en);
/** @brief Calculate r=x^e.y^f mod p. Faster but non constant time
*
@param r FF instance, on exit = x^e.y^f mod p
Expand All @@ -320,7 +310,7 @@ extern void FF_WWW_pow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX e,BIG_XXX *y,BIG_XXX f,BIG
@param n size of FF in BIGs
@param en size of exponent in BIGs
*/
void FF_WWW_bpow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX *e, BIG_XXX *y, BIG_XXX *f, BIG_XXX *p,int n, int en);
void FF_WWW_pow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX *e, BIG_XXX *y, BIG_XXX *f, BIG_XXX *p,int n, int en);
/** @brief Calculate r=x^e.y^f.z^g mod p. Faster but non constant time
*
@param r FF instance, on exit = x^e.y^f.z^g mod p
Expand Down
4 changes: 1 addition & 3 deletions include/paillier.h
Expand Up @@ -50,9 +50,7 @@ extern "C" {
*/
typedef struct
{
BIG_512_60 n[FFLEN_4096]; /**< Paillier Modulus - \f$ n = pq \f$ */
BIG_512_60 g[FFLEN_4096]; /**< Public Base - \f$ g = n+1 \f$ */

BIG_512_60 n[HFLEN_4096]; /**< Paillier Modulus - \f$ n = pq \f$ */
BIG_512_60 n2[FFLEN_4096]; /**< Precomputed \f$ n^2 \f$ */
} PAILLIER_public_key;

Expand Down
72 changes: 17 additions & 55 deletions src/ff.c.in
Expand Up @@ -766,8 +766,8 @@ static void FF_WWW_modsqr(BIG_XXX z[],BIG_XXX x[],BIG_XXX p[],BIG_XXX ND[],int n
}
}

/* r=x^e mod p using side-channel resistant Montgomery Ladder, for large e */
void FF_WWW_skpow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n, int en)
/* r=x^e mod p using side-channel resistant Montgomery Ladder, for short e */
void FF_WWW_skspow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e,BIG_XXX p[],int n)
{
int i,b;
#ifndef C99
Expand All @@ -776,29 +776,25 @@ void FF_WWW_skpow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n, int en)
BIG_XXX R0[n],R1[n],ND[n];
#endif
FF_WWW_invmod2m(ND,p,n);

FF_WWW_one(R0,n);
FF_WWW_copy(R1,x,n);
FF_WWW_nres(R0,p,n);
FF_WWW_nres(R1,p,n);

for (i=8*MODBYTES_XXX*en-1; i>=0; i--)
for (i=8*MODBYTES_XXX-1; i>=0; i--)
{
b=BIG_XXX_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
b=BIG_XXX_bit(e,i);
FF_WWW_modmul(r,R0,R1,p,ND,n);

FF_WWW_cswap(R0,R1,b,n);
FF_WWW_modsqr(R0,R0,p,ND,n);

FF_WWW_copy(R1,r,n);
FF_WWW_cswap(R0,R1,b,n);
}
FF_WWW_copy(r,R0,n);
FF_WWW_redc(r,p,ND,n);
}

/* r=x^e mod p using side-channel resistant Montgomery Ladder, for short e */
void FF_WWW_skspow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e,BIG_XXX p[],int n)
/* r=x^e mod p using side-channel resistant Montgomery Ladder, for large e */
void FF_WWW_skpow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n, int en)
{
int i,b;
#ifndef C99
Expand All @@ -807,16 +803,20 @@ void FF_WWW_skspow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e,BIG_XXX p[],int n)
BIG_XXX R0[n],R1[n],ND[n];
#endif
FF_WWW_invmod2m(ND,p,n);

FF_WWW_one(R0,n);
FF_WWW_copy(R1,x,n);
FF_WWW_nres(R0,p,n);
FF_WWW_nres(R1,p,n);
for (i=8*MODBYTES_XXX-1; i>=0; i--)

for (i=8*MODBYTES_XXX*en-1; i>=0; i--)
{
b=BIG_XXX_bit(e,i);
b=BIG_XXX_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
FF_WWW_modmul(r,R0,R1,p,ND,n);

FF_WWW_cswap(R0,R1,b,n);
FF_WWW_modsqr(R0,R0,p,ND,n);

FF_WWW_copy(R1,r,n);
FF_WWW_cswap(R0,R1,b,n);
}
Expand Down Expand Up @@ -959,7 +959,7 @@ void FF_WWW_power(BIG_XXX r[],BIG_XXX x[],int e,BIG_XXX p[],int n)
}

/* r=x^e mod p, faster but not side channel resistant */
void FF_WWW_pow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n)
void FF_WWW_pow(BIG_XXX r[], BIG_XXX x[], BIG_XXX e[], BIG_XXX p[], int n, int en)
{
int i,b;
#ifndef C99
Expand All @@ -974,7 +974,7 @@ void FF_WWW_pow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n)
FF_WWW_nres(r,p,n);
FF_WWW_nres(w,p,n);

for (i=8*MODBYTES_XXX*n-1; i>=0; i--)
for (i=8*MODBYTES_XXX*en-1; i>=0; i--)
{
FF_WWW_modsqr(r,r,p,ND,n);
b=BIG_XXX_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
Expand All @@ -983,46 +983,8 @@ void FF_WWW_pow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n)
FF_WWW_redc(r,p,ND,n);
}

/* double exponentiation r=x^e.y^f mod p */
void FF_WWW_pow2(BIG_XXX r[],BIG_XXX x[],BIG_XXX e,BIG_XXX y[],BIG_XXX f,BIG_XXX p[],int n)
{
int i,eb,fb;
#ifndef C99
BIG_XXX xn[FFLEN_WWW],yn[FFLEN_WWW],xy[FFLEN_WWW],ND[FFLEN_WWW];
#else
BIG_XXX xn[n],yn[n],xy[n],ND[n];
#endif

FF_WWW_invmod2m(ND,p,n);

FF_WWW_copy(xn,x,n);
FF_WWW_copy(yn,y,n);
FF_WWW_nres(xn,p,n);
FF_WWW_nres(yn,p,n);
FF_WWW_modmul(xy,xn,yn,p,ND,n);
FF_WWW_one(r,n);
FF_WWW_nres(r,p,n);

for (i=8*MODBYTES_XXX-1; i>=0; i--)
{
eb=BIG_XXX_bit(e,i);
fb=BIG_XXX_bit(f,i);
FF_WWW_modsqr(r,r,p,ND,n);
if (eb==1)
{
if (fb==1) FF_WWW_modmul(r,r,xy,p,ND,n);
else FF_WWW_modmul(r,r,xn,p,ND,n);
}
else
{
if (fb==1) FF_WWW_modmul(r,r,yn,p,ND,n);
}
}
FF_WWW_redc(r,p,ND,n);
}

/* Compute prod(x_i^e_i) mod p. Faster but not constant time */
void FF_WWW_pown(BIG_XXX *r, BIG_XXX *x[], BIG_XXX *e[], BIG_XXX *p, int xlen, int elen, int n)
static void FF_WWW_pown(BIG_XXX *r, BIG_XXX *x[], BIG_XXX *e[], BIG_XXX *p, int xlen, int elen, int n)
{
#ifndef C99
BIG_XXX products[15][FFLEN_WWW], ND[FFLEN_WWW];
Expand Down Expand Up @@ -1080,7 +1042,7 @@ void FF_WWW_pown(BIG_XXX *r, BIG_XXX *x[], BIG_XXX *e[], BIG_XXX *p, int xlen, i
FF_WWW_redc(r, p, ND, xlen);
}

void FF_WWW_bpow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX *e, BIG_XXX *y, BIG_XXX *f, BIG_XXX *p,int n, int en)
void FF_WWW_pow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX *e, BIG_XXX *y, BIG_XXX *f, BIG_XXX *p,int n, int en)
{
BIG_XXX *x_s[] = {x,y};
BIG_XXX *e_s[] = {e,f};
Expand Down Expand Up @@ -1174,7 +1136,7 @@ int FF_WWW_prime(BIG_XXX p[],csprng *rng,int n)
for (i=0; i<10; i++)
{
FF_WWW_randomnum(x,p,rng,n);
FF_WWW_pow(x,x,d,p,n);
FF_WWW_pow(x,x,d,p,n,n);
if (FF_WWW_comp(x,unity,n)==0 || FF_WWW_comp(x,nm1,n)==0) continue;
loop=0;
for (j=1; j<s; j++)
Expand Down
89 changes: 38 additions & 51 deletions src/paillier.c
Expand Up @@ -33,12 +33,7 @@ void PAILLIER_KEY_PAIR(csprng *RNG, octet *P, octet* Q, PAILLIER_public_key *PUB
char oct[FS_2048];
octet OCT = {0, FS_2048, oct};

// Public key
BIG_1024_58 g[FFLEN_2048];

// Workspace for CRT precomputations
BIG_1024_58 ff[FFLEN_2048];
BIG_1024_58 dff[2*FFLEN_2048];
BIG_1024_58 n[FFLEN_2048];

/* Private key */

Expand Down Expand Up @@ -92,44 +87,32 @@ void PAILLIER_KEY_PAIR(csprng *RNG, octet *P, octet* Q, PAILLIER_public_key *PUB
FF_2048_norm(PRIV->p2, FFLEN_2048);
FF_2048_norm(PRIV->q2, FFLEN_2048);

// g = n + 1
FF_2048_mul(g, PRIV->p, PRIV->q, HFLEN_2048);
FF_2048_inc(g, 1, 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

// (((g^(p-1) mod p^2) - 1) / p)^(-1) mod p for dec/enc with CRT
FF_2048_skpow(ff, g, PRIV->lp, PRIV->p2, FFLEN_2048, HFLEN_2048);
FF_2048_dec(ff, 1, FFLEN_2048);
FF_2048_mul(dff, ff, PRIV->invp, FFLEN_2048);
FF_2048_invmodp(PRIV->mp, dff, PRIV->p, HFLEN_2048);
// (-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);

// (((g^(q-1) mod q^2) - 1) / q)^(-1) mod q for dec/enc with CRT
FF_2048_skpow(ff, g, PRIV->lq, PRIV->q2, FFLEN_2048, HFLEN_2048);
FF_2048_dec(ff, 1, FFLEN_2048);
FF_2048_mul(dff, ff, PRIV->invq, FFLEN_2048);
FF_2048_invmodp(PRIV->mq, dff, PRIV->q, HFLEN_2048);
// (-p)^(-1) mod q
FF_2048_invmodp(PRIV->mq, PRIV->p, PRIV->q, HFLEN_2048);
FF_2048_sub(PRIV->mq, PRIV->q, PRIV->mq, HFLEN_2048);
FF_2048_norm(PRIV->mq, HFLEN_2048);

/* Public Key */

// g = n + 1
FF_2048_toOctet(&OCT, g, FFLEN_2048);
FF_4096_zero(PUB->g, FFLEN_4096);
FF_4096_fromOctet(PUB->g, &OCT, HFLEN_4096);
OCT_empty(&OCT);

// n
FF_2048_dec(g, 1, FFLEN_2048);
FF_2048_toOctet(&OCT, g, FFLEN_2048);
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);

// Clean memory
FF_2048_zero(ff, FFLEN_2048);
FF_2048_zero(dff, 2*FFLEN_2048);
}

/* Clean secrets from private key */
Expand All @@ -150,41 +133,49 @@ void PAILLIER_PRIVATE_KEY_KILL(PAILLIER_private_key *PRIV)
// Paillier encryption
void PAILLIER_ENCRYPT(csprng *RNG, PAILLIER_public_key *PUB, octet* PT, octet* CT, octet* R)
{
// Random r < n^2
BIG_512_60 r[FFLEN_4096];

// plaintext
BIG_512_60 pt[HFLEN_4096];

// ciphertext
BIG_512_60 ct[FFLEN_4096];
// workspaces
BIG_512_60 ws1[FFLEN_4096];
BIG_512_60 ws2[FFLEN_4096];
BIG_512_60 dws[2 * FFLEN_4096];

FF_4096_fromOctet(pt,PT,HFLEN_4096);
FF_4096_fromOctet(pt, PT, HFLEN_4096);

// In production generate R from RNG
if (RNG!=NULL)
{
FF_4096_randomnum(r, PUB->n2, RNG,FFLEN_4096);
FF_4096_randomnum(ws1, PUB->n2, RNG,FFLEN_4096);
}
else
{
FF_4096_fromOctet(r, R, FFLEN_4096);
FF_4096_fromOctet(ws1, R, FFLEN_4096);
}

// ct = g^pt * r^n mod n2
FF_4096_skpow2(ct, PUB->g, pt, r, PUB->n, PUB->n2, FFLEN_4096, HFLEN_4096);

// Output
FF_4096_toOctet(CT, ct, FFLEN_4096);

// Output R for Debug
if (R!=NULL)
{
FF_4096_toOctet(R, r, FFLEN_4096);
FF_4096_toOctet(R, ws1, FFLEN_4096);
}

// r^n
FF_4096_pow(ws1, ws1, PUB->n, PUB->n2, FFLEN_4096, HFLEN_4096);

// g^pt = 1 + pt * n
FF_4096_mul(ws2, pt, PUB->n, HFLEN_4096);
FF_4096_inc(ws2, 1, FFLEN_4096);
FF_4096_norm(ws2, FFLEN_4096);

// ct = g^pt * r^n mod n^2
FF_4096_mul(dws, ws1, ws2, FFLEN_4096);
FF_4096_dmod(ws1, dws, PUB->n2, FFLEN_4096);

// Output
FF_4096_toOctet(CT, ws1, FFLEN_4096);

// Clean memory
FF_4096_zero(r, FFLEN_4096);
FF_4096_zero(ws2, FFLEN_4096);
FF_4096_zero(pt, HFLEN_4096);
}

Expand Down Expand Up @@ -298,14 +289,10 @@ void PAILLIER_MULT(PAILLIER_public_key *PUB, octet* CT1, octet* PT, octet* CT)
// Read a public key from its octet representation
void PAILLIER_PK_fromOctet(PAILLIER_public_key *PUB, octet *PK)
{
FF_4096_zero(PUB->n, FFLEN_4096);
FF_4096_fromOctet(PUB->n, PK, HFLEN_4096);

FF_4096_sqr(PUB->n2, PUB->n, HFLEN_4096);
FF_4096_norm(PUB->n2, FFLEN_4096);

FF_4096_copy(PUB->g, PUB->n, FFLEN_4096);
FF_4096_inc(PUB->g, 1, HFLEN_4096);
}

// Write a public key to an octet
Expand Down