void main(void) { mpint *z = mpnew(0); mpint *p = mpnew(0); mpint *q = mpnew(0); mpint *nine = mpnew(0); fmtinstall('B', mpconv); strtomp("2492491", nil, 16, z); // 38347921 = x*y = (2**28-9)/7, // an example of 3**(n-1)=1 mod n strtomp("15662C00E811", nil, 16, p);// 23528569104401, a prime uitomp(9, nine); if(probably_prime(z, 5) == 1) fprint(2, "tricked primality test\n"); if(probably_prime(nine, 5) == 1) fprint(2, "9 passed primality test!\n"); if(probably_prime(p, 25) == 1) fprint(2, "ok\n"); DSAprimes(q, p, nil); print("q=%B\np=%B\n", q, p); exits(0); }
RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q) { mpint *c2, *kq, *kp, *x; RSApriv *rsa; // make sure we're not being hoodwinked if(!probably_prime(p, 10) || !probably_prime(q, 10)){ werrstr("rsafill: p or q not prime"); return nil; } x = mpnew(0); mpmul(p, q, x); if(mpcmp(n, x) != 0){ werrstr("rsafill: n != p*q"); mpfree(x); return nil; } c2 = mpnew(0); mpsub(p, mpone, c2); mpsub(q, mpone, x); mpmul(c2, x, x); mpmul(e, d, c2); mpmod(c2, x, x); if(mpcmp(x, mpone) != 0){ werrstr("rsafill: e*d != 1 mod (p-1)*(q-1)"); mpfree(x); mpfree(c2); return nil; } // compute chinese remainder coefficient mpinvert(p, q, c2); // for crt a**k mod p == (a**(k mod p-1)) mod p kq = mpnew(0); kp = mpnew(0); mpsub(p, mpone, x); mpmod(d, x, kp); mpsub(q, mpone, x); mpmod(d, x, kq); rsa = rsaprivalloc(); rsa->pub.ek = mpcopy(e); rsa->pub.n = mpcopy(n); rsa->dk = mpcopy(d); rsa->kp = kp; rsa->kq = kq; rsa->p = mpcopy(p); rsa->q = mpcopy(q); rsa->c2 = c2; mpfree(x); return rsa; }
// find a prime p of length n and a generator alpha of Z^*_p // Alg 4.86 Menezes et al () Handbook, p.164 void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy) { mpint *q, *b; q = mpnew(n-1); while(1){ genprime(q, n-1, accuracy); mpleft(q, 1, p); mpadd(p, mpone, p); // p = 2*q+1 if(probably_prime(p, accuracy)) break; } // now find a generator alpha of the multiplicative // group Z*_p of order p-1=2q b = mpnew(0); while(1){ mprand(n, genrandom, alpha); mpmod(alpha, p, alpha); mpmul(alpha, alpha, b); mpmod(b, p, b); if(mpcmp(b, mpone) == 0) continue; mpexp(alpha, q, p, b); if(mpcmp(b, mpone) != 0) break; } mpfree(b); mpfree(q); }
// generate a probable prime. accuracy is the miller-rabin interations void genprime(mpint *p, int n, int accuracy) { mpdigit x; // generate n random bits with high and low bits set mpbits(p, n); genrandom((uint8_t*)p->p, (n+7)/8); p->top = (n+Dbits-1)/Dbits; x = 1; x <<= ((n-1)%Dbits); p->p[p->top-1] &= (x-1); p->p[p->top-1] |= x; p->p[0] |= 1; // keep icrementing till it looks prime for(;;){ if(probably_prime(p, accuracy)) break; mpadd(p, mptwo, p); } }