📄 mycryptlib.cpp
字号:
// MyCryptLib.cpp: implementation of the MyCryptLib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SecureChat.h"
#include "MyCryptLib.h"
// For timeGetTime();timeBeginPeriod() timeEndPeriod()
#include <Mmsystem.h>
#pragma comment( lib, "winmm" )
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
MyCryptLib::MyCryptLib()
{
m_mtIndex=0;
m_bSeeded=FALSE;
}
MyCryptLib::~MyCryptLib()
{
}
// Used to Speed up prime nr generator.
const DWORD MyCryptLib::SMALL_PRIMES[] = {
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
103, 107, 109, 113,127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
211, 223, 227, 229,233, 239, 241, 251, 257, 263,
269, 271, 277, 281,283, 293, 307, 311, 313, 317,
331, 337, 347, 349,353, 359, 367, 373, 379, 383,
389, 397, 401, 409,419, 421, 431, 433, 439, 443,
449, 457, 461, 463,467, 479, 487, 491, 499, 503,
509, 521, 523, 541,547, 557, 563, 569, 571, 577,
587, 593, 599, 601,607, 613, 617, 619, 631, 641,
643, 647, 653, 659,661, 673, 677, 683, 691, 701,
709, 719, 727, 733,739, 743, 751, 757, 761, 769,
773, 787, 797, 809,811, 821, 823, 827, 829, 839,
853, 857, 859, 863,877, 881, 883, 887, 907, 911,
919, 929, 937, 941,947, 953, 967, 971, 977, 983,
991, 997,
};
const UINT MyCryptLib::_NUMBEROFPRIMES_=sizeof(MyCryptLib::SMALL_PRIMES)/sizeof(DWORD);
// SHA konstants.
#ifdef SYSTEM_LITTLE_ENDIAN
const UINT MyCryptLib::_SHA_MASK_[4]={0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff};
const UINT MyCryptLib::_SHA_BITS_[4]={0x00000080, 0x00008000, 0x00800000, 0x80000000};
#else
const UINT MyCryptLib::_SHA_MASK_[4]={0x00000000, 0xff000000, 0xffff0000, 0xffffff00};
const UINT MyCryptLib::_SHA_BITS_[4]={0x80000000, 0x00800000, 0x00008000, 0x00000080};
#endif
/*
* Add(DWORD C[], DWORD A[], DWORD B[], UINT nSize)
-----------------------------------------------------
* Addition for very big numbers A,B,C
* Assumes that A, B and C, have the same size.
* nSize = number of bytes.
* Adds A & B and put the result in C.
* Reference Knuth, Donald. 1968. The Art of Computer Programming
* Returns 0 if success 1 if overflow.
*/
DWORD MyCryptLib::BNAdd(DWORD C[], const DWORD A[], const DWORD B[], const UINT nSize)
{
DWORD k=0; // carry
for (UINT i = 0; i < nSize; i++)
{
C[i] = A[i] + k;
if(C[i]>=k)// detect overflow and set k
k=0;
else
k=1;
C[i] += B[i];
if (C[i] < B[i]) // Detect overflow again.
k++;
}
return k;
}
// Returns ceil(x) as a non-negative integer or 0 if x < 0
UINT MyCryptLib::BNUiceil(double x)
{
UINT c;
if (x < 0) return 0;
c = (UINT)x;
if ((x - c) > 0.0)
c++;
return c;
}
/*
* SHA1 Implementation algoritm from, the algorith is taken from
* Federal Information
* Processing Standards Publication 180-1, 1995 April 17
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*
*/
/*
* Sha1Hash(unsigned char *_pOutDigest, const unsigned char *_pData,UINT nSize)
*
*
* Computes SH1 hash given data (_pData) of size nSize.
*
* _pOutDigest is an buffer of size SHA1_DIGEST_SIZE (20) which will be filled with
* the digestvalue.
*
*
*/
void MyCryptLib::SHA1Hash(unsigned char *_pOutDigest, const unsigned char *_pData,UINT nSize)
{
// Be safe
if ( !_pOutDigest || !_pData )
return;
SHA1_STATETYPE csha1;
memset(&csha1,0,sizeof(csha1));
SHA1_Start(&csha1);
SHA1_Hash(_pData,nSize,&csha1);
SHA1_Finish(_pOutDigest,&csha1);
}
void MyCryptLib::SHA1_Transform(SHA1_STATETYPE* _pcsha1)
{
UINT w[80], i, a, b, c, d, e, t;
for (i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
w[i] = SHA_BLOCK32(_pcsha1->wbuf[i]);
for (i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
w[i] = rotate32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
a = _pcsha1->hash[0];
b = _pcsha1->hash[1];
c = _pcsha1->hash[2];
d = _pcsha1->hash[3];
e = _pcsha1->hash[4];
for(i = 0; i < 20; ++i)
{
sha_round(F0to19, 0x5a827999);
}
for(i = 20; i < 40; ++i)
{
sha_round(F20to39, 0x6ed9eba1);
}
for(i = 40; i < 60; ++i)
{
sha_round(F40to59, 0x8f1bbcdc);
}
for(i = 60; i < 80; ++i)
{
sha_round(F60to79, 0xca62c1d6);
}
_pcsha1->hash[0] += a;
_pcsha1->hash[1] += b;
_pcsha1->hash[2] += c;
_pcsha1->hash[3] += d;
_pcsha1->hash[4] += e;
}
void MyCryptLib::SHA1_Start(SHA1_STATETYPE *_pcsha1)
{
_pcsha1->hash[0] = 0x67452301;
_pcsha1->hash[1] = 0xefcdab89;
_pcsha1->hash[2] = 0x98badcfe;
_pcsha1->hash[3] = 0x10325476;
_pcsha1->hash[4] = 0xc3d2e1f0;
_pcsha1->count[0] = 0;
_pcsha1->count[1] = 0;
}
void MyCryptLib::SHA1_Finish(unsigned char* _pShaValue, SHA1_STATETYPE* _pcsha1)
{
UINT i = (UINT)(_pcsha1->count[0] & (SHA1_BLOCK_SIZE - 1));
_pcsha1->wbuf[i >> 2] = (_pcsha1->wbuf[i >> 2] & _SHA_MASK_[i & 3]) | _SHA_BITS_[i & 3];
if(i > SHA1_BLOCK_SIZE - 9)
{
if(i < 60) _pcsha1->wbuf[15] = 0;
SHA1_Transform(_pcsha1);
i = 0;
}
else
i = (i >> 2) + 1;
while(i < 14)
_pcsha1->wbuf[i++] = 0;
_pcsha1->wbuf[14] = SHA_BLOCK32((_pcsha1->count[1] << 3) | (_pcsha1->count[0] >> 29));
_pcsha1->wbuf[15] = SHA_BLOCK32(_pcsha1->count[0] << 3);
SHA1_Transform(_pcsha1);
for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
_pShaValue[i] = (unsigned char)(_pcsha1->hash[i >> 2] >> 8 * (~i & 3));
}
void MyCryptLib::SHA1_Hash(const unsigned char *_pData, unsigned int _iSize, SHA1_STATETYPE* _pcsha1)
{
UINT ipos = (UINT)(_pcsha1->count[0] & (SHA1_BLOCK_SIZE - 1));
UINT ispace = SHA1_BLOCK_SIZE - ipos;
unsigned char *pData=(unsigned char *)_pData;
if((_pcsha1->count[0] += _iSize) < _iSize)
++(_pcsha1->count[1]);
while(_iSize >= ispace)
{
memcpy(((unsigned char*)_pcsha1->wbuf) + ipos, pData, ispace);
ipos = 0;
_iSize -= ispace;
pData += ispace;
ispace = SHA1_BLOCK_SIZE;
SHA1_Transform(_pcsha1);
}
memcpy(((unsigned char*)_pcsha1->wbuf) + ipos, pData, _iSize);
}
/*
* BNAdddw(DWORD w[], const DWORD u[], DWORD v, UINT nSize)
-----------------------------------------------------
* Addition for very big numbers w,u
* w=u+v.
* nSize = number of bytes.
* Reference Knuth, Donald. 1968. The Art of Computer Programming
* Returns 0 if success 1 if overflow.
*/
inline DWORD MyCryptLib::BNAdddw(DWORD w[], const DWORD u[], DWORD v, UINT nSize)
{
DWORD k=0;
w[0] = u[0] + v;
k=(w[0] >= v) ? 0:1;
for (UINT j = 1; j < nSize; j++)
{
w[j] = u[j] + k;
k=(w[j] >= k) ? 0:1;
}
return k;
}
/*
* BNSubtract(DWORD C[], DWORD A[], DWORD B[], UINT nSize)
-----------------------------------------------------
* Subtraction for very big numbers A,B,C
* Assumes that A, B and C, have the same size.
* nSize = number of bytes.
* Calculates C = A - B where A >= B
* Reference Knuth, Donald. 1968. The Art of Computer Programming
* Returns 0 if success 1 if overflow.
*/
DWORD MyCryptLib::BNSubtract(DWORD C[], const DWORD A[], const DWORD B[],const UINT nSize)
{
DWORD k=0;
for (UINT i = 0; i < nSize; i++)
{
C[i] = A[i] - k;
if (C[i] > _MAXIMUMNR_ - k) // detect underflow (borrow)
k = 1;
else
k = 0;
C[i] -= B[i];
if (C[i] > _MAXIMUMNR_ - B[i])
k++;
}
return k;
}
/*
* BNSubtract(DWORD w[], const DWORD u[], DWORD v, UINT nSize)
-----------------------------------------------------
* Subtraction for very big numbers u to an normal DWORD.
* Assumes that w,u, have the same size.
* nSize = number of bytes.
* Calculates w=u-v
* Reference Knuth, Donald. 1968. The Art of Computer Programming
* Returns 0 if success 1 if overflow.
*/
DWORD MyCryptLib::BNSubtractdw(DWORD w[], const DWORD u[], DWORD v, UINT nSize)
{
DWORD k=0;
w[0] = u[0] - v;
if (w[0] > _MAXIMUMNR_- v)
k = 1;
else
k = 0;
for (UINT j = 1; j < nSize; j++)
{
w[j] = u[j] - k;
if (w[j] > _MAXIMUMNR_ - k)
k = 1;
else
k = 0;
}
return k;
}
CString MyCryptLib::BNPrint(const DWORD *p, UINT nSize)
{
CString stmp="";
CString sRet="";
// Trim leading zeroes
while (nSize--)
{
if (p[nSize] != 0)
break;
}
nSize++;
// Catch empty len to show 0
if ( nSize==0 )
nSize=1;
while ( nSize-- )
{
stmp.Format("%08lx ", p[nSize]);
sRet+=stmp;
}
return sRet;
}
CString MyCryptLib::BNPrintC(const DWORD *p, UINT nSize)
{
CString stmp="";
CString sRet;
sRet.Format("[%i] = {\r\n",nSize);
int iNrPrinted=0;
for ( UINT i=0; i<nSize; i++ )
{
stmp.Format("0x%08lx, ", p[i]);
iNrPrinted++;
sRet+=stmp;
if(iNrPrinted%6==0)
sRet+="\r\n";
}
sRet+="};";
return sRet;
}
/*
* Returns an CString version of the number
*
*/
CString MyCryptLib::BNToString(const DWORD *a, UINT nSize,UINT nBase)
{
// Is the number is Zero
if ( BNIsZero(a, nSize) )
return "0";
CString sRet=""; // return String
const char DEC_DIGITS[] = "0123456789";
const char HEX_DIGITS[] = "0123456789abcdef";
const char *cdigits;
double dFactor=0.0;
// Setup the data according to nBase
switch (nBase)
{
case 10:
cdigits = DEC_DIGITS;
dFactor = 2.40824; /* log(256)/log(10)=2.40824 */
break;
case 16:
cdigits = HEX_DIGITS;
dFactor = 2.0; /* log(256)/log(16)=2.0 */
break;
default:
return "Base must be 10 or 16";
}
// Convert to 8 bits octtlets (is easier to handle)
UINT nbytes = nSize * sizeof(DWORD);
BYTE* pOct=NULL;
pOct=new BYTE[nbytes];
// be safe
if ( pOct==NULL )
return "Not enough memory: pOct=new BYTE[nbytes] Failed..";
memset(pOct,0,nbytes);
UINT NumberOfOctNeeded= BNToOctets(a,nSize,pOct,nbytes);
// Create temporary place
UINT NewOctLength=BNUiceil(NumberOfOctNeeded*dFactor);
BYTE* pNewOct=new BYTE[NewOctLength];
// Be safe
if ( pNewOct==NULL )
{
delete[] pOct;
return "Not enough memory: pNewOct=new BYTE[NewOctLength] Failed..";
}
memset(pNewOct,0,NewOctLength);
// Transform
UINT t=0;
UINT i=0;
for (i = 0; i < nbytes; i++)
{
t = pOct[i];
for (UINT j = NewOctLength; j > 0; j--)
{
t += (unsigned long)(pNewOct[j-1] * 256);
pNewOct[j-1] = (unsigned char)(t % nBase);
t /= nBase;
}
}
// Find index of leading significant digit
UINT isig=0;
for ( isig = 0; isig < NewOctLength; isig++ )
if (pNewOct[isig])
break;
// number of charachters needed..
UINT nchars = NewOctLength - isig;
for(i=0;i<nchars;i++)
sRet+=cdigits[pNewOct[isig+i]];
delete[] pOct;
delete[] pNewOct;
return sRet;
}
/*
* Returns True if a == b else false
*/
int MyCryptLib::BNIsEqual(const DWORD a[], const DWORD b[], UINT nSize)
{
if ( nSize <= 0 )
return FALSE;
while ( nSize-- )
{
if ( a[nSize] != b[nSize] )
return FALSE;
}
return TRUE;
}
/*
* Makes A=0
*/
void MyCryptLib::BNSetZero(DWORD A[], UINT nSize)
{
while ( nSize-- )
A[nSize] = 0;
}
/*
* Return True if a==0
*/
int MyCryptLib::BNIsZero(const DWORD a[], UINT nSize)
{
if (nSize == 0)
return FALSE;
for (UINT i = 0; i < nSize; i++)
{
if (a[i] != 0)
return FALSE;
}
return TRUE;
}
/*
* Makes a=b
*/
void MyCryptLib::BNSetEqual(DWORD a[], const DWORD b[], UINT nSize)
{
for (UINT i = 0; i < nSize; i++)
{
a[i] = b[i];
}
}
/*
* Makes a=d
* Where d is an normal DWORD.
*/
void MyCryptLib::BNSetEqualdw(DWORD a[], const DWORD d, UINT nSize)
{
if(nSize<=0)
return;
BNSetZero(a,nSize);
a[0]=d;
}
int MyCryptLib::BNCompare(const DWORD a[], const DWORD b[], UINT nSize)
{
if ( nSize <= 0 )
return 0;
while (nSize--)
{
if (a[nSize] > b[nSize])
return 1; // Grater than
if (a[nSize] < b[nSize])
return -1; // Less Than
}
return 0;// equal
}
/* Returns sign of (a - b) where b is an DWORD */
inline int MyCryptLib::BNComparedw(const DWORD a[], DWORD b, UINT nSize)
{
// Be Safe
if (nSize == 0) return (b ? -1 : 0);
for (UINT i = 1; i < nSize; i++)
{
if (a[i] != 0)
return 1; // Greater than
}
if ( a[0] < b)
return -1; // Less than
else if ( a[0] > b )
return 1; // Greater
return 0; //equal
}
/* BNShiftLeft(DWORD a[], const DWORD *b, DWORD x, DWORD nSize)
* Computes a = b << x
* returns carry
*/
inline DWORD MyCryptLib::BNShiftLeft(DWORD a[], const DWORD *b, UINT x, UINT nSize)
{
DWORD mask, carry, nextcarry;
UINT i=0;
if ( x >= sizeof(DWORD)*8 )
return 0;
mask = _HIBITMASK_;
for (i = 1; i < x; i++)
{
mask = (mask >> 1) | mask;
}
if (x == 0) mask = 0x0;
UINT y = (sizeof(DWORD)*8) - x;
carry = 0;
for (i = 0; i < nSize; i++)
{
nextcarry = (b[i] & mask) >> y;
a[i] = b[i] << x | carry;
carry = nextcarry;
}
return carry;
}
/* BNShiftRight(DWORD a[], const DWORD *b, DWORD x, DWORD nSize)
* Computes a = b >> x
* returns carry
*
*/
inline DWORD MyCryptLib::BNShiftRight(DWORD a[], const DWORD *b, DWORD x, DWORD nSize)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -