예제 #1
0
파일: VLONG.CPP 프로젝트: ands904/SEnum
monty::monty( const vlong &M )
{
  m = M;
  N = 0; R = 1; while ( R < M ) { R += R; N += 1; }
  R1 = modinv( R-m, m );
  n1 = R - modinv( m, R );
}
예제 #2
0
int nCr_ferma(int n, int r, unsigned int p) {
  if (r == 0)
    return 1;
  int fac[n + 1];
  fac[0] = 1;
  for (int i = 1; i <= n; ++i) {
    fac[i] = fac[i-1] * i % p;
  }
  return (fac[n] * modinv(fac[r], p) % p * modinv(fac[n-r], p) % p) % p;
}
예제 #3
0
	vlong private_key::decrypt( const vlong& cipher )
	{
		// Calculate values for performing decryption
		// These could be cached, but the calculation is quite fast
		vlong d = modinv( e, (p-(vlong)1)*(q-(vlong)1) );
		vlong u = modinv( p, q );
		vlong dp = d % (p-(vlong)1);
		vlong dq = d % (q-(vlong)1);

		// Apply chinese remainder theorem
		vlong a = modexp( cipher % p, dp, p );
		vlong b = modexp( cipher % q, dq, q );
		if ( b < a ) b += q;
		return a + p * ( ((b-a)*u) % q );
	}
예제 #4
0
파일: CryptRSA.cpp 프로젝트: BitMax/openitg
int RSAKey::Generate( int bits )
{
	Bignum pm1, qm1, phi_n;

	/*
	 * We don't generate e; we just use a standard one always.
	 */
	this->exponent = bignum_from_long(RSA_EXPONENT);

	/*
	 * Generate p and q: primes with combined length `bits', not
	 * congruent to 1 modulo e. (Strictly speaking, we wanted (p-1)
	 * and e to be coprime, and (q-1) and e to be coprime, but in
	 * general that's slightly more fiddly to arrange. By choosing
	 * a prime e, we can simplify the criterion.)
	 */
	this->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL, 1);
	this->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL, 2);

	/*
	 * Ensure p > q, by swapping them if not.
	 */
	if (bignum_cmp(this->p, this->q) < 0)
		swap( p, q );

	/*
	 * Now we have p, q and e. All we need to do now is work out
	 * the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1),
	 * and (q^-1 mod p).
	 */
	this->modulus = bigmul(this->p, this->q);
	pm1 = copybn(this->p);
	decbn(pm1);
	qm1 = copybn(this->q);
	decbn(qm1);
	phi_n = bigmul(pm1, qm1);
	freebn(pm1);
	freebn(qm1);
	this->private_exponent = modinv(this->exponent, phi_n);
	this->iqmp = modinv(this->q, this->p);

	/*
	 * Clean up temporary numbers.
	 */
	freebn(phi_n);

	return 1;
}
예제 #5
0
파일: rsa.cpp 프로젝트: fangbaolei/EC700IR
//创建公私钥
void rsa_create_key(vlong& e, vlong& d , vlong& m )
{
	unsigned char prand[2][128],tc;
	UINT i,j, nCount = 64;

	srand((unsigned)time(NULL));

	for(i=0; i<2; i++)
	{
		for(j=0; j<nCount; j++)
		{
			tc = (char)(0x41+rand()%0xAF);
			prand[i][j] = tc;
		}
		prand[i][j]=0;
	}

	// Choose primes
	prime_factory pf;

	vlong s1 = from_str((const char*)prand[0]);
	vlong s2 = from_str((const char*)prand[1]);

	vlong p = pf.find_prime( s1 );
	vlong q = pf.find_prime( s2 );

	// Calculate public key
	m = p*q;

	e = 65537;
	while ( gcd(p-1,e) != 1 || gcd(q-1,e) != 1 ) e += 2;

	// Calculate private key
	d = modinv( e, (p-1)*(q-1) );
}
예제 #6
0
파일: rsa.cpp 프로젝트: fangbaolei/EC700IR
//创建公私钥
void rsa_create_key(RSA_KEY& pub, RSA_PRIVATE_KEY& pri)
{
	unsigned char prand[2][128],tc;
	UINT i,j, nCount = 64;

	srand((unsigned)time(NULL));

	for(i=0; i<2; i++)
	{
		for(j=0; j<nCount; j++)
		{
			tc = (char)(0x41+rand()%0xAF);
			prand[i][j] = tc;
		}
		prand[i][j]=0;
	}

	// Choose primes
	prime_factory pf;

	vlong s1 = from_str((const char*)prand[0]);
	vlong s2 = from_str((const char*)prand[1]);

	vlong tp = pf.find_prime( s1 );
	vlong tq = pf.find_prime( s2 );

	if ( tq > tp ) //make sure p > q
	{
		vlong tmp = tp;
		tp = tq;
		tq = tmp;
	}

	// Calculate public key
	pub.modulus = tp*tq;

	pub.key = 65537;
	while ( gcd(tp-1,pub.key) != 1 || gcd(tq-1,pub.key) != 1 ) pub.key += 2;

	// Calculate private key
	pri.p=tp;
	pri.q=tq;
	pri.dp=modinv(pub.key,tp-1);
	pri.dq=modinv(pub.key,tq-1);
	pri.qinv=modinv(tq,tp);
}
예제 #7
0
파일: sshdss.c 프로젝트: DAVe3283/PuTTY
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
{
    struct dss_key *dss = (struct dss_key *) key;
    Bignum k, gkp, hash, kinv, hxr, r, s;
    unsigned char digest[20];
    unsigned char *bytes;
    int nbytes, i;

    SHA_Simple(data, datalen, digest);

    k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x,
                  digest, sizeof(digest));
    kinv = modinv(k, dss->q);	       /* k^-1 mod q */
    assert(kinv);

    /*
     * Now we have k, so just go ahead and compute the signature.
     */
    gkp = modpow(dss->g, k, dss->p);   /* g^k mod p */
    r = bigmod(gkp, dss->q);	       /* r = (g^k mod p) mod q */
    freebn(gkp);

    hash = bignum_from_bytes(digest, 20);
    hxr = bigmuladd(dss->x, r, hash);  /* hash + x*r */
    s = modmul(kinv, hxr, dss->q);     /* s = k^-1 * (hash + x*r) mod q */
    freebn(hxr);
    freebn(kinv);
    freebn(k);
    freebn(hash);

    /*
     * Signature blob is
     * 
     *   string  "ssh-dss"
     *   string  two 20-byte numbers r and s, end to end
     * 
     * i.e. 4+7 + 4+40 bytes.
     */
    nbytes = 4 + 7 + 4 + 40;
    bytes = snewn(nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-dss", 7);
    PUT_32BIT(bytes + 4 + 7, 40);
    for (i = 0; i < 20; i++) {
	bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
	bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
    }
    freebn(r);
    freebn(s);

    *siglen = nbytes;
    return bytes;
}
예제 #8
0
int main()
{
    for (int m = 1; m < 10000; ++m) {
        for (int a = 0; a < 2*m; ++a) {
            if (gcd(a,m) % m == 1) {
                assert((a * modinv(a,m)) % m == 1);
            }
        }
    }

    return 0;
}
예제 #9
0
void solve(int n, int m, int k){
    long long sum = 0;
    long long sdi2 = m;
    for(int i=1;i<=k;i++){
        sum+= (sdi2*pnr(n,i))%PRIME;;
        long long den = i+1;
        long long num = m-i;
        sdi2 = (sdi2*num)%PRIME;
        sdi2 = (sdi2*modinv(den,PRIME))%PRIME;

    }
    printf("%ld\n",(sum+PRIME)%PRIME);
}
예제 #10
0
파일: sshdss.c 프로젝트: AshKash/kit-sink
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
{
    /*
     * The basic DSS signing algorithm is:
     * 
     *  - invent a random k between 1 and q-1 (exclusive).
     *  - Compute r = (g^k mod p) mod q.
     *  - Compute s = k^-1 * (hash + x*r) mod q.
     * 
     * This has the dangerous properties that:
     * 
     *  - if an attacker in possession of the public key _and_ the
     *    signature (for example, the host you just authenticated
     *    to) can guess your k, he can reverse the computation of s
     *    and work out x = r^-1 * (s*k - hash) mod q. That is, he
     *    can deduce the private half of your key, and masquerade
     *    as you for as long as the key is still valid.
     * 
     *  - since r is a function purely of k and the public key, if
     *    the attacker only has a _range of possibilities_ for k
     *    it's easy for him to work through them all and check each
     *    one against r; he'll never be unsure of whether he's got
     *    the right one.
     * 
     *  - if you ever sign two different hashes with the same k, it
     *    will be immediately obvious because the two signatures
     *    will have the same r, and moreover an attacker in
     *    possession of both signatures (and the public key of
     *    course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
     *    and from there deduce x as before.
     * 
     *  - the Bleichenbacher attack on DSA makes use of methods of
     *    generating k which are significantly non-uniformly
     *    distributed; in particular, generating a 160-bit random
     *    number and reducing it mod q is right out.
     * 
     * For this reason we must be pretty careful about how we
     * generate our k. Since this code runs on Windows, with no
     * particularly good system entropy sources, we can't trust our
     * RNG itself to produce properly unpredictable data. Hence, we
     * use a totally different scheme instead.
     * 
     * What we do is to take a SHA-512 (_big_) hash of the private
     * key x, and then feed this into another SHA-512 hash that
     * also includes the message hash being signed. That is:
     * 
     *   proto_k = SHA512 ( SHA512(x) || SHA160(message) )
     * 
     * This number is 512 bits long, so reducing it mod q won't be
     * noticeably non-uniform. So
     * 
     *   k = proto_k mod q
     * 
     * This has the interesting property that it's _deterministic_:
     * signing the same hash twice with the same key yields the
     * same signature.
     * 
     * Despite this determinism, it's still not predictable to an
     * attacker, because in order to repeat the SHA-512
     * construction that created it, the attacker would have to
     * know the private key value x - and by assumption he doesn't,
     * because if he knew that he wouldn't be attacking k!
     *
     * (This trick doesn't, _per se_, protect against reuse of k.
     * Reuse of k is left to chance; all it does is prevent
     * _excessively high_ chances of reuse of k due to entropy
     * problems.)
     * 
     * Thanks to Colin Plumb for the general idea of using x to
     * ensure k is hard to guess, and to the Cambridge University
     * Computer Security Group for helping to argue out all the
     * fine details.
     */
    struct dss_key *dss = (struct dss_key *) key;
    SHA512_State ss;
    unsigned char digest[20], digest512[64];
    Bignum proto_k, k, gkp, hash, kinv, hxr, r, s;
    unsigned char *bytes;
    int nbytes, i;

    SHA_Simple(data, datalen, digest);

    /*
     * Hash some identifying text plus x.
     */
    SHA512_Init(&ss);
    SHA512_Bytes(&ss, "DSA deterministic k generator", 30);
    sha512_mpint(&ss, dss->x);
    SHA512_Final(&ss, digest512);

    /*
     * Now hash that digest plus the message hash.
     */
    SHA512_Init(&ss);
    SHA512_Bytes(&ss, digest512, sizeof(digest512));
    SHA512_Bytes(&ss, digest, sizeof(digest));
    SHA512_Final(&ss, digest512);

    memset(&ss, 0, sizeof(ss));

    /*
     * Now convert the result into a bignum, and reduce it mod q.
     */
    proto_k = bignum_from_bytes(digest512, 64);
    k = bigmod(proto_k, dss->q);
    freebn(proto_k);

    memset(digest512, 0, sizeof(digest512));

    /*
     * Now we have k, so just go ahead and compute the signature.
     */
    gkp = modpow(dss->g, k, dss->p);   /* g^k mod p */
    r = bigmod(gkp, dss->q);	       /* r = (g^k mod p) mod q */
    freebn(gkp);

    hash = bignum_from_bytes(digest, 20);
    kinv = modinv(k, dss->q);	       /* k^-1 mod q */
    hxr = bigmuladd(dss->x, r, hash);  /* hash + x*r */
    s = modmul(kinv, hxr, dss->q);     /* s = k^-1 * (hash + x*r) mod q */
    freebn(hxr);
    freebn(kinv);
    freebn(hash);

    /*
     * Signature blob is
     * 
     *   string  "ssh-dss"
     *   string  two 20-byte numbers r and s, end to end
     * 
     * i.e. 4+7 + 4+40 bytes.
     */
    nbytes = 4 + 7 + 4 + 40;
    bytes = snewn(nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-dss", 7);
    PUT_32BIT(bytes + 4 + 7, 40);
    for (i = 0; i < 20; i++) {
	bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
	bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
    }
    freebn(r);
    freebn(s);

    *siglen = nbytes;
    return bytes;
}
예제 #11
0
파일: sshdss.c 프로젝트: AshKash/kit-sink
static int dss_verifysig(void *key, char *sig, int siglen,
			 char *data, int datalen)
{
    struct dss_key *dss = (struct dss_key *) key;
    char *p;
    int slen;
    char hash[20];
    Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v;
    int ret;

    if (!dss->p)
	return 0;

#ifdef DEBUG_DSS
    {
	int i;
	printf("sig:");
	for (i = 0; i < siglen; i++)
	    printf("  %02x", (unsigned char) (sig[i]));
	printf("\n");
    }
#endif
    /*
     * Commercial SSH (2.0.13) and OpenSSH disagree over the format
     * of a DSA signature. OpenSSH is in line with the IETF drafts:
     * it uses a string "ssh-dss", followed by a 40-byte string
     * containing two 160-bit integers end-to-end. Commercial SSH
     * can't be bothered with the header bit, and considers a DSA
     * signature blob to be _just_ the 40-byte string containing
     * the two 160-bit integers. We tell them apart by measuring
     * the length: length 40 means the commercial-SSH bug, anything
     * else is assumed to be IETF-compliant.
     */
    if (siglen != 40) {		       /* bug not present; read admin fields */
	getstring(&sig, &siglen, &p, &slen);
	if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
	    return 0;
	}
	sig += 4, siglen -= 4;	       /* skip yet another length field */
    }
    r = get160(&sig, &siglen);
    s = get160(&sig, &siglen);
    if (!r || !s)
	return 0;

    /*
     * Step 1. w <- s^-1 mod q.
     */
    w = modinv(s, dss->q);

    /*
     * Step 2. u1 <- SHA(message) * w mod q.
     */
    SHA_Simple(data, datalen, (unsigned char *)hash);
    p = hash;
    slen = 20;
    sha = get160(&p, &slen);
    u1 = modmul(sha, w, dss->q);

    /*
     * Step 3. u2 <- r * w mod q.
     */
    u2 = modmul(r, w, dss->q);

    /*
     * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
     */
    gu1p = modpow(dss->g, u1, dss->p);
    yu2p = modpow(dss->y, u2, dss->p);
    gu1yu2p = modmul(gu1p, yu2p, dss->p);
    v = modmul(gu1yu2p, One, dss->q);

    /*
     * Step 5. v should now be equal to r.
     */

    ret = !bignum_cmp(v, r);

    freebn(w);
    freebn(sha);
    freebn(gu1p);
    freebn(yu2p);
    freebn(gu1yu2p);
    freebn(v);
    freebn(r);
    freebn(s);

    return ret;
}
예제 #12
0
파일: SSHRSA.C 프로젝트: marsupial/rikiglue
/*
 * This function is a wrapper on modpow(). It has the same effect
 * as modpow(), but employs RSA blinding to protect against timing
 * attacks.
 */
static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)
{
    Bignum random, random_encrypted, random_inverse;
    Bignum input_blinded, ret_blinded;
    Bignum ret;

    SHA512_State ss;
    unsigned char digest512[64];
    int digestused = lenof(digest512);
    int hashseq = 0;

    /*
     * Start by inventing a random number chosen uniformly from the
     * range 2..modulus-1. (We do this by preparing a random number
     * of the right length and retrying if it's greater than the
     * modulus, to prevent any potential Bleichenbacher-like
     * attacks making use of the uneven distribution within the
     * range that would arise from just reducing our number mod n.
     * There are timing implications to the potential retries, of
     * course, but all they tell you is the modulus, which you
     * already knew.)
     * 
     * To preserve determinism and avoid Pageant needing to share
     * the random number pool, we actually generate this `random'
     * number by hashing stuff with the private key.
     */
    while (1) {
	int bits, byte, bitsleft, v;
	random = copybn(key->modulus);
	/*
	 * Find the topmost set bit. (This function will return its
	 * index plus one.) Then we'll set all bits from that one
	 * downwards randomly.
	 */
	bits = bignum_bitcount(random);
	byte = 0;
	bitsleft = 0;
	while (bits--) {
	    if (bitsleft <= 0) {
		bitsleft = 8;
		/*
		 * Conceptually the following few lines are equivalent to
		 *    byte = random_byte();
		 */
		if (digestused >= lenof(digest512)) {
		    unsigned char seqbuf[4];
		    PUT_32BIT(seqbuf, hashseq);
		    pSHA512_Init(&ss);
		    SHA512_Bytes(&ss, "RSA deterministic blinding", 26);
		    SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf));
		    sha512_mpint(&ss, key->private_exponent);
		    pSHA512_Final(&ss, digest512);
		    hashseq++;

		    /*
		     * Now hash that digest plus the signature
		     * input.
		     */
		    pSHA512_Init(&ss);
		    SHA512_Bytes(&ss, digest512, sizeof(digest512));
		    sha512_mpint(&ss, input);
		    pSHA512_Final(&ss, digest512);

		    digestused = 0;
		}
		byte = digest512[digestused++];
	    }
	    v = byte & 1;
	    byte >>= 1;
	    bitsleft--;
	    bignum_set_bit(random, bits, v);
	}

	/*
	 * Now check that this number is strictly greater than
	 * zero, and strictly less than modulus.
	 */
	if (bignum_cmp(random, Zero) <= 0 ||
	    bignum_cmp(random, key->modulus) >= 0) {
	    freebn(random);
	    continue;
	} else {
	    break;
	}
    }

    /*
     * RSA blinding relies on the fact that (xy)^d mod n is equal
     * to (x^d mod n) * (y^d mod n) mod n. We invent a random pair
     * y and y^d; then we multiply x by y, raise to the power d mod
     * n as usual, and divide by y^d to recover x^d. Thus an
     * attacker can't correlate the timing of the modpow with the
     * input, because they don't know anything about the number
     * that was input to the actual modpow.
     * 
     * The clever bit is that we don't have to do a huge modpow to
     * get y and y^d; we will use the number we just invented as
     * _y^d_, and use the _public_ exponent to compute (y^d)^e = y
     * from it, which is much faster to do.
     */
    random_encrypted = modpow(random, key->exponent, key->modulus);
    random_inverse = modinv(random, key->modulus);
    input_blinded = modmul(input, random_encrypted, key->modulus);
    ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus);
    ret = modmul(ret_blinded, random_inverse, key->modulus);

    freebn(ret_blinded);
    freebn(input_blinded);
    freebn(random_inverse);
    freebn(random_encrypted);
    freebn(random);

    return ret;
}
예제 #13
0
파일: main.c 프로젝트: Tojaj/rsa-algorithm
int
main(int argc, char *argv[])
{
    KryState state = STATE_BADARG;
    long mod_bits;

    if (argc == 3 && !strcmp(argv[1], "-g")) {
        // Key generation
        state = STATE_KEYGEN;
        mod_bits = strtol(argv[2], NULL, 10);
        if (mod_bits < 16) {
            state = STATE_BADARG;
            fprintf(stderr, "Too small key length\n");
        }
    } else if (argc == 5 && !strcmp(argv[1], "-e")) {
        // Encryption
        state = STATE_ENCRYPTION;
    } else if (argc == 5 && !strcmp(argv[1], "-d")) {
        // Decryption
        state = STATE_DECRYPTION;
    } else if (argc == 5 && !strcmp(argv[1], "-b")) {
        // RSA cracking
        state = STATE_CRACKING;
    }

    if (state == STATE_BADARG) {
        // Someting is messed up
        print_help(argv[0]);
        return EXIT_FAILURE;
    }

    // Prepare pseudo number generator stuff
    gmp_randstate_t randstate;
    gmp_randinit_default(randstate);
    //gmp_randseed_ui(randstate, 1);
    gmp_randseed_ui(randstate, time(NULL));

    int rc = EXIT_SUCCESS;
    mpz_t res;
    mpz_init(res);

    switch (state) {
        case STATE_KEYGEN: {
            mpz_t p, q, n, e;  // For d use res var
            mpz_init(p);
            mpz_init(q);
            mpz_init(n);
            mpz_init(e);
            rc = keygen(p, q, n, e, res, mod_bits, randstate);
            gmp_printf("0x%Zx 0x%Zx 0x%Zx 0x%Zx 0x%Zx\n", p, q, n, e, res);
            mpz_clear(p);
            mpz_clear(q);
            mpz_clear(n);
            mpz_clear(e);
            break;
        }

        case STATE_ENCRYPTION:
            // Argv: [2]=e; [3]=n; [4]=m;
            rc = encrypt(res, argv[2], argv[3], argv[4]);
            gmp_printf("0x%Zx\n", res);
            break;

        case STATE_DECRYPTION:
            // Argv: [2]=d; [3]=n; [4]=c;
            rc = decrypt(res, argv[2], argv[3], argv[4]);
            gmp_printf("0x%Zx\n", res);
            break;

        case STATE_CRACKING: {
            // Argv: [2]=e; [3]=n; [4]=c;
            mpz_t p, q, p_, q_, e, d;
            mpz_init(p);
            mpz_init(q);
            mpz_init(p_);
            mpz_init(q_);
            mpz_init(e);
            mpz_init(d);

            rc = factorization(p, q, argv[3]);
            if (rc != 0)
                goto cracking_cleanup;

            // phi = (p-1) * (q-1)
            mpz_sub_ui(p_, p, 1L);
            mpz_sub_ui(q_, q, 1L);
            mpz_mul(res, p_, q_);

            // d = e^1 mod phi
            mpz_set_str(e, argv[2], 0);
            modinv(d, e, res);

            rc = decrypt_mpz_d(res, d, argv[3], argv[4]);
            gmp_printf("0x%Zx 0x%Zx 0x%Zx\n", p, q, res);
        cracking_cleanup:
            mpz_clear(p);
            mpz_clear(q);
            mpz_clear(p_);
            mpz_clear(q_);
            mpz_clear(e);
            mpz_clear(d);
            break;
        }

        case STATE_BADARG:
            break;
    }

    mpz_clear(res);
    gmp_randclear(randstate);
    return rc;
}
예제 #14
0
파일: p134.c 프로젝트: hacatu/project-euler
uint64_t moddiv(uint64_t a, uint64_t b, uint64_t m) {
    uint64_t i = modinv(b, m);
    return a*i%m;
}
예제 #15
0
int main() {
  printf("%d\n", modinv(3, 4));
  return 0;
}
예제 #16
0
파일: sshrsag.c 프로젝트: rdebath/sgt
int rsa_generate(struct RSAKey *key, struct RSAAux *aux, int bits,
                 progfn_t pfn, void *pfnparam) {
    Bignum pm1, qm1, phi_n;

    /*
     * Set up the phase limits for the progress report. We do this
     * by passing minus the phase number.
     *
     * For prime generation: our initial filter finds things
     * coprime to everything below 2^16. Computing the product of
     * (p-1)/p for all prime p below 2^16 gives about 20.33; so
     * among B-bit integers, one in every 20.33 will get through
     * the initial filter to be a candidate prime.
     *
     * Meanwhile, we are searching for primes in the region of 2^B;
     * since pi(x) ~ x/log(x), when x is in the region of 2^B, the
     * prime density will be d/dx pi(x) ~ 1/log(B), i.e. about
     * 1/0.6931B. So the chance of any given candidate being prime
     * is 20.33/0.6931B, which is roughly 29.34 divided by B.
     *
     * So now we have this probability P, we're looking at an
     * exponential distribution with parameter P: we will manage in
     * one attempt with probability P, in two with probability
     * P(1-P), in three with probability P(1-P)^2, etc. The
     * probability that we have still not managed to find a prime
     * after N attempts is (1-P)^N.
     * 
     * We therefore inform the progress indicator of the number B
     * (29.34/B), so that it knows how much to increment by each
     * time. We do this in 16-bit fixed point, so 29.34 becomes
     * 0x1D.57C4.
     */
    pfn(pfnparam, -1, -0x1D57C4/(bits/2));
    pfn(pfnparam, -2, -0x1D57C4/(bits-bits/2));
    pfn(pfnparam, -3, 5);

    /*
     * We don't generate e; we just use a standard one always.
     */
    key->exponent = bignum_from_short(RSA_EXPONENT);

    /*
     * Generate p and q: primes with combined length `bits', not
     * congruent to 1 modulo e. (Strictly speaking, we wanted (p-1)
     * and e to be coprime, and (q-1) and e to be coprime, but in
     * general that's slightly more fiddly to arrange. By choosing
     * a prime e, we can simplify the criterion.)
     */
    aux->p = primegen(bits/2, RSA_EXPONENT, 1, 1, pfn, pfnparam);
    aux->q = primegen(bits - bits/2, RSA_EXPONENT, 1, 2, pfn, pfnparam);

    /*
     * Ensure p > q, by swapping them if not.
     */
    if (bignum_cmp(aux->p, aux->q) < 0) {
        Bignum t = aux->p;
        aux->p = aux->q;
        aux->q = t;
    }

    /*
     * Now we have p, q and e. All we need to do now is work out
     * the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1),
     * and (q^-1 mod p).
     */
    pfn(pfnparam, 3, 1);
    key->modulus = bigmul(aux->p, aux->q);
    pfn(pfnparam, 3, 2);
    pm1 = copybn(aux->p);
    decbn(pm1);
    qm1 = copybn(aux->q);
    decbn(qm1);
    phi_n = bigmul(pm1, qm1);
    pfn(pfnparam, 3, 3);
    freebn(pm1);
    freebn(qm1);
    key->private_exponent = modinv(key->exponent, phi_n);
    pfn(pfnparam, 3, 4);
    aux->iqmp = modinv(aux->q, aux->p);
    pfn(pfnparam, 3, 5);

    /*
     * Clean up temporary numbers.
     */
    freebn(phi_n);

    return 1;
}