// Subtracts two bigints and returns the result which is a bigint // Returns a-b bigint bigint_sub(bigint a, bigint b){ if(a.pos==0&&b.pos==1){ b.pos = 0; return bigint_add(a,b); } else if(a.pos==1&&b.pos==0){ b.pos = 1; return bigint_add(a,b); } //At this point, both the numbers are of the same sign. So, a normal subtraction will work. else{ int max_num = compare_bigint(a,b); //Case: a>b and both are negative. Example: a = -20 ; b = -30 //a-b = (-x) - (-y) = y-x. 'y' and 'x' are positive. And 'y' is greater than 'x'. if(a.pos==0 && max_num==1){ b.pos = 1; a.pos = 1; return bigint_sub(b,a);//Returns (y-x). 'y' and 'x' are positive. } //Case: b>a and both are negative //a-b = (-x) - (-y) = y-x. 'y' and 'x' are positive. 'x' is greater than 'y'. //So, do x-y and then change the sign to negative. Then return. else if(a.pos==0 && max_num==-1){ a.pos = 1; b.pos = 1; bigint tempNo = bigint_sub(a,b); tempNo.pos = 0; return tempNo; } // Case: b>a and both are positive // a-b = x-y. 'x' and 'y' are positive // Do y-x and change the sign, then return. else if(a.pos==1 && max_num==-1){ bigint tempNo = bigint_sub(b,a); tempNo.pos = 0; return tempNo; } //Case: a>b and both are positive else if(a.pos==1 && max_num==1){ return borrow_subtraction(a,b); } //Case: Both are equal. Return 0. else{ return init_bigint(); } } }
// Multiplies two big ints and returns a bigint bigint bigint_mul(bigint a, bigint b){ // Idea: Multiply the bigger number by a digit of the smaller number. Then shift by the digit's 10's place. Add this newly found // multiplication to the already calculated result. Keep adding until all the digits of the smaller number exhaust. bigint multiplicand_table[9];// [0] stores the multiplicand. [1] stores multiplicand*2. [2] stores multiplicand*3 and so on. int positive = 0;//Stores whether the multiplication is positive or negative. 0 means negative. 1 means positive. if((a.pos==0 && b.pos==0)||(a.pos==1 && b.pos==1)) positive = 1; else positive = 0; a.pos = 1; b.pos = 1;//Make both the numbers positive for multiplication. int compare = compare_bigint(a,b); bigint bigger_num, smaller_num; //If 'a' is greater than or equal to 'b' then do this. if(compare==1||compare==0){ bigger_num = a; smaller_num = b; } //If 'b' is greater than 'a' then do this. else{ bigger_num = b; smaller_num = a; } //Now fill the multiplicand table from 1 to 9. multiplicand_table[0] = bigger_num;// bigger_num*1 multiplicand_table[1] = bigint_add(bigger_num,bigger_num);// bigger_num*2 multiplicand_table[2] = bigint_add(multiplicand_table[1],multiplicand_table[0]);//bigger_num*3 multiplicand_table[3] = bigint_add(multiplicand_table[2], multiplicand_table[0]);//bigger_num*4 multiplicand_table[4] = bigint_add(multiplicand_table[3], multiplicand_table[0]);//bigger_num*5 multiplicand_table[5] = bigint_add(multiplicand_table[4], multiplicand_table[0]);//bigger_num*6 multiplicand_table[6] = bigint_add(multiplicand_table[5], multiplicand_table[0]);//bigger_num*7 multiplicand_table[7] = bigint_add(multiplicand_table[6], multiplicand_table[0]);//bigger_num*8 multiplicand_table[8] = bigint_add(multiplicand_table[7], multiplicand_table[0]);//bigger_num*9 bigint result = init_bigint(); int i = 0;//iterator for(i = smaller_num.length-1;i>=0;i--){ if((smaller_num.value[i]-48)>=1){//Only if the digit is non zero will it add to the result. bigint tempNum = shift_by_power_of_10(multiplicand_table[smaller_num.value[i]-48-1],(smaller_num.length-1-i)); result = bigint_add(result, tempNum); } } result.pos = positive; return result; }
/** Multiply two big integers. * * The big integers @a a and @a b are multiplied and the result is stored in * @a dest. * * @param a First factor. * @param b Second factor. * @param dest Destination bigint. */ void bigint_mul(bigint_t *a, bigint_t *b, bigint_t *dest) { size_t idx; bigint_t dprod; bigint_t sum; bigint_t tmp; #ifdef DEBUG_BIGINT_TRACE printf("Multiply bigints.\n"); #endif bigint_init(&sum, 0); for (idx = 0; idx < b->length; ++idx) { bigint_shift_mul_dig(a, b->digit[idx], idx, &dprod); bigint_add(&dprod, &sum, &tmp); bigint_destroy(&dprod); bigint_destroy(&sum); bigint_shallow_copy(&tmp, &sum); } if (b->negative) sum.negative = !sum.negative; bigint_shallow_copy(&sum, dest); }
/** * Generate a truly random KUID within given `kuid'. */ void kuid_random_fill(kuid_t *kuid) { struct sha1 entropy; bigint_t bk, be; /* * Entropy collection is slow but we generate our KUID only at startup * and when none was present (nodes reuse their KUID from session to * session to reuse as much of their previous routing table as possible). * * The aim is to obtain the most random KUID to ensure that among all * the peers in the Kademlia network, KUIDs are unique and uniformly * distributed in the KUID space. */ entropy_collect(&entropy); /* slow */ random_strong_bytes(kuid->v, KUID_RAW_SIZE); /* * Combine the two random numbers by adding them. * * It's slightly better than XOR-ing the two since the propagation * of the carry bit diffuses the randomness (entropy remains the same). */ STATIC_ASSERT(sizeof kuid->v == sizeof entropy.data); bigint_use(&bk, kuid->v, sizeof kuid->v); bigint_use(&be, entropy.data, sizeof entropy.data); (void) bigint_add(&bk, &be); }
void bii_monproduct(bigint *dest, bigint abar, bigint bbar, bigint n, bigint nprime, uint32_t rpow){ bigint t, m, u, tmp1, tmp2; bigint_init(&t); bigint_init(&m); bigint_init(&u); bigint_init(&tmp1); bigint_init(&tmp2); bigint_multiply(&t, abar, bbar); bigint_multiply(&tmp1, t, nprime); bigint_getsigbits(&m, tmp1, rpow); bigint_multiply(&tmp1, m,n); bigint_add(&u,t,tmp1); bigint_rightshift(&u,rpow); if(bigint_cmp(u,n)>=0) bigint_subtract(dest,u,n); else bigint_setval(dest, u); bigint_free(&t); bigint_free(&m); bigint_free(&u); bigint_free(&tmp1); bigint_free(&tmp2); }
int bigint_multiply(bigint_s *dst, bigint_s *a, bigint_s *b) { if (!dst || !a || !b || !dst->bytes || !a->bytes || !b->bytes) return BIGINT_INVALID_ARGUMENT; if (a->bytes_alloced != b->bytes_alloced) return BIGINT_DIFFRENT_SIZE; // TODO: allow different sizes (padding) uint32_t buffer_size = dst->bytes_alloced; /* * multiply two big numbers (in columns with carry) * assuming that: * (b-number) first row * x (a-number) second row * ------------- * result */ bool add = false; for (uint32_t i = 0; i < a->bytes_used; i++) { // second row on paper bigint_s tmp; bigint_init(&tmp); uint32_t k = i; uint16_t rest = 0, carry = 0; for (uint32_t j = 0; j < b->bytes_used; j++) { uint16_t result = (uint16_t) a->bytes[i] * (uint16_t) b->bytes[j] + carry; carry = result/BIGINT_BASE; rest = result % BIGINT_BASE; if (k >= buffer_size) return BIGINT_OUT_OF_MEMORY; tmp.bytes[k++] = (uint8_t) rest; } if (k >= buffer_size) return BIGINT_OUT_OF_MEMORY; if (carry > 0) tmp.bytes[k++] = (uint8_t) carry; tmp.bytes_used = k; if (!add) { bigint_swap(dst, &tmp); add = true; } else { bigint_s r; bigint_init(&r); int rr = bigint_add(&r, dst, &tmp); if (rr != BIGINT_OK) return rr; bigint_swap(dst, &r); bigint_free(&r); } while (dst->bytes_used > 0 && dst->bytes[dst->bytes_used - 1] == 0) { dst->bytes_used--; } // sometimes result is prefixed with zeros, cutting them off bigint_free(&tmp); } return BIGINT_OK; }
/** * Add entropy from previous calls. */ static G_GNUC_COLD void entropy_merge(sha1_t *digest) { bigint_t older, newer; /* * These big integers operate on the buffer space from ``digest'' and * ``entropy_previous'' directly. */ bigint_use(&older, &entropy_previous, SHA1_RAW_SIZE); bigint_use(&newer, digest, SHA1_RAW_SIZE); bigint_add(&newer, &older); bigint_copy(&older, &newer); }
int crypto_stream_salsa20_xor( unsigned char *c, const unsigned char *m,crypto_uint16 mlen, const unsigned char *n,const unsigned char *k ) { unsigned char z[16],x[64],u[8],i; for(i=0;i<8;i++) { z[i] = n[i]; z[i+8] = 0; u[i] = 0; } u[0] = 1; while (mlen >= 64) { if(m) { crypto_core_salsa20(x,z,k,sigma); for(i=0;i<64;i++) c[i] = m[i] ^ x[i]; } else crypto_core_salsa20(c,z,k,sigma); bigint_add(z+8,z+8,u,8); mlen -= 64; c += 64; if (m) m += 64; } if (mlen) { crypto_core_salsa20(x,z,k,sigma); if(m) for(i=0;i<mlen;i++) c[i] = x[i] ^ m[i]; else for(i=0;i<mlen;i++) c[i] = x[i]; } return 0; }
int crypto_stream_xor( unsigned char *c, const unsigned char *m,crypto_uint16 mlen, const unsigned char *n, const unsigned char *k ) { unsigned char in[16]; unsigned char block[64]; unsigned char u[8]; unsigned char i; if (!mlen) return 0; for (i = 0;i < 8;++i) { in[i] = n[i]; u[i] = 0; } for (i = 8;i < 16;++i) in[i] = 0; u[0]=1; while (mlen >= 64) { crypto_core(block,in,k,sigma); bigint_xor(c,m,block,64); bigint_add(&(in[8]),&(in[8]),&(u[0]),8); mlen -= 64; c += 64; m += 64; } if (mlen) { crypto_core(block,in,k,sigma); bigint_xor(c,m,block,(int)mlen); } return 0; }
int main( int argc, char* argv[] ) { char cmd[ BUF_SIZE ]; // NOTE: Uncomment this once you've implemented this function bigint result = init_bigint(); //bigint result; // At the end of every arithmetic operation update the result. // In an infinite loop, get input from user while( 1 ) { char* op = NULL; // Store the operation // Get a line of input from the user fgets( cmd, BUF_SIZE, stdin ); // Parse the line using strtok // Note: Given a string like "a b c d", strtok returns "a" the first // time it's called, and "b", "c", "d" and NULL subsequently, if the // first argument is NULL. Read the manpage for more details op = strtok( cmd, " " ); // If the last line is a new line, make it a null character int len = strlen( op ); if( op[ len-1 ] == '\n' ) op[ len-1 ] = 0; // Match the operation, and do appropriate action if( strcmp( op, "quit" ) == 0 || op[0] == EOF ) { // Quit when you see this break; } else if( strcmp( op, "set" ) == 0 ) { // set <data> // Sets a big int value to data int data; if( read_args1( &data ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting // printf( "Setting value as %d\n", data ); // NOTE: Uncomment this once you've implemented this function result = int_to_bigint(data); } } else if( strcmp( op, "add" ) == 0 ) { // add <num1> <num2> // Adds two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Add %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_add( a, b); print_bigint(result); } } else if( strcmp( op, "sub" ) == 0 ) { // sub <num1> <num2> // Subtracts two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Subtract %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_sub( a, b); print_bigint(result); printf("\n"); } } else if( strcmp( op, "mul" ) == 0 ) { // mul <num1> <num2> // Multiplies two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Multiply %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_mul( a, b); print_bigint(result); } } else if( strcmp( op, "div" ) == 0 ) { // add <num1> <num2> // Adds two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Divide %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_div( a, b); print_bigint(result); } } else { printf( "Invalid command\n" ); } } return 0; }
BigInt operator+(const BigInt& x, word y) { return bigint_add(x, &y, 1, BigInt::Positive); }
BigInt operator+(const BigInt& x, const BigInt& y) { return bigint_add(x, y.data(), y.sig_words(), y.sign()); }
/* * RSA Sign using Garners algorithm and Chinese Remainder theorem. * See the derivation on page 613 in handbook of applied cryptography * use factors dp and dq of secret exponent d and p and q of public * exponent n, and qinv */ void CSL_ComputeRsaSigFast(u8 *result, u32 *message, u32 *certpublickey, u32 *certp, u32 *certq, u32 *dmp, u32 *dmq, u32 *qinv, int num_bits) { u32 pDigits, qDigits, cDigits, nDigits; bigint_digit bigp[MAX_BIGINT_DIGITS]; bigint_digit bigq[MAX_BIGINT_DIGITS]; bigint_digit bigc[MAX_BIGINT_DIGITS]; bigint_digit bigdmp[MAX_BIGINT_DIGITS]; bigint_digit bigdmq[MAX_BIGINT_DIGITS]; bigint_digit bigqinv[MAX_BIGINT_DIGITS]; bigint_digit bign[MAX_BIGINT_DIGITS]; bigint_digit cP[MAX_BIGINT_DIGITS]; bigint_digit cQ[MAX_BIGINT_DIGITS]; bigint_digit mP[MAX_BIGINT_DIGITS]; bigint_digit mQ[MAX_BIGINT_DIGITS]; bigint_digit temp[MAX_BIGINT_DIGITS]; int outlen; int i; int num_words = num_bits/BIGINT_DIGIT_BITS; bigint_zero(bigp, MAX_BIGINT_DIGITS); bigint_zero(bigq, MAX_BIGINT_DIGITS); bigint_zero(bigdmp, MAX_BIGINT_DIGITS); bigint_zero(bigdmq, MAX_BIGINT_DIGITS); bigint_zero(bigqinv, MAX_BIGINT_DIGITS); bigint_zero(bigc, MAX_BIGINT_DIGITS); for (i = 0; i < num_words/2; i++) { bigp[num_words/2 - 1 - i] = certp[i]; bigq[num_words/2 - 1 - i] = certq[i]; bigdmp[num_words/2 - 1 - i] = dmp[i]; bigdmq[num_words/2 - 1 - i] = dmq[i]; bigqinv[num_words/2 - 1 - i] = qinv[i]; } for (i = 0; i < num_words; i++) { bigc[num_words - 1 - i] = message[i]; bign[num_words - 1 - i] = certpublickey[i]; } cDigits = bigint_digits(bigc, MAX_BIGINT_DIGITS); pDigits = bigint_digits(bigp, MAX_BIGINT_DIGITS); qDigits = bigint_digits(bigq, MAX_BIGINT_DIGITS); nDigits = bigint_digits(bign, MAX_BIGINT_DIGITS); /* * compute cP and cQ */ bigint_mod(cP, bigc, cDigits, bigp, pDigits); bigint_mod(cQ, bigc, cDigits, bigq, qDigits); /* * Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. */ bigint_mod_exp(mP, cP, bigdmp, pDigits, bigp, pDigits); bigint_zero(mQ, nDigits); bigint_mod_exp(mQ, cQ, bigdmq, pDigits, bigq, pDigits); /* * do CRT * m = ((((mP - mQ) mod p)*qinv) mod p) *q + mQ */ if (bigint_cmp(mP, mQ, pDigits) >= 0) { bigint_sub(temp, mP, mQ, pDigits); } else { bigint_sub(temp, mQ, mP, pDigits); bigint_sub(temp, bigp, temp, pDigits); } bigint_mod_mult(temp, temp, bigqinv, bigp, pDigits); bigint_mult(temp, temp, bigq, pDigits); bigint_add(temp, temp, mQ, nDigits); outlen = (num_bits + 7)/8; I2OSP(result, outlen, temp, nDigits); }
void bii_modexpeven(bigint *dest, bigint a, bigint e, bigint n){ /* * Returns a**e mod n for the case when n is even. * This algorithm is from the paper: * Montgomery reduction with even modulus * Koc,C.K. * IEE Proceedings - Computers and Digital Techniques(1994),141(5):314 * http://dx.doi.org/10.1049/ip-cdt:19941291 */ bigint q, j, A, E, x1, x2, y, qinv, tmp1, tmp2; bigint_init(&q); bigint_init(&j); bigint_init(&A); bigint_init(&E); bigint_init(&x1); bigint_init(&x2); bigint_init(&y); bigint_init(&qinv); bigint_init(&tmp1); bigint_init(&tmp2); //n = q * (2**jpow) bigint_setval(&q,n); uint32_t jpow = 0; bigint_setval32(&j,1); while(bigint_parity(q)==0){ bigint_rightshift(&q,1); bigint_leftshift(&j,1); jpow++; } bigint_divide(&tmp1,&A,a,q); bii_modexpodd(&x1, A, e, q); bigint_getsigbits(&A,a,jpow); bigint_getsigbits(&E, e, jpow-1); bii_binarymodpow_powerof2(&x2,A,E,jpow); bigint_setval32(&tmp1, 1); bigint_egcd(q,j,tmp1, &qinv,&tmp2); bigint_subtract(&tmp1,x2,x1); bigint_multiply(&tmp2,tmp1,qinv); bigint_divide(&tmp1,&y,tmp2,j); bigint_multiply(&tmp1,q,y); bigint_add(dest,x1,tmp1); bigint_free(&q); bigint_free(&j); bigint_free(&A); bigint_free(&E); bigint_free(&x1); bigint_free(&x2); bigint_free(&y); bigint_free(&qinv); bigint_free(&tmp1); bigint_free(&tmp2); }