// 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(); } } }
/** Get value of big integer. * * Allows to obtain the value of big integer, provided that it fits * into a small integer. * * @param bigint Bigint to obtain value from. * @param dval Place to store value. * @return EOK on success, ELIMIT if bigint is too big to fit * to @a dval. */ int bigint_get_value_int(bigint_t *bigint, int *dval) { bigint_t vval, diff; size_t idx; int val; bool_t zf; #ifdef DEBUG_BIGINT_TRACE printf("Get int value of bigint.\n"); #endif val = 0; for (idx = 0; idx < bigint->length; ++idx) { val = val * BIGINT_BASE + bigint->digit[idx]; } if (bigint->negative) val = - val; /* If the value did not fit @c val now contains garbage. Verify. */ bigint_init(&vval, val); bigint_sub(bigint, &vval, &diff); zf = bigint_is_zero(&diff); bigint_destroy(&vval); bigint_destroy(&diff); /* If the difference is not zero, the verification failed. */ if (zf != b_true) return EINVAL; *dval = val; return EOK; }
//Uses subtraction repeatedly to find the remainder and the quotient. //Stores the remainder in a new bigint and uses 'pos' to store the quotient. //returns this new bigint bigint get_remainder_quotient(bigint dividend, bigint divisor){ int quotient = 0; while(compare_bigint(dividend, divisor)>=0){ dividend = bigint_sub(dividend,divisor); quotient+=1; } dividend.pos = quotient;//Will be 1 anyway, but to ensure it. Not very crucial. return dividend; }
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; }
// Adds two bigints and returns the result which is a bigint bigint bigint_add(bigint a, bigint b){ //If they are of the opposite signs, then send them for subtraction if(a.pos==0&&b.pos==1||a.pos==1&&b.pos==0){ if(a.pos==0){ a.pos = 1;//Make it positive and send it for subtraction. return bigint_sub(b,a);//Returns (b-a) } else{ b.pos = 1;//Make it positive and send it for subtraction. return bigint_sub(a,b);//Returns (a-b) } } //If of the same sign, then add. else{ bigint bigger_num, smaller_num;// Here the bigger number is in terms of the absolute quantity. if(!a.pos){ if(compare_bigint(a,b)==1){ bigger_num = b; smaller_num = a; } else if(compare_bigint(a,b)==-1){ bigger_num = a; smaller_num = b; } else{ //Both are equal. Assign any number to any variable. bigger_num = a; smaller_num = b; } } else{ if(compare_bigint(a,b)==1){ bigger_num = a; smaller_num = b; } else if(compare_bigint(a,b)==-1){ bigger_num = b; smaller_num = a; } else{ //Both are equal. Assign any number to any variable. bigger_num = b; smaller_num = a; } } //At this point, bigger_num has the larger number in absolute terms. The 'smaller_num' contains the other. //Now, create a new character array which can hold the sum of the two terms and pass that array to make_bigint //For the new character array, assign memory 1 greater than the length of the bigger_num. //In case the left hand most field doesn't get filled up, then assign 0 to it. make_bigint takes care of that. int new_length = bigger_num.length+1;//This length excludes the negative sign. char* new_value; if(bigger_num.pos==0){ new_value = (char*)malloc((new_length+1+1)*sizeof(char));//+1 for the negative sign and +1 for terminating it with NULL new_value[0] = '-'; new_value[new_length+1] = '\0';//Terminating with a null character } else{ new_value = (char*)malloc((new_length+1)*sizeof(char));//+1 for terminating it with null. new_value[new_length] = '\0';//Terminating with a null character } addValues(bigger_num, smaller_num, new_value, new_length);//Does string addition and stores the result in new_value return make_bigint(new_value); }//Else ends }
BigInt operator-(const BigInt& x, word y) { return bigint_sub(x, &y, 1, BigInt::Positive); }
BigInt operator-(const BigInt& x, const BigInt& y) { return bigint_sub(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); }