#include #include #include // modexp 0857bde36f680cda9535784bc4aec5f4344131071b419f732ac9c74d0e61db49dd958c7344236e0279df009c6e66aec6ba574c2820d4aeb0c4d814c8e184c6ea7e6d8aa3e15d1c251c78c5364ea2b3edb3c19e90739afa765506242e78fcdc71a87efdfe2df6ce6039fc62cb3b360cb77cd5574292282df352886cbc3fcfbff2 10001 F765A3A0C9C291D81A56FE73794A746B8DA23DBE155D0D495B49D581B5C6545F449A10FDF1C26A92FBD1F43A0687044927A6A21B69A73999E6083D03ACDAFFA6409F1BC71D810628F6E18F76231ED6E22D54ED2502E66F8A33D0D5F07B3EB605F7418110E2EF9A5EE77B070F4EADFCF3D70C53E870F29C9D4F229F2CB6C25383 typedef unsigned char num_t; // all numbers are stored least significant byte first. // all numbers contain a number of max len, and have space for 1 extra byte void writenum(const num_t *num, int len); void rightshift(num_t *val, int len) { int carry= 0; for (int i=len-1 ; i>=0 ; i--) { carry |= val[i]; val[i]= carry>>1; carry &= 1; carry <<= 8; } } void leftshift(num_t *val, int len) { int carry= 0; for (int i=0 ; i>= 8; carry &= 1; } } void big_add(num_t *sum, const num_t *val, int len) { int carry=0; //writenum(sum, len); printf(" + "); writenum(val, len); for (int i=0 ; i>= 8; } //printf(" = "); writenum(sum, len); printf("\n"); } void big_sub(num_t *sum, const num_t *val, int len) { int carry=0; //writenum(sum, len); printf(" - "); writenum(val, len); for (int i=0 ; i>= 8; //printf("=%x:%x\n", carry, sum[i]); } //printf(" = "); writenum(sum, len); printf("\n"); } void modtrunc(num_t *val, const num_t *mod, int len) { //printf("modtrunc "); writenum(val, len); printf(" : "); writenum(mod, len); printf("\n"); int i=len-1; while (i>0 && val[i]==mod[i]) { i--; } if (val[i]>=mod[i]) { //printf("mod trunc %d: %02X >= %02X\n", i, val[i], mod[i]); big_sub(val, mod, len); } } void big_mulmod(num_t *val, const num_t *mult, const num_t *mod, int len) { //printf("calc mulmod "); //writenum(val, len); printf(" x "); //writenum(mult, len); printf(" mod "); //writenum(mod, len); printf("\n"); num_t *bits=(num_t*)alloca(len); memcpy(bits, val, len); num_t *lshifter=(num_t*)alloca(len+1); memcpy(lshifter, mult, len); lshifter[len]=0; memset(val, 0, len); for (int i=0 ; i=0 ; i--, j++) { if (j&1) { num[j/2] |= digit2val(hexstr[i])<<4; } else { num[j/2] = digit2val(hexstr[i]); } } if (j&1) j++; j/=2; while (j0) i--; while (i>=0) { printf("%02X", num[i]); i--; } } int main(int argc, char **argv) { if (argc!=4) { printf("Usage: modexp num exp mod\n"); return 1; } char *numstr= argv[1]; char *expstr= argv[2]; char *modstr= argv[3]; // strip leading zeros while (*numstr=='0') numstr++; while (*expstr=='0') expstr++; while (*modstr=='0') modstr++; int numlen= strlen(numstr)/2+2; int explen= strlen(expstr)/2+2; int modlen= strlen(modstr)/2+2; if (numlen>modlen) { printf("number cannot be larger than mod\n"); return 1; } int len= modlen; num_t *num= (num_t*)alloca(len); num_t *exp= (num_t*)alloca(explen); num_t *mod= (num_t*)alloca(len); hexstr2num(num, len, numstr); hexstr2num(exp, explen, expstr); hexstr2num(mod, len, modstr); //printf("num="); writenum(num, len); printf("\n"); //printf("mod="); writenum(mod, len); printf("\n"); //printf("exp="); writenum(exp, explen); printf("\n"); num_t *result= (num_t*)alloca(len); modexp(num, exp, explen, mod, result, len); writenum(result, len); printf("\n"); }