📄 mycryptlib.cpp
字号:
*/
UINT MyCryptLib::BNFromOctets(DWORD a[], UINT nSize, const unsigned char *c, UINT nOctBytes)
{
UINT i;
int j, k;
DWORD t;
DWORD t2;
BNSetZero(a, nSize);
/* Read in octets, least significant first */
/* i counts into big_d, j along c, and k is # bits to shift */
for (i = 0, j = nOctBytes - 1; (i < nSize)&&(j >= 0); i++)
{
t = 0;
for (k = 0; (j >= 0) && (k < (sizeof(DWORD)*8)); j--, k += 8)
{
t2=((DWORD)c[j]);
t |= t2 << k;
}
a[i] = t;
}
return i;
}
/*
* Convert an big Number a into an array of octets, in big-endian order,
* padding to nbytes or truncating if necessary.
* Return number of octets required excluding leading zero bytes.
*/
UINT MyCryptLib::BNToOctets(const DWORD a[], UINT nSize, unsigned char *c, UINT nbytes)
{
int j, k, len;
DWORD t;
UINT i, noctets, nbits;
nbits = BNBitLength(a, nSize);
noctets = (nbits + 7) / 8;
len = (int)nbytes;
for (i = 0, j = len - 1; i < nSize && j >= 0; i++)
{
t = a[i];
for (k = 0; j >= 0 && k < (sizeof(DWORD)*8); j--, k += 8)
c[j] = (unsigned char)(t >> k);
}
for ( ; j >= 0; j--)
c[j] = 0;
return noctets;
}
UINT MyCryptLib::BNFromDecimal(DWORD a[], UINT nSize, const char *s,UINT nStringLength)
{
BNSetZero(a, nSize);
// Create some temp storage for int values.
UINT newlen = BNUiceil(nStringLength * 0.41524); // log(10)/log(256)=0.41524
BYTE* ptmp=NULL;
ptmp=new BYTE[newlen];
memset(ptmp,0,newlen);
if (ptmp==NULL)
return 0; //FAILED
// Go through zero-terminated string
DWORD t=0;
for (UINT i = 0; s[i]; i++)
{
t = s[i] - '0';
if (t > 9 || t < 0) continue;
for (UINT j = newlen; j > 0; j--)
{
t += (DWORD)(ptmp[j-1] * 10);
ptmp[j-1] = (unsigned char)(t & 0xFF);
t >>= 8;
}
}
// now Convert bytes to big digits
UINT AcctualNumberofbytes = BNFromOctets(a, nSize, ptmp, newlen);
// Clean up
delete[] ptmp;
return AcctualNumberofbytes;
}
UINT MyCryptLib::BNFromHex(DWORD a[], UINT nSize, const char *s, UINT nStringLength)
{
size_t newlen;
BYTE *newdigits;
size_t n;
unsigned long t;
size_t i, j;
BNSetZero(a, nSize);
// temporary
n = strlen(s);
newlen = BNUiceil(n * 0.5); // log(16)/log(256)=0.5
newdigits = new BYTE[newlen];
if (newdigits==NULL)
return 0;
memset(newdigits,0,newlen);
// Work through zero-terminated string
for ( i = 0; s[i]; i++ )
{
t = s[i];
if ((t >= '0') && (t <= '9')) t = (t - '0');
else if ((t >= 'a') && (t <= 'f')) t = (t - 'a' + 10);
else if ((t >= 'A') && (t <= 'F')) t = (t - 'A' + 10);
else continue;
for (j = newlen; j > 0; j--)
{
t += (unsigned long)newdigits[j-1] << 4;
newdigits[j-1] = (unsigned char)(t & 0xFF);
t >>= 8;
}
}
// Convert bytes to big digits
n = BNFromOctets(a, nSize, newdigits, newlen);
// Clean up
delete[] newdigits;
return n;
}
/* Computes y = x^e mod m */
/* Binary left-to-right method */
int MyCryptLib::BNModExp(DWORD yout[], const DWORD x[], const DWORD e[], const DWORD m[], UINT nSize)
{
// Be safe
if ( nSize <= 0 )
return -1;
DWORD mask;
UINT n;
DWORD *t1, *t2, *t3, *tm, *y; //temporary variables
// Create some temporary variables
const UINT nn = nSize * 2;
t1 = BNAlloc(nn);
if(t1==NULL)
{
return -1;
}
t2 = BNAlloc(nn);
if(t2==NULL)
{
BNFree(&t1);
return -1;
}
t3 = BNAlloc(nn);
if(t3==NULL)
{
BNFree(&t1);
BNFree(&t2);
return -1;
}
tm = BNAlloc(nSize);
if(tm==NULL)
{
BNFree(&t1);
BNFree(&t2);
BNFree(&t3);
return -1;
}
y = BNAlloc(nSize);
if(y==NULL)
{
BNFree(&t1);
BNFree(&t2);
BNFree(&t3);
BNFree(&tm);
return -1;
}
BNSetEqual(tm, m, nSize);
// Find second-most significant bit in e
n = BNSizeof(e, nSize);
for (mask = _HIBITMASK_; mask > 0; mask >>= 1)
{
if (e[n-1] & mask)
break;
}
// next bitmask
if ( mask==1 )
{
mask=_HIBITMASK_;
n--;
}else
mask >>=1;
BNSetEqual(y, x, nSize);
while ( n )
{
BNModSquareTmp(y, y, tm, nSize, t1, t2, t3);
if (mask & e[n-1])
BNMultTmp(y, y, x, tm, nSize, t1, t2, t3);
// Move to next bit
// next bitmask
if ( mask==1 )
{
mask=_HIBITMASK_;
n--;
}else
mask >>=1;
}
BNSetEqual(yout, y, nSize);
BNFree(&t1);
BNFree(&t2);
BNFree(&t3);
BNFree(&tm);
BNFree(&y);
return 0;
}
// helper function for code cleannesss.
inline int MyCryptLib::BNMultTmp(DWORD a[], const DWORD x[], const DWORD y[], DWORD m[], UINT nSize, DWORD temp[], DWORD tqq[], DWORD trr[])
{
BNMultiply(temp, x, y, nSize);
BNModuloTmp(a, temp, nSize * 2, m, nSize, tqq, trr);
return 0;
}
inline int MyCryptLib::BNModuloTmp(DWORD r[], const DWORD u[], UINT nUSize, DWORD v[], UINT nVSize, DWORD tqq[], DWORD trr[])
{
BNDivide(tqq, trr, u, nUSize, v, nVSize);
BNSetEqual(r, trr, nVSize);
return 0;
}
inline int MyCryptLib::BNModSquareTmp(DWORD a[], const DWORD x[], DWORD m[], UINT nSize, DWORD temp[], DWORD tqq[], DWORD trr[])
{
//x*x
BNSquare(temp, x, nSize);
// Then modulo m
BNModuloTmp(a, temp, nSize * 2, m, nSize, tqq, trr);
return 0;
}
/*
* Computes sw = x * x
* where:
* x is a Big multiprecision Number
* w is a Big multiprecision Number of 2*nSize
* nSize is the size of the number in bytes.
*/
inline int MyCryptLib::BNSquare(DWORD w[], const DWORD x[], UINT nSize)
{
DWORD k, p[2], u[2], cbit, carry;
UINT i, j, t, i2, cpos;
t = nSize;
i2 = t << 1;
for (i = 0; i < i2; i++)
w[i] = 0;
carry = 0;
cpos = i2-1;
for (i = 0; i < t; i++)
{
i2 = i << 1;
BNMultiplyHelper(p, x[i], x[i]);
p[0] += w[i2];
if (p[0] < w[i2])
p[1]++;
k = 0;
if ( i2 == cpos && carry )
{
p[1] += carry;
if (p[1] < carry)
k++;
carry = 0;
}
u[0] = p[1];
u[1] = k;
w[i2] = p[0];
k = 0;
for ( j = i+1; j < t; j++ )
{
BNMultiplyHelper(p, x[j], x[i]);
cbit = (p[0] & _HIBITMASK_) != 0;
k = (p[1] & _HIBITMASK_) != 0;
p[0] <<= 1;
p[1] <<= 1;
p[1] |= cbit;
p[0] += u[0];
if (p[0] < u[0])
{
p[1]++;
if (p[1] == 0)
k++;
}
p[1] += u[1];
if (p[1] < u[1])
k++;
p[0] += w[i+j];
if (p[0] < w[i+j])
{
p[1]++;
if (p[1] == 0)
k++;
}
if ((i+j) == cpos && carry)
{
p[1] += carry;
if (p[1] < carry)
k++;
carry = 0;
}
u[0] = p[1];
u[1] = k;
w[i+j] = p[0];
}
carry = u[1];
w[i+t] = u[0];
cpos = i+t;
}
return 0;
}
// Computes inv = u^(-1) mod v
// This function is not 100% correct, I have to check it later.
int MyCryptLib::BNModInv(DWORD inv[], const DWORD u[], const DWORD v[], UINT nSize)
{
DWORD *u1, *u3, *v1, *v3, *t1, *t3, *q, *w;
u1=u3=v1=v3=t1=t3=q=w=NULL;
int bIterations;
int result;
// Allocate temp storage
u1 = BNAlloc(nSize);
if ( u1==NULL )
{
return -1;
}
u3 = BNAlloc(nSize);
if ( u3==NULL )
{
BNFree(&u1);
return -1;
}
v1 = BNAlloc(nSize);
if ( v1==NULL )
{
BNFree(&u1);
BNFree(&u3);
return -1;
}
v3 = BNAlloc(nSize);
if ( v3==NULL )
{
BNFree(&u1);
BNFree(&u3);
BNFree(&v1);
return -1;
}
t1 = BNAlloc(nSize);
if ( t1==NULL )
{
BNFree(&u1);
BNFree(&u3);
BNFree(&v1);
BNFree(&v3);
return -1;
}
t3 = BNAlloc(nSize);
if ( t3==NULL )
{
BNFree(&u1);
BNFree(&u3);
BNFree(&v1);
BNFree(&v3);
BNFree(&t1);
return -1;
}
q = BNAlloc(nSize);
if ( q==NULL )
{
BNFree(&u1);
BNFree(&u3);
BNFree(&v1);
BNFree(&v3);
BNFree(&t1);
BNFree(&t3);
return -1;
}
w = BNAlloc(2 * nSize);
if ( w==NULL )
{
BNFree(&u1);
BNFree(&u3);
BNFree(&v1);
BNFree(&v3);
BNFree(&t1);
BNFree(&t3);
BNFree(&q);
return -1;
}
// Init
BNSetEqualdw(u1, 1, nSize); // u1 = 1
BNSetEqual(u3, u, nSize); // u3 = u
BNSetZero(v1, nSize); // v1 = 0
BNSetEqual(v3, v, nSize); // v3 = v
bIterations = 1;
while ( !BNIsZero(v3, nSize) )
{
BNDivide(q, t3, u3, nSize, v3, nSize);
BNMultiply(w, q, v1, nSize);
// what if the real sizeof(w+u1)> nSize ???
//ASSERT(BNSizeof(w,nSize*2)>nSize);
BNAdd(t1, u1, w, nSize);
// Swap
BNSetEqual(u1, v1, nSize);
BNSetEqual(v1, t1, nSize);
BNSetEqual(u3, v3, nSize);
BNSetEqual(v3, t3, nSize);
bIterations = -bIterations;
}
if (bIterations < 0)
BNSubtract(inv, v, u1, nSize);
else
BNSetEqual(inv, u1, nSize);
if (BNComparedw(u3, 1, nSize) != 0)
{
result = 1;
BNSetZero(inv, nSize);
}
else
result = 0;
// Free the memory
BNSetZero(u1, nSize);
BNSetZero(v1, nSize);
BNSetZero(t1, nSize);
BNSetZero(u3, nSize);
BNSetZero(v3, nSize);
BNSetZero(t3, nSize);
BNSetZero(q, nSize);
BNSetZero(w, 2*nSize);
BNFree(&u1);
BNFree(&v1);
BNFree(&t1);
BNFree(&u3);
BNFree(&v3);
BNFree(&t3);
BNFree(&q);
BNFree(&w);
return 0;
}
int MyCryptLib::BNGcd(DWORD g[], const DWORD x[], const DWORD y[], UINT nSize)
{
DWORD *yy, *xx;
yy = BNAlloc(nSize);
if( yy==NULL )
return -1;
xx = BNAlloc(nSize);
if( xx==NULL )
{
BNFree(&yy);
return -1;
}
BNSetZero(yy, nSize);
BNSetZero(xx, nSize);
BNSetEqual(xx, x, nSize);
BNSetEqual(yy, y, nSize);
BNSetEqual(g, yy, nSize);
while ( !BNIsZero(xx, nSize) )
{
BNSetEqual(g, xx, nSize);
BNMod(xx, yy, nSize, xx, nSize);
BNSetEqual(yy, g, nSize);
}
BNSetZero(xx, nSize);
BNSetZero(yy, nSize);
BNFree(&xx);
BNFree(&yy);
return 0; // gcd = g
}
/* Returns true if w is a probable prime using the
* Rabin-Miller Probabilistic Primality Test.
* Carries out t iterations specified by user.
*
* DSS Standard recommends using t >= 50
* Ferguson & Schneier recommend t = 64 for prob error < 2^-128
* In practice, most random composites are caught in the first
* round or two and so specifying a large t will only affect
* the final check.
*
*/
int MyCryptLib::BNRabinMiller(const DWORD w[], UINT nSize, UINT t)
{
DWORD *m, *a, *b, *z, *w1, *j;
DWORD maxrand;
int failed;
BOOL bisprime;
UINT i;
// Catch w <= 1
if (BNComparedw(w, 1, nSize) <= 0)
return 0;
// Allocate temp storage..
m = BNAlloc(nSize);
if ( m==NULL )
{
return FALSE;
}
a = BNAlloc(nSize);
if ( a==NULL )
{
BNFree(&m);
return FALSE;
}
b = BNAlloc(nSize);
if ( b==NULL )
{
BNFree(&m);
BNFree(&a);
return FALSE;
}
z = BNAlloc(nSize);
if ( z==NULL )
{
BNFree(&m);
BNFree(&a);
BNFree(&b);
return FALSE;
}
w1 = BNAlloc(nSize);
if ( w1==NULL )
{
BNFree(&m);
BNFree(&a);
BNFree(&b);
BNFree(&z);
return FALSE;
}
j = BNAlloc(nSize);
if ( j==NULL )
{
BNFree(&m);
BNFree(&a);
BNFree(&b);
BNFree(&z);
BNFree(&w1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -