BigInt PointGFp::get_affine_y() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); const BigInt& r2 = curve.get_r2(); BigInt z3 = monty_mult(coord_z, monty_sqr(coord_z)); z3 = inverse_mod(z3, curve.get_p()); z3 = monty_mult(z3, r2); return monty_mult(coord_y, z3); }
bool PointGFp::on_the_curve() const { /* Is the point still on the curve?? (If everything is correct, the point is always on its curve; then the function will return true. If somehow the state is corrupted, which suggests a fault attack (or internal computational error), then return false. */ if(is_zero()) return true; BigInt y2 = monty_mult(monty_sqr(coord_y), 1); BigInt x3 = monty_mult(coord_x, monty_sqr(coord_x)); BigInt ax = monty_mult(coord_x, curve.get_a_r()); const BigInt& b_r = curve.get_b_r(); BigInt z2 = monty_sqr(coord_z); if(coord_z == z2) // Is z equal to 1 (in Montgomery form)? { if(y2 != monty_mult(x3 + ax + b_r, 1)) return false; } BigInt z3 = monty_mult(coord_z, z2); BigInt ax_z4 = monty_mult(ax, monty_sqr(z2)); BigInt b_z6 = monty_mult(b_r, monty_sqr(z3)); if(y2 != monty_mult(x3 + ax_z4 + b_z6, 1)) return false; return true; }
void zmModExp(z *a, z *b, z *u, z *nn) { //computes a^b mod m = u using the right to left binary method //see, for instance, the handbook of applied cryptography //uses monty arith //a is already in monty rep, b doesn't need to be. z n,bb,aa,t; zInit(&aa); zInit(&bb); zInit(&n); zInit(&t); //overflow possibilities: //t ranges to 2x input 'a' //u needs at least as much space as modulus zCopy(&montyconst.one,&n); zCopy(a,&aa); zCopy(b,&bb); while (!isZero(&bb)) { if (bb.val[0] & 0x1) { monty_mul(&n,&aa,&t,nn); zCopy(&t,&n); } zShiftRight(&bb,&bb,1); //compute successive squares of a monty_sqr(&aa,&t,nn); zCopy(&t,&aa); if (aa.size < 0) aa.size *= -1; } zCopy(&n,u); zFree(&aa); zFree(&bb); zFree(&n); zFree(&t); return; }
// Point addition void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn) { if(is_zero()) { coord_x = rhs.coord_x; coord_y = rhs.coord_y; coord_z = rhs.coord_z; return; } else if(rhs.is_zero()) return; const BigInt& p = curve.get_p(); BigInt& rhs_z2 = ws_bn[0]; BigInt& U1 = ws_bn[1]; BigInt& S1 = ws_bn[2]; BigInt& lhs_z2 = ws_bn[3]; BigInt& U2 = ws_bn[4]; BigInt& S2 = ws_bn[5]; BigInt& H = ws_bn[6]; BigInt& r = ws_bn[7]; monty_sqr(rhs_z2, rhs.coord_z); monty_mult(U1, coord_x, rhs_z2); monty_mult(S1, coord_y, monty_mult(rhs.coord_z, rhs_z2)); monty_sqr(lhs_z2, coord_z); monty_mult(U2, rhs.coord_x, lhs_z2); monty_mult(S2, rhs.coord_y, monty_mult(coord_z, lhs_z2)); H = U2; H -= U1; if(H.is_negative()) H += p; r = S2; r -= S1; if(r.is_negative()) r += p; if(H.is_zero()) { if(r.is_zero()) { mult2(ws_bn); return; } *this = PointGFp(curve); // setting myself to zero return; } monty_sqr(U2, H); monty_mult(S2, U2, H); U2 = monty_mult(U1, U2); monty_sqr(coord_x, r); coord_x -= S2; coord_x -= (U2 << 1); while(coord_x.is_negative()) coord_x += p; U2 -= coord_x; if(U2.is_negative()) U2 += p; monty_mult(coord_y, r, U2); coord_y -= monty_mult(S1, S2); if(coord_y.is_negative()) coord_y += p; monty_mult(coord_z, monty_mult(coord_z, rhs.coord_z), H); }
// *this *= 2 void PointGFp::mult2(std::vector<BigInt>& ws_bn) { if(is_zero()) return; else if(coord_y.is_zero()) { *this = PointGFp(curve); // setting myself to zero return; } const BigInt& p = curve.get_p(); BigInt& y_2 = ws_bn[0]; BigInt& S = ws_bn[1]; BigInt& z4 = ws_bn[2]; BigInt& a_z4 = ws_bn[3]; BigInt& M = ws_bn[4]; BigInt& U = ws_bn[5]; BigInt& x = ws_bn[6]; BigInt& y = ws_bn[7]; BigInt& z = ws_bn[8]; monty_sqr(y_2, coord_y); monty_mult(S, coord_x, y_2); S <<= 2; // * 4 while(S >= p) S -= p; monty_sqr(z4, monty_sqr(coord_z)); monty_mult(a_z4, curve.get_a_r(), z4); M = 3 * monty_sqr(coord_x); M += a_z4; while(M >= p) M -= p; monty_sqr(x, M); x -= (S << 1); while(x.is_negative()) x += p; monty_sqr(U, y_2); U <<= 3; while(U >= p) U -= p; S -= x; while(S.is_negative()) S += p; monty_mult(y, M, S); y -= U; if(y.is_negative()) y += p; monty_mult(z, coord_y, coord_z); z <<= 1; if(z >= p) z -= p; coord_x = x; coord_y = y; coord_z = z; }
void zmModExpw(z *a, z *e, z *u, z *n, int k) { //computes a^e mod m = u using the sliding window left to right binary method //see, for instance, the handbook of applied cryptography //uses monty arith //a is already in monty rep, b doesn't need to be. k is the window size /* INPUT: g, e = (etet-1 . . . e1e0)2 with et = 1, and an integer k >= 1. OUTPUT: g^e. 1. Precomputation. 1.1 g1 = g, g2 = g^2. 1.2 For i from 1 to (2^(k-1) - 1) do: g_{2i+1} = g_{2i-1} * g2. 2. A = 1, i = t. 3. While i >= 0 do the following: 3.1 If ei = 0 then do: A = A^2, i = i - 1. 3.2 Otherwise (ei != 0), find the longest bitstring eiei-1 . . . el such that i-l+1 <= k and el = 1, and do the following: A = A^{2^{i-l+1}} * g_{eiei-1...el}2 , i = l - 1. 4. Return(A). test -> 11749. 3 multiplications at i=7,4,0 */ //need to allocate (2^(k-1) + 1) g's for precomputation. z *g, g2, ztmp; int numg, i, j, l, t, tmp1, tmp2; fp_digit utmp1; uint8 *bitarray; //overflow possibilities: //t ranges to 2x input 'a' //u needs at least as much space as modulus numg = (int)((1<<(k-1))+1); g = (z *)malloc(numg*sizeof(z)); for (i=0;i<numg;i++) zInit(&g[i]); zInit(&g2); zInit(&ztmp); //precomputation zCopy(a,&g[0]); //g[0] = a monty_sqr(a,&g2,n); //g2 = a^2 for (i=1;i<numg;i++) monty_mul(&g[i-1],&g2,&g[i],n); //g[i] = g[i-1] * g2, where g[i] holds g^{2*i+1} zCopy(&montyconst.one,u); t = zBits(e); bitarray = (uint8 *)malloc(t * sizeof(uint8)); //get e in one array for (i=0;i< e->size - 1;i++) { utmp1 = e->val[i]; j=0; while (j<BITS_PER_DIGIT) { bitarray[BITS_PER_DIGIT*i+j] = (uint8)(utmp1 & 0x1); utmp1 >>= 1; j++; } } utmp1 = e->val[i]; j=0; while (utmp1) { bitarray[BITS_PER_DIGIT*i+j] = (uint8)(utmp1 & 0x1); utmp1 >>= 1; j++; } i=t-1; while (i >= 0) { if (bitarray[i]) { //find the longest bitstring ei,e1-1,...el such that i-l+1 <= k and el == 1 l=i; if (i >= (k-1)) { //protect against accessing bitarray past its boundaries for (j=k-1;j>0;j--) { if (bitarray[i-j]) { //this is the longest possible string, exit l=i-j; break; } } } //now, bitarray[i] to bitarray[i-j] is the longest bitstring //figure out the g value to use corresponding to this bitstring tmp1 = 1; tmp2 = 0; for (j=l;j<=i;j++) { tmp2 += tmp1 * bitarray[j]; tmp1 <<= 1; } tmp2 = (tmp2-1)/2; //do the operation A = A^{2^{i-l+1}} * g_{eiei-1...el}2 for (j=0;j<(i-l+1);j++) { monty_sqr(u,&ztmp,n); zCopy(&ztmp,u); } monty_mul(u,&g[tmp2],&ztmp,n); zCopy(&ztmp,u); //decrement bit pointer i = l-1; } else { monty_sqr(u,&ztmp,n); zCopy(&ztmp,u); i--; } } for (i=0;i<numg;i++) zFree(&g[i]); free(g); zFree(&g2); zFree(&ztmp); free(bitarray); return; }