void BigInt_PowerModulus(BigInt n, BigInt exp, BigInt modulus, BigInt answer) { DIGIT *eptr, *eend, emask; BigInt p, temp, r; r=BigInt_Zero(); /* If n is negative and the exponent is odd, the answer will be negative. */ int neg=(n->negative && (exp->digits[0]&0x01)); p=BigInt_Create(); temp=BigInt_Create(); if(modulus) r=BigInt_Create(); BigInt_Copy(p, n); p->negative=0; BigInt_Set(answer, 1); /* Continue this loop while the exponent is not zero */ eptr=exp->digits; eend=eptr+exp->length; emask=0x01; while(eptr<eend) { /* If e is odd, multiply the answer by p */ if((*eptr) & emask) { BigInt_Copy(temp, answer); BigInt_Multiply(temp, p, answer); if(modulus) { BigInt_Modulus(answer, modulus, r); BigInt_Copy(answer, r); } } /* Now square p (mod modulus, if supplied) */ BigInt_Multiply(p, p, temp); if(modulus) BigInt_Modulus(temp, modulus, p); else BigInt_Copy(p, temp); /* Shift e right by one bit */ emask<<=1; if(emask==0) { ++eptr; emask=0x01; } } answer->negative=neg; if(modulus) BigInt_Destroy(r); BigInt_Destroy(temp); BigInt_Destroy(p); }
void KG_GenerateEcdsaParameters(const char* encryptiontemplate, char* private_text, char* basepoint_text, char* public_x_text, char* public_y_text) { EC_PARAMETER Base; EC_KEYPAIR Signer; ECC_POINT temp; char encryption_template[512]; char rndinitstring[1024]; unsigned long i[4]; unsigned int basepointinit; BigInt test = BigInt_Create(); BigInt secretkeyhash = BigInt_Create(); BigInt prime_order = BigInt_Create(); CookText(encryption_template, encryptiontemplate); md5(i, encryption_template, strlen(encryption_template)); basepointinit = i[0]; sprintf(basepoint_text, "%u", basepointinit); ECC_InitializeTable(); BigInt_FromString(ECC_PRIMEORDER, 10, prime_order); BigIntToField(prime_order, &Base.pnt_order); Field_Clear(&Base.cofactor); Base.cofactor.e[ECC_NUMWORD] = 2; Base.crv.form = 1; Field_Set(&Base.crv.a2); Field_Set(&Base.crv.a6); InitRandomGenerator(basepointinit); ECC_RandomPoint(&temp, &Base.crv); ECC_PointDouble(&temp, &Base.pnt, &Base.crv); strcpy(rndinitstring, encryption_template); strcat(rndinitstring, "PVTKEY"); BigInt_Hash(rndinitstring, strlen(rndinitstring), secretkeyhash); ECC_KeyGenerationPrimitive(&Base, &Signer, secretkeyhash); FieldToBigInt(&Signer.pblc_key.x, test); BigInt_ToString(test, 10, public_x_text); FieldToBigInt(&Signer.pblc_key.y, test); BigInt_ToString(test, 10, public_y_text); FieldToBigInt(&Signer.prvt_key, test); BigInt_ToString(test, 10, private_text); BigInt_Destroy(test); BigInt_Destroy(secretkeyhash); BigInt_Destroy(prime_order); }
bool KG_GeneratePvtY(int level, char* keytemplate, char* pvt_text, char* y_text) { char tmp[256] = ""; BigInt p, p1, pub, pvt, y, temp, temp2; int size, keysystem; if(level == 29) { char basepoint_text[10] = "", public_x_text[100] = "", public_y_text[100] = ""; KG_GenerateEcdsaParameters(keytemplate, pvt_text, basepoint_text, public_x_text, public_y_text); sprintf(y_text, "%s,%s,%s", basepoint_text, public_x_text, public_y_text); return true; } else if(level >= 20) { keysystem = KS_SHORTV3; level = level - 20; if(level > 8) return false; } else if(level >= 10) { keysystem = KS_V3; level = level - 10; if(level > 8) return false; } else { keysystem = KS_V2; if(level<0 or level>3) return false; } size = level + 4; p = BigInt_Create(); p1 = BigInt_Create(); pub = BigInt_Create(); pvt = BigInt_Create(); y = BigInt_Create(); temp = BigInt_Create(); temp2 = BigInt_Create(); BigInt_Set(temp, 1); BigInt_Shift(temp, size * 8, p); BigInt_Set(temp, primeoffsets[level]); BigInt_Add(p, temp, temp2); BigInt_Copy(p, temp2); BigInt_Subtract(p, BigInt_One(), p1); sprintf(tmp, "%u Level Public Key", level); GenerateKeyNumberFromString(tmp, p, &pub, keysystem, ((keysystem == KS_V3 || keysystem == KS_SHORTV3) ? level + 1 : 0)); GenerateKeyNumberFromString(keytemplate, p, &pvt, keysystem, ((keysystem == KS_V3 || keysystem == KS_SHORTV3) ? level + 1 : 0)); BigInt_ToString(pvt, 16, pvt_text); BigInt_PowerModulus(pub, pvt, p, y); BigInt_ToString(y, 16, y_text); BigInt_Destroy(temp2); BigInt_Destroy(temp); BigInt_Destroy(y); BigInt_Destroy(pvt); BigInt_Destroy(pub); BigInt_Destroy(p1); BigInt_Destroy(p); return true; }
int BigInt_Divide(BigInt a, BigInt b, BigInt answer, BigInt remainder) { //TODO: fix something here (memleak temp1 or t) int compare, i, signa, signb; WORKING_DIGIT high, low, t; BigInt temp1, temp2; temp1=BigInt_Create(); temp2=BigInt_Create(); signa=a->negative; a->negative=0; signb=b->negative; b->negative=0; /* Check for divide-by-zero, it's not allowed */ if(b->length==1 && b->digits[0]==0) return 0; /* Compare a and b, to see if we can take a shortcut */ compare=BigInt_Compare_SignOptional(a, b, 1); if(compare<0) { BigInt_Set(answer, 0); BigInt_Copy(remainder, a); return 1; } else if(compare==0) { BigInt_Set(answer, 1); BigInt_Set(remainder, 0); return 1; } BigInt_Realloc(answer, a->length, 0); BigInt_Set(remainder, 0); for(i=1; i<=a->length; ++i) { /* remainder=(remainder<<BITS_PER_DIGIT)+a->digits[a->length-i]; */ BigInt_Copy(temp1, remainder); BigInt_Shift(temp1, BITS_PER_DIGIT, remainder); remainder->digits[0]=a->digits[a->length-i]; if(BigInt_Compare_SignOptional(remainder, b, 1)>=0) { high=OVERFLOW_DIGIT; low=0; while(low<high) { t=((high-low)/2)+low; /* if ((b*t)>remainder) high=t; else low=t+1; */ BigInt_Set(temp2, t); BigInt_Multiply(b, temp2, temp1); if(BigInt_Compare(temp1, remainder)>0) high=t; else low=t+1; } t=low-1; answer->digits[a->length-i]=(DIGIT)(t); /* remainder=remainder-(b*t) */ BigInt_Set(temp2, t); BigInt_Multiply(b, temp2, temp1); BigInt_Subtract(remainder, temp1, temp2); BigInt_Copy(remainder, temp2); } else answer->digits[a->length-i]=0; } a->negative=signa; b->negative=signb; answer->negative=(a->negative ^ b->negative); BigInt_FindMSD(answer); BigInt_Destroy(temp2); BigInt_Destroy(temp1); return 1; }
void BigInt_Add(BigInt a, BigInt b, BigInt answer) { DIGIT *ad, *bd, *ansd; int level=0, x, carry; WORKING_DIGIT n; BigInt savedb; savedb=BigInt_Zero(); /* Check for zeros */ if(a->length==0 || (a->length==1 && a->digits[0]==0)) { BigInt_Copy(answer, b); return; } else if(b->length==0 || (b->length==1 && b->digits[0]==0)) { BigInt_Copy(answer, a); return; } /* Handle mismatched signs, step 1 */ if(a->negative!=b->negative) { savedb=BigInt_Create(); BigInt_Copy(savedb, b); /* Bug fix. If 'a' and 'b' aren't the same length, we need to expand the shorter one to the same size as the longer one before we invert it. This was the original source of the invert problem. */ if(b->length<a->length) BigInt_Realloc(b, a->length, 1); else if(a->length<b->length) BigInt_Realloc(a, b->length, 1); level=b->length; BigInt_Invert(b); } /* Make the numbers both the same size */ if(a->length!=b->length) { if(a->length>b->length) BigInt_Realloc(b, a->length, 1); else BigInt_Realloc(a, b->length, 1); } /* Allocate one more digit for the answer */ BigInt_Realloc(answer, a->length+1, 0); answer->negative=a->negative; carry=0; ad=a->digits; bd=b->digits; ansd=answer->digits; for(x=0; x<a->length; ++x) { n=(WORKING_DIGIT)(*ad++)+(WORKING_DIGIT)(*bd++)+carry; if(n>=OVERFLOW_DIGIT) { carry=1; *ansd++=(DIGIT)(n-OVERFLOW_DIGIT); } else { carry=0; *ansd++=(DIGIT)(n); } } *ansd=carry; /* Find the most significant digits, for efficiency */ BigInt_FindMSD(answer); BigInt_FindMSD(b); BigInt_FindMSD(a); if(level!=0) { /* Handle mismatched signs, step 2 */ BigInt_Copy(b, savedb); BigInt_Destroy(savedb); if(answer->length>level) { --answer->digits[level]; BigInt_FindMSD(answer); } else { BigInt_Realloc(answer, level, 1); BigInt_Invert(answer); #ifdef DEBUG1 BigInt_Dump(answer, "inverted, step 2"); #endif } } }
int DecodeShortV3(const char* serial, bool level10, unsigned char* dest, int dest_len) { char keybytes_[512]; char* kb=keybytes_; char* keybytes=keybytes_; char* k1; char* k2; bool keystring=false; int keylength; const char* udigits="0123456789ABCDEFGHJKMNPQRTUVWXYZ"; const char* ldigits="0123456789abcdefghjkmnpqrtuvwxyz"; const char* c=serial; const char* p; unsigned char value=0; unsigned char firstdigit=1; BigInt n, n2, n3; n=BigInt_Create(); n2=BigInt_Create(); n3=BigInt_Create(); int level=0; if(level10) level=10; if(serial==0 || serial[0]==0) { return 0; } while(c[0]) { p=strchr(udigits, c[0]); //first the current serial character in udigits if(p) { value=p-udigits; } else { p=strchr(ldigits, c[0]); //first the current character in ldigits if(p) { value=p-ldigits; } else if(c[0]=='i' || c[0]=='I' || c[0]=='l' || c[0]=='L') { value=1; } else if(c[0]=='o' || c[0]=='O') { value=0; } else if(c[0]=='s' || c[0]=='S') { value=5; } else { value=32; } } c++; if(value<32) //must be base32 { if(firstdigit) //ignore the first key character { if(level==10) { /* All level 10 keys start with the digit 1. It doesn't convey any information other than the fact that they're level 10 keys; discard it. */ //KeyString starts with 3 if(value==3) { value=0; keystring=true; //TODO: remove? } if(value!=0) { value=0; firstdigit=0; } } else { //KeyString starts with 3 if(value==3) { value=0; keystring=true; //TODO: remove? } if(value!=0 && value>=16) { value-=16; firstdigit=0; } } } BigInt_Shift(n, 5, n2); BigInt_SetU(n3, value); BigInt_Add(n2, n3, n); } } //end of loop //Spit out the bytes, in reverse order. BigInt_Set(n3, 0xFF); if(level==10) { while(BigInt_Compare(n, BigInt_One())>0) { BigInt_And(n, n3, n2); kb[0]=(unsigned char)BigInt_GetU(n2); kb++; BigInt_Shift(n, -8, n2); BigInt_Copy(n, n2); } } else { while(BigInt_Compare(n, BigInt_Zero())!=0) { BigInt_And(n, n3, n2); kb[0]=(unsigned char)BigInt_GetU(n2); kb++; BigInt_Shift(n, -8, n2); BigInt_Copy(n, n2); } } if((kb-keybytes)%2) //if the length / 2 has a remainder { kb[0]=0; //discard last byte? kb++; } /* Reverse digits in keybytes */ k1=keybytes; k2=kb-1; while(k1<k2) { char t=k1[0]; k1[0]=k2[0]; k2[0]=t; k2--; k1++; } BigInt_Destroy(n3); BigInt_Destroy(n2); BigInt_Destroy(n); keylength=kb-keybytes; memset(dest, 0, dest_len); memcpy(dest, keybytes, keylength); return keylength; }
char* EncodeShortV3(unsigned char* keybytes, int keylength, bool level10) { char* cc; char* shortv3digits=(char*)"0123456789ABCDEFGHJKMNPQRTUVWXYZ"; static char retval[512]=""; int level=0; int dcount; int nn; if(level10) level=29; strcpy(retval, ""); BigInt n=BigInt_Create(); BigInt t1=BigInt_Create(); BigInt t2=BigInt_Create(); if(level==29) BigInt_Set(n, 1); for(int x=0; x<keylength; ++x) { BigInt_Shift(n, 8, t1); BigInt_SetU(t2, keybytes[x]); BigInt_Add(t1, t2, n); } cc=retval; dcount=6; while(BigInt_Compare(n, BigInt_Zero())!=0) { BigInt_SetU(t2, 32); BigInt_Modulus(n, t2, t1); nn=BigInt_Get(t1); BigInt_Shift(n, -5, t2); BigInt_Copy(n, t2); if(level==29) { *cc++=shortv3digits[nn]; if(--dcount==0) { dcount=6; *cc++='-'; } } else { if(BigInt_Compare(n, BigInt_Zero())==0) { if(nn<16) { *cc++=shortv3digits[nn+16]; --dcount; } else { *cc++=shortv3digits[nn]; if(--dcount==0) { dcount=6; *cc++='-'; } *cc++=shortv3digits[16]; --dcount; } } else { *cc++=shortv3digits[nn]; if(--dcount==0) { dcount=6; *cc++='-'; } } } } if(level==29) { *cc++='1'; --dcount; } while(dcount-->0) *cc++='0'; *cc=0; mystrrev(retval); BigInt_Destroy(t2); BigInt_Destroy(t1); BigInt_Destroy(n); return retval; }