int isPrime2(int n) { int nc = n-1; int s = 0; while ((nc&1) == 0) { s += 1; nc >>= 1; } int d = n>>s; int a = 2; while (a <= 3) { if (isPrime1(a)) { if (modpow(a,d,n) != 1 & modpow(a,d,n) != n-1) { int r = 0; int worked = 0; while ((r <= s-1) & (r <= s)) { if (modpow(a, (2<<r)*d, n) == n-1) { worked = 1; } r += 1; } if (worked == 0) { return 0; } } } a++; } return 1; }
/** * is_prime(uint64_t n, unsigned int k): * * SYNOPSIS * Tests if a given candidate is prime with a given number of rounds of * the Miller-Rabin-Test. * * DESCRIPTION * is_prime() first tests primitely, and if the number passes it, * goes on with the Miller-Rabin-Test. We do this because dividing is faster * than the test. * Note that even here, we don't know for sure if the given number is prime, * it's only a probability test. * * RETURN VALUE * 1 if candidate passes the test, otherwise 0 */ int is_prime(uint64_t n, unsigned int k) { if (n == 2) return 1; if (n == 1 || (n & 1) == 0) return 0; if (primitive_test(n) == NO_PRIME) return 0; uint64_t t, a, y, d = n-1; while ((d & 1) == 0) { d >>= 1; } int count; for (count=0; count < k; count++) { a = rand()/100; t = d; y = modpow(a, t, n); while (t != n-1 && y != 1 && y != n-1) { y = (y*y) % n; t <<= 1; } if (y != n-1 && (t & 1) == 0) return 0; } return 1; }
/* * DH stage 2: given a number f, compute K = f^x mod p. */ Bignum dh_find_K(void *handle, Bignum f) { struct dh_ctx *ctx = (struct dh_ctx *)handle; Bignum ret; ret = modpow(f, ctx->x, ctx->p); return ret; }
int rsaencrypt(unsigned char *data, int length, struct RSAKey *key) { Bignum b1, b2; int i; unsigned char *p; if (key->bytes < length + 4) return 0; /* RSA key too short! */ memmove(data + key->bytes - length, data, length); data[0] = 0; data[1] = 2; for (i = 2; i < key->bytes - length - 1; i++) { do { data[i] = random_byte(); } while (data[i] == 0); } data[key->bytes - length - 1] = 0; b1 = bignum_from_bytes(data, key->bytes); b2 = modpow(b1, key->exponent, key->modulus); p = data; for (i = key->bytes; i--;) { *p++ = bignum_byte(b2, i); } freebn(b1); freebn(b2); return 1; }
// find smallest primitive root of _n (assuming _n is prime) unsigned int primitive_root(unsigned int _n) { // find unique factors of _n-1 unsigned int unique_factors[MAX_FACTORS]; unsigned int num_unique_factors = 0; unsigned int n = _n-1; unsigned int k; do { for (k=2; k<=n; k++) { if ( (n%k)==0 ) { // k is a factor of (_n-1) n /= k; // add element to end of table unique_factors[num_unique_factors] = k; // increment counter only if element is unique if (num_unique_factors == 0) num_unique_factors++; else if (unique_factors[num_unique_factors-1] != k) num_unique_factors++; break; } } } while (n > 1 && num_unique_factors < MAX_FACTORS); #if 0 // print unique factors printf("found %u unique factors of n-1 = %u\n", num_unique_factors, _n-1); for (k=0; k<num_unique_factors; k++) printf(" %3u\n", unique_factors[k]); #endif // search for minimum integer for which // g^( (_n-1)/m ) != 1 (mod _n) // for all unique roots 'm' unsigned int g; int root_found = 0; for (g=2; g<_n; g++) { int is_root = 1; for (k=0; k<num_unique_factors; k++) { unsigned int e = (_n-1) / unique_factors[k]; if ( modpow(g,e,_n) == 1 ) { // not a root is_root = 0; break; } } if (is_root) { //printf(" %u is a primitive root!\n", g); root_found = 1; break; } } return g; }
/** \brief Preforms RSA encryption on plaintext m using exponent e and modulus n\n * m^e mod n * * \param m int Plaintext * \param e int Encryption Exponent * \param n int Modulus * \return int Ciphertext * */ int RSA::encode(int m, int e, int n) { int c; m &= 0x000000ff; c = modpow(m, e, n); return c; }
long long ncr_modp(const long long x, const long long y, const long long p) { long long temp, result; temp = fact_modp(x, p) * fact_modp(y, p) % p; result = modpow(temp, p-2, p) * fact_modp(x + y, p); return result % p; }
void rsaencrypt(unsigned char *data, int length, struct RSAKey *key) { Bignum b1, b2; int w, i; unsigned char *p; debug(key->exponent); memmove(data+key->bytes-length, data, length); data[0] = 0; data[1] = 2; for (i = 2; i < key->bytes-length-1; i++) { do { data[i] = random_byte(); } while (data[i] == 0); } data[key->bytes-length-1] = 0; w = (key->bytes+1)/2; b1 = newbn(w); b2 = newbn(w); p = data; for (i=1; i<=w; i++) b1[i] = 0; for (i=0; i<key->bytes; i++) { unsigned char byte = *p++; if ((key->bytes-i) & 1) b1[w-i/2] |= byte; else b1[w-i/2] |= byte<<8; } debug(b1); modpow(b1, key->exponent, key->modulus, b2); debug(b2); p = data; for (i=0; i<key->bytes; i++) { unsigned char b; if (i & 1) b = b2[w-i/2] & 0xFF; else b = b2[w-i/2] >> 8; *p++ = b; } freebn(b1); freebn(b2); }
static void *dss_createkey(unsigned char *pub_blob, int pub_len, unsigned char *priv_blob, int priv_len) { dss_key *dss; char *pb = (char *) priv_blob; char *hash; int hashlen; SHA_State s; unsigned char digest[20]; Bignum ytest; dss = dss_newkey((char *) pub_blob, pub_len); if (!dss) return NULL; dss->x = getmp(&pb, &priv_len); if (!dss->x) { dss_freekey(dss); return NULL; } /* * Check the obsolete hash in the old DSS key format. */ hashlen = -1; getstring(&pb, &priv_len, &hash, &hashlen); if (hashlen == 20) { SHA_Init(&s); sha_mpint(&s, dss->p); sha_mpint(&s, dss->q); sha_mpint(&s, dss->g); SHA_Final(&s, digest); if (0 != memcmp(hash, digest, 20)) { dss_freekey(dss); return NULL; } } /* * Now ensure g^x mod p really is y. */ ytest = modpow(dss->g, dss->x, dss->p); if (0 != bignum_cmp(ytest, dss->y)) { dss_freekey(dss); freebn(ytest); return NULL; } freebn(ytest); return dss; }
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; }
function SPRP(N,a) { var d = N-1; s = 1; // Assumes N is odd! while ( ((d=d/2) & 1) == 0) s++; // Using d>>1 changed the sign of d! // Now N-1 = d*2^s with d odd var b = modpow(a,d,N); if (b == 1) return true; if (b+1 == N) return true; while (s-- > 1) { b = modmult(b,b,N); if (b+1 == N) return true; } return false; }
int main(void) { modmult(P1, P2, bigmod, a); debug(a); modmult(a, P3, bigmod, mod); debug(mod); sub(P1, One, a); debug(a); sub(P2, One, b); debug(b); modmult(a, b, bigmod, c); debug(c); sub(P3, One, a); debug(a); modmult(a, c, bigmod, b); debug(b); modpow(Two, b, mod, a); debug(a); return 0; }
/* * DH stage 1: invent a number x between 1 and q, and compute e = * g^x mod p. Return e. * * If `nbits' is greater than zero, it is used as an upper limit * for the number of bits in x. This is safe provided that (a) you * use twice as many bits in x as the number of bits you expect to * use in your session key, and (b) the DH group is a safe prime * (which SSH demands that it must be). * * P. C. van Oorschot, M. J. Wiener * "On Diffie-Hellman Key Agreement with Short Exponents". * Advances in Cryptology: Proceedings of Eurocrypt '96 * Springer-Verlag, May 1996. */ Bignum dh_create_e(void *handle, int nbits) { struct dh_ctx *ctx = (struct dh_ctx *)handle; int i; int nbytes; unsigned char *buf; nbytes = ssh1_bignum_length(ctx->qmask); buf = snewn(nbytes, unsigned char); do { /* * Create a potential x, by ANDing a string of random bytes * with qmask. */ if (ctx->x) freebn(ctx->x); if (nbits == 0 || nbits > bignum_bitcount(ctx->qmask)) { ssh1_write_bignum(buf, ctx->qmask); for (i = 2; i < nbytes; i++) buf[i] &= random_byte(); ssh1_read_bignum(buf, nbytes, &ctx->x); /* can't fail */ } else { int b, nb; ctx->x = bn_power_2(nbits); b = nb = 0; for (i = 0; i < nbits; i++) { if (nb == 0) { nb = 8; b = random_byte(); } bignum_set_bit(ctx->x, i, b & 1); b >>= 1; nb--; } } } while (bignum_cmp(ctx->x, One) <= 0 || bignum_cmp(ctx->x, ctx->q) >= 0); sfree(buf); /* * Done. Now compute e = g^x mod p. */ ctx->e = modpow(ctx->g, ctx->x, ctx->p); return ctx->e; }
static int rsa2_verifysig(void *key, char *sig, int siglen, char *data, int datalen) { struct RSAKey *rsa = (struct RSAKey *) key; Bignum in, out; char *p; int slen; int bytes, i, j, ret; unsigned char hash[20]; getstring(&sig, &siglen, &p, &slen); if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) { return 0; } in = getmp(&sig, &siglen); out = modpow(in, rsa->exponent, rsa->modulus); freebn(in); ret = 1; bytes = (bignum_bitcount(rsa->modulus)+7) / 8; /* Top (partial) byte should be zero. */ if (bignum_byte(out, bytes - 1) != 0) ret = 0; /* First whole byte should be 1. */ if (bignum_byte(out, bytes - 2) != 1) ret = 0; /* Most of the rest should be FF. */ for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) { if (bignum_byte(out, i) != 0xFF) ret = 0; } /* Then we expect to see the asn1_weird_stuff. */ for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) { if (bignum_byte(out, i) != asn1_weird_stuff[j]) ret = 0; } /* Finally, we expect to see the SHA-1 hash of the signed data. */ SHA_Simple(data, datalen, hash); for (i = 19, j = 0; i >= 0; i--, j++) { if (bignum_byte(out, i) != hash[j]) ret = 0; } freebn(out); return ret; }
bool RSAKey::Verify( const CString &data, const CString &sig ) const { Bignum in, out; int bytes, i, j; unsigned char hash[20]; in = bignum_from_bytes( (const unsigned char *) sig.data(), sig.size() ); /* Base (in) must be smaller than the modulus. */ if( bignum_cmp(in, this->modulus) >= 0 ) { freebn(in); return false; } out = modpow(in, this->exponent, this->modulus); freebn(in); bool ret = true; bytes = (bignum_bitcount(this->modulus)+7) / 8; /* Top (partial) byte should be zero. */ if (bignum_byte(out, bytes - 1) != 0) ret = 0; /* First whole byte should be 1. */ if (bignum_byte(out, bytes - 2) != 1) ret = 0; /* Most of the rest should be FF. */ for (i = bytes - 3; i >= 20; i--) { if (bignum_byte(out, i) != 0xFF) ret = 0; } /* Finally, we expect to see the SHA-1 hash of the signed data. */ SHA_Simple( data.data(), data.size(), hash ); for (i = 19, j = 0; i >= 0; i--, j++) { if (bignum_byte(out, i) != hash[j]) ret = false; } freebn(out); return ret; }
bool Miller(unsigned long long N) { if(N<2)return false; else if(N<4) return true; else if((N&1)==0)return false; unsigned long long D=N-1,S=0; while((D&1)==0) { D>>=1; S++; } for(int a=0;a<5;a++) { unsigned long long ad=modpow(rand()%(N-4)+2,D,N); if(ad==1||ad==N-1) continue; for(unsigned long long r=0;r<S-1;r++) if((ad=modmult(ad,ad,N))==N-1) goto BPP; return false; BPP:; } return true; }
int main(){ long long int t,i,j,k; long long int V,N; scanf("%lld",&t); while(t--){ long long int P[100]; long long int Q[100]; long long int L[100]; long long int V,N,p0,p1,A0,B0,C0,M0,q0,q1,A1,B1,C1,M1; scanf("%lld %lld",&V,&N); scanf("%lld %lld %lld %lld %lld %lld",&p0,&p1,&A0,&B0,&C0,&M0); scanf("%lld %lld %lld %lld %lld %lld",&q0,&q1,&A1,&B1,&C1,&M1); P[0] = p0; P[1] = p1; Q[0] = q0; Q[1] = q1; for(j=2;j<N;j++){ P[j] = ( A0*A0*P[j-1] + B0*P[j-2] + C0 )%M0; Q[j] = ( A1*A1*Q[j-1] + B1*Q[j-2] + C1 )%M1; } for(j=0;j<N;j++){ L[j] = P[j]*(M1)+ Q[j] + 1; } long long int ans,temp; ans = V; for(j=0;j<N;j++){ ans = (modpow(ans,L[j]-1,MOD))%MOD; } printf("%lld\n",ans); } return 0; }
int main(int argc, char*argv[]) { // transform size (must be prime) unsigned int nfft = 17; int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // validate input if ( nfft <= 2 || !is_prime(nfft)) { fprintf(stderr,"error: %s, input transform size must be prime and greater than two\n", argv[0]); exit(1); } unsigned int i; // create and initialize data arrays float complex * x = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y_test = (float complex *) malloc(nfft * sizeof(float complex)); if (x == NULL || y == NULL || y_test == NULL) { fprintf(stderr,"error: %s, not enough memory for allocation\n", argv[0]); exit(1); } for (i=0; i<nfft; i++) { //x[i] = randnf() + _Complex_I*randnf(); x[i] = (float)i + _Complex_I*(3 - (float)i); y[i] = 0.0f; } // compute output for testing dft_run(nfft, x, y_test, DFT_FORWARD, 0); // // run Rader's algorithm // // compute primitive root of nfft unsigned int g = primitive_root(nfft); // create and initialize sequence unsigned int * s = (unsigned int *)malloc((nfft-1)*sizeof(unsigned int)); for (i=0; i<nfft-1; i++) s[i] = modpow(g, i+1, nfft); #if DEBUG printf("computed primitive root of %u as %u\n", nfft, g); // generate sequence (sanity check) printf("s = ["); for (i=0; i<nfft-1; i++) printf("%4u", s[i]); printf("]\n"); #endif // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft-1 // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0 // NOTE: R can be pre-computed float complex * r = (float complex*)malloc((nfft-1)*sizeof(float complex)); float complex * R = (float complex*)malloc((nfft-1)*sizeof(float complex)); for (i=0; i<nfft-1; i++) r[i] = cexpf(-_Complex_I*2*M_PI*s[i]/(float)(nfft)); dft_run(nfft-1, r, R, DFT_FORWARD, 0); // compute DFT of permuted sequence, size: nfft-1 float complex * xp = (float complex*)malloc((nfft-1)*sizeof(float complex)); float complex * Xp = (float complex*)malloc((nfft-1)*sizeof(float complex)); for (i=0; i<nfft-1; i++) { // reverse sequence unsigned int k = s[nfft-1-i-1]; xp[i] = x[k]; } dft_run(nfft-1, xp, Xp, DFT_FORWARD, 0); // compute inverse FFT of product for (i=0; i<nfft-1; i++) Xp[i] *= R[i]; dft_run(nfft-1, Xp, xp, DFT_REVERSE, 0); // set DC value y[0] = 0.0f; for (i=0; i<nfft; i++) y[0] += x[i]; // reverse permute result, scale, and add offset x[0] for (i=0; i<nfft-1; i++) { unsigned int k = s[i]; y[k] = xp[i] / (float)(nfft-1) + x[0]; } // free internal memory free(r); free(R); free(xp); free(Xp); free(s); // // print results // for (i=0; i<nfft; i++) { printf(" y[%3u] = %12.6f + j*%12.6f (expected %12.6f + j%12.6f)\n", i, crealf(y[i]), cimagf(y[i]), crealf(y_test[i]), cimagf(y_test[i])); } // compute error float rmse = 0.0f; for (i=0; i<nfft; i++) { float e = cabsf(y[i] - y_test[i]); rmse += e*e; } rmse = sqrtf(rmse / (float)nfft); printf("RMS error : %12.4e (%s)\n", rmse, rmse < 1e-3 ? "pass" : "FAIL"); // free allocated memory free(x); free(y); free(y_test); return 0; }
/* * 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; }
Bignum RSAKey::Encrypt(const Bignum input) const { return modpow( input, this->exponent, this->modulus ); }
/** \brief Preforms RSA decryption on ciphertext c using exponent d and modulus n * c^d mod n * * \param c int Ciphertext * \param d int Private Exponent * \param n int Modulus * \return int Plaintext * */ int RSA::decode(int c, int d, int n) { int m; m = modpow(c, d, n); return m; }
int dsa_generate(struct dss_key *key, int bits, progfn_t pfn, void *pfnparam) { Bignum qm1, power, g, h, tmp; unsigned pfirst, qfirst; int progress; /* * 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, PROGFN_PHASE_EXTENT, 1, 0x2800); pfn(pfnparam, PROGFN_EXP_PHASE, 1, -0x1D57C4 / 160); pfn(pfnparam, PROGFN_PHASE_EXTENT, 2, 0x40 * bits); pfn(pfnparam, PROGFN_EXP_PHASE, 2, -0x1D57C4 / bits); /* * In phase three we are finding an order-q element of the * multiplicative group of p, by finding an element whose order * is _divisible_ by q and raising it to the power of (p-1)/q. * _Most_ elements will have order divisible by q, since for a * start phi(p) of them will be primitive roots. So * realistically we don't need to set this much below 1 (64K). * Still, we'll set it to 1/2 (32K) to be on the safe side. */ pfn(pfnparam, PROGFN_PHASE_EXTENT, 3, 0x2000); pfn(pfnparam, PROGFN_EXP_PHASE, 3, -32768); /* * In phase four we are finding an element x between 1 and q-1 * (exclusive), by inventing 160 random bits and hoping they * come out to a plausible number; so assuming q is uniformly * distributed between 2^159 and 2^160, the chance of any given * attempt succeeding is somewhere between 0.5 and 1. Lacking * the energy to arrange to be able to specify this probability * _after_ generating q, we'll just set it to 0.75. */ pfn(pfnparam, PROGFN_PHASE_EXTENT, 4, 0x2000); pfn(pfnparam, PROGFN_EXP_PHASE, 4, -49152); pfn(pfnparam, PROGFN_READY, 0, 0); invent_firstbits(&pfirst, &qfirst); /* * Generate q: a prime of length 160. */ key->q = primegen(160, 2, 2, NULL, 1, pfn, pfnparam, qfirst); /* * Now generate p: a prime of length `bits', such that p-1 is * divisible by q. */ key->p = primegen(bits-160, 2, 2, key->q, 2, pfn, pfnparam, pfirst); /* * Next we need g. Raise 2 to the power (p-1)/q modulo p, and * if that comes out to one then try 3, then 4 and so on. As * soon as we hit a non-unit (and non-zero!) one, that'll do * for g. */ power = bigdiv(key->p, key->q); /* this is floor(p/q) == (p-1)/q */ h = bignum_from_long(1); progress = 0; while (1) { pfn(pfnparam, PROGFN_PROGRESS, 3, ++progress); g = modpow(h, power, key->p); if (bignum_cmp(g, One) > 0) break; /* got one */ tmp = h; h = bignum_add_long(h, 1); freebn(tmp); } key->g = g; freebn(h); /* * Now we're nearly done. All we need now is our private key x, * which should be a number between 1 and q-1 exclusive, and * our public key y = g^x mod p. */ qm1 = copybn(key->q); decbn(qm1); progress = 0; while (1) { int i, v, byte, bitsleft; Bignum x; pfn(pfnparam, PROGFN_PROGRESS, 4, ++progress); x = bn_power_2(159); byte = 0; bitsleft = 0; for (i = 0; i < 160; i++) { if (bitsleft <= 0) bitsleft = 8, byte = random_byte(); v = byte & 1; byte >>= 1; bitsleft--; bignum_set_bit(x, i, v); } if (bignum_cmp(x, One) <= 0 || bignum_cmp(x, qm1) >= 0) { freebn(x); continue; } else { key->x = x; break; } } freebn(qm1); key->y = modpow(key->g, key->x, key->p); return 1; }
/** * get_shared_key(uint64_t partner_public, uint64_t own_secret, uint64_t prime): * * SYNOPSIS * Gets the shared key for our the given public key of our partner, * our own secret, and the prime * * RETURN VALUE * 64-bit integer */ uint64_t get_shared_key(uint64_t partner_public, uint64_t own_secret, uint64_t prime) { return modpow(partner_public, own_secret, prime); }
/** * gen_public_key(uint64_t g, uint64_t secret, uint64_t prime): * * SYNOPSIS * Generates the public key * * RETURN VALUE * 64-bit integer */ uint64_t gen_public_key(uint64_t g, uint64_t secret, uint64_t prime) { return modpow(g, secret, prime); }
/* * Generate a prime. We arrange to select a prime with the property * (prime % modulus) != residue (to speed up use in RSA). */ Bignum primegen(int bits, int modulus, int residue, int phase, progfn_t pfn, void *pfnparam) { int i, k, v, byte, bitsleft, check, checks; unsigned long delta, moduli[NPRIMES+1], residues[NPRIMES+1]; Bignum p, pm1, q, wqp, wqp2; int progress = 0; byte = 0; bitsleft = 0; STARTOVER: pfn(pfnparam, phase, ++progress); /* * Generate a k-bit random number with top and bottom bits set. */ p = newbn((bits+15)/16); for (i = 0; i < bits; i++) { if (i == 0 || i == bits-1) v = 1; else { if (bitsleft <= 0) bitsleft = 8; byte = random_byte(); v = byte & 1; byte >>= 1; bitsleft--; } bignum_set_bit(p, i, v); } /* * Ensure this random number is coprime to the first few * primes, by repeatedly adding 2 to it until it is. */ for (i = 0; i < NPRIMES; i++) { moduli[i] = primes[i]; residues[i] = bignum_mod_short(p, primes[i]); } moduli[NPRIMES] = modulus; residues[NPRIMES] = (bignum_mod_short(p, (unsigned short)modulus) + modulus - residue); delta = 0; while (1) { for (i = 0; i < (sizeof(moduli) / sizeof(*moduli)); i++) if (!((residues[i] + delta) % moduli[i])) break; if (i < (sizeof(moduli) / sizeof(*moduli))) {/* we broke */ delta += 2; if (delta < 2) { freebn(p); goto STARTOVER; } continue; } break; } q = p; p = bignum_add_long(q, delta); freebn(q); /* * Now apply the Miller-Rabin primality test a few times. First * work out how many checks are needed. */ checks = 27; if (bits >= 150) checks = 18; if (bits >= 200) checks = 15; if (bits >= 250) checks = 12; if (bits >= 300) checks = 9; if (bits >= 350) checks = 8; if (bits >= 400) checks = 7; if (bits >= 450) checks = 6; if (bits >= 550) checks = 5; if (bits >= 650) checks = 4; if (bits >= 850) checks = 3; if (bits >= 1300) checks = 2; /* * Next, write p-1 as q*2^k. */ for (k = 0; bignum_bit(p, k) == !k; k++); /* find first 1 bit in p-1 */ q = bignum_rshift(p, k); /* And store p-1 itself, which we'll need. */ pm1 = copybn(p); decbn(pm1); /* * Now, for each check ... */ for (check = 0; check < checks; check++) { Bignum w; /* * Invent a random number between 1 and p-1 inclusive. */ while (1) { w = newbn((bits+15)/16); for (i = 0; i < bits; i++) { if (bitsleft <= 0) bitsleft = 8; byte = random_byte(); v = byte & 1; byte >>= 1; bitsleft--; bignum_set_bit(w, i, v); } if (bignum_cmp(w, p) >= 0 || bignum_cmp(w, Zero) == 0) { freebn(w); continue; } break; } pfn(pfnparam, phase, ++progress); /* * Compute w^q mod p. */ wqp = modpow(w, q, p); freebn(w); /* * See if this is 1, or if it is -1, or if it becomes -1 * when squared at most k-1 times. */ if (bignum_cmp(wqp, One) == 0 || bignum_cmp(wqp, pm1) == 0) { freebn(wqp); continue; } for (i = 0; i < k-1; i++) { wqp2 = modmul(wqp, wqp, p); freebn(wqp); wqp = wqp2; if (bignum_cmp(wqp, pm1) == 0) break; } if (i < k-1) { freebn(wqp); continue; } /* * It didn't. Therefore, w is a witness for the * compositeness of p. */ freebn(p); freebn(pm1); freebn(q); goto STARTOVER; } /* * We have a prime! */ freebn(q); freebn(pm1); return p; }
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; }
/** \brief Preforms RSA decryption on ciphertext c using exponent d and modulus n * c^d mod n * * \param c int Ciphertext * \param d int Private Exponent * \param n int Modulus * \return int Plaintext * */ int decodeRSA(int c, int d, int n) { int m; m = modpow(c, d, n); return m; }
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; }
/** \brief Preforms RSA encryption on plaintext m using exponent e and modulus n\n * m^e mod n * * \param m int Plaintext * \param e int Encryption Exponent * \param n int Modulus * \return int Ciphertext * */ int encodeRSA(int m, int e, int n) { int c; c = modpow(m, e, n); return c; }