SM2算法

更新时间:2024-05-19 12:24:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

SM2算法实现

说明:

1、 纯源码无库实现,编译环境:VC++ 6,建立控制台程序把程序文件加入编译即可

2、 源码文件包括:main.cpp,SM2.cpp,HashSM3.cpp,Random.cpp,VLONG.cpp

头文件: AlgDump.h,AlgUtil.h,SM2.h,cfg_w32.h,cos_type.h,CryptoErr.h,HashSM3.h,Random.h,TypeDef.h,UniError.h,VLONG.h

3、 算法实现功能:

1)、SM2加密 2)、SM2解密 3)、SM2签名 4)、SM2验签

下载后如果有使用问题联系QQ: 1900109344

源码 SM2算法例程(main.cpp,SM2.cpp,HashSM3.cpp,Random.cpp,VLONG.cpp,AlgDump.h,AlgUtil.h,SM2.h,cfg_w32.h,cos_type.h,CryptoErr.h,HashSM3.h,Random.h,TypeDef.h,UniError.h,VLONG.h)

Main.cpp

#include #include #include

#define ECC_BITS 256

#define ECC_DATA_BYTES VL_DATA_BYTES(ECC_BITS)

#if ECC_BITS > ECC_DATA_BITS_MAX #error #endif

void PrintError( DWORD ErrCode ) { }

extern \ mem_xor( void *dst, const void *src1, const void *src2, int nBytes ) {

PBYTE pDst = (PBYTE) dst; PCBYTE pSrc1 = (PCBYTE) src1; PCBYTE pSrc2 = (PCBYTE) src2;

while( nBytes-- )

*pDst++ = (*pSrc1++) ^ (*pSrc2++); }

extern \ memchk( void *pBuff, int bByte, int nSize ) {

int i;

PCBYTE pByte = (PCBYTE) pBuff;

for( i = 0; i < nSize; i++, pByte++ ) {

if( *pByte != bByte ) return 0; // false }

return 1; // true }

extern \ HEX_VAL( int c ) {

if( c >= '0' && c <= '9' ) return (c-'0');

if( c >= 'a' && c <= 'f' ) return (c-'a'+10);

if( c >= 'A' && c <= 'F' ) return (c-'A'+10); return -1; }

#define IS_HEX(c) ( ((c)>='0'&&(c)<='9') || ((c)>='a'&&(c)<='f') || ((c)>='A'&&(c)<='F') )

extern \ LoadHex( unsigned char *abBuf, const char *szHex ) {

unsigned char c, v; unsigned long n;

for( n = 0; *szHex != '\\0'; ) { do

{ c = *szHex++; } while( c == ' ' );

if( c == '\\0' || !IS_HEX(c) ) break;

v = HEX_VAL(c) << 4; do

{ c = *szHex++; } while( c == ' ' ); if( IS_HEX(c) )

v |= HEX_VAL(c); abBuf[n++] = v;

if( c == '\\'0' || !IS_HEX(c) )

break; }

return n; }

extern \ memswap( void *ptr, int nBytes ) {

PBYTE pBuf = (PBYTE) ptr; BYTE bTmp; int i;

for( i=0; i

bTmp = pBuf[i];

pBuf[i] = pBuf[nBytes-1-i]; pBuf[nBytes-1-i] = bTmp; } }

void main( void ) {

ECC_PUB_KEY PubKey; ECC_PRV_KEY PrvKey;

BYTE abPlain[ECC_PLAIN_BYTES_MAX];

BYTE abCipher[ECC_CIPHER_SIZE(ECC_BITS,ECC_PLAIN_BYTES_MAX)]; BYTE abDecrypted[ECC_PLAIN_BYTES_MAX]; DWORD dwCipherSize, dwDecryptSize; BYTE Za[SM3_DIGESTSIZE]; BYTE E[SM3_DIGESTSIZE]; ECC_SIGN sign; ECC_CNTX cntx; DWORD ErrCode;

ECC_Init( &cntx, ECC_BITS );

printf( \

ECC_KeyGenerate( &cntx, &PrvKey, &PubKey );

printf( \

ErrCode = ECC_CheckPubKey( &cntx, &PubKey ); PrintError( ErrCode ); if( ErrCode != ERR_OK ) return;

printf( \

RAND_FillRandom( abPlain, sizeof(abPlain) ); memset( abCipher, 0x00, sizeof(abCipher) );

printf( \

ErrCode = ECC_Encrypt( &cntx, abPlain, sizeof(abPlain), &PubKey, abCipher, &dwCipherSize ); //SM2 加密

PrintError( ErrCode ); if( ErrCode != ERR_OK ) return;

printf( \

ErrCode = ECC_Decrypt( &cntx, abCipher, dwCipherSize, &PrvKey, abDecrypted, &dwDecryptSize ); //SM2 解密

PrintError( ErrCode ); if( ErrCode != ERR_OK ) return;

if( dwDecryptSize == sizeof(abPlain) &&

memcmp( abDecrypted, abPlain, sizeof(abPlain) ) == 0 ) printf( \ CMP: OK \\r\\n\ else

{ printf( \ CMP: Failed\\r\\n\ return; }

printf( \#if 0

RAND_FillRandom( E, SM3_DIGESTSIZE ); #else

ErrCode = ECC_GetZA( &cntx, (PCBYTE)\ PrintError( ErrCode ); if( ErrCode != ERR_OK ) return;

ErrCode = ECC_GetE( (PCBYTE) \ PrintError( ErrCode ); if( ErrCode != ERR_OK ) return; #endif

ErrCode = ECC_Sign( &cntx, E, &PrvKey, &sign ); //SM2签名 PrintError( ErrCode ); if( ErrCode != ERR_OK ) return;

printf( \

ErrCode = ECC_Verify( &cntx, E, &PubKey, &sign ); //SM2验签 PrintError( ErrCode ); if( ErrCode != ERR_OK ) return; }

Random.cpp

#include #include #include

/****************************************************************************************/

static DWORD gdwRandomSeed = 0; static WORD gwRemainBits = 0; static DWORD gdwRemain;

/****************************************************************************************/

DWORD RANDOMAPI PASCAL RAND_GetRandom(void) {

#if (DO_NOT_USE_RANDOM!=0) // LQ

return 0x4c232797; // 2010.06.24 17:32 #else

DWORD dwTemp;

if (gdwRandomSeed == 0) {

gdwRandomSeed = (DWORD) time(NULL); gwRemainBits = 0; }

gdwRandomSeed = (gdwRandomSeed * 10807L) & 0x7fffffffL;

if (gwRemainBits == 0) {

dwTemp = gdwRandomSeed << 1;

gdwRandomSeed = (gdwRandomSeed * 10807L) & 0x7fffffffL; gwRemainBits = 31; } else

{

dwTemp = gdwRemain; }

gwRemainBits --;

dwTemp |= gdwRandomSeed >> (gwRemainBits); if (gwRemainBits)

gdwRemain = gdwRandomSeed << (32-gwRemainBits); return dwTemp; #endif }

void RANDOMAPI RAND_FillRandom( PBYTE pBuff, int nSize ) {

// In some embeded system, memory is word aligned. In this case, converting pointer

// from PBYTE to PDWORD is dangerous. The following code is modified to use memcpy() // which is safe. -- Liu Qing, 2012.07.18 DWORD dwTemp;

while( nSize > 0 ) {

dwTemp = RAND_GetRandom();

memcpy( pBuff, &dwTemp, (nSize > sizeof(DWORD)) ? sizeof(DWORD) : nSize ); pBuff += sizeof(DWORD); nSize -= sizeof(DWORD); } }

HashSM3.cpp

#include #include #include

// Sample 1 // Input:\

// Output:66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0

// Sample 2

// Input:\

// Outpuf:debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732

#define FF0(x,y,z) ( (x) ^ (y) ^ (z))

#define FF1(x,y,z) (((x) & (y)) | ( (x) & (z)) | ( (y) & (z)))

#define GG0(x,y,z) ( (x) ^ (y) ^ (z))

#define GG1(x,y,z) (((x) & (y)) | ( (~(x)) & (z)) )

#define SHL(x,n) (((x) & 0xFFFFFFFF) << (n)) #define ROTL(x,n) (SHL((x),(n)) | ((x) >> (32 - (n))))

#define P0(x) ((x) ^ ROTL((x),9) ^ ROTL((x),17)) #define P1(x) ((x) ^ ROTL((x),15) ^ ROTL((x),23))

static void SM3_UpdateBlock( SM3_CNTX *ctx, const BYTE data[64] ) {

unsigned long SS1, SS2, TT1, TT2, W[68], W1[64]; unsigned long A, B, C, D, E, F, G, H; unsigned long T[64]; unsigned long Temp; int j; for(j = 0; j < 16; j++) T[j] = 0x79CC4519; for(j =16; j < 64; j++) T[j] = 0x7A879D8A;

for(j = 0; j < 16; j++)

W[j] = mfGetDWord( data+4*j ); for(j = 16; j < 68; j++ ) { #if 0 W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15) ) ^ ROTL(W[j-13],7 ) ^ W[j-6]; #else Temp = W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15); W[j] = P1(Temp) ^ ROTL(W[j-13], 7) ^ W[j-6]; #endif } for( j = 0; j < 64; j++ ) W1[j] = W[j] ^ W[j+4];

A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; E = ctx->state[4]; F = ctx->state[5];

G = ctx->state[6]; H = ctx->state[7]; for( j=0; j<16; j++ ) { SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7); SS2 = SS1 ^ ROTL(A,12); TT1 = FF0(A,B,C) + D + SS2 + W1[j]; TT2 = GG0(E,F,G) + H + SS1 + W[j]; D = C; C = ROTL(B,9); B = A; A = TT1; H = G; G = ROTL(F,19); F = E; E = P0(TT2); } for( j=16; j<64; j++ ) { SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7); SS2 = SS1 ^ ROTL(A,12); TT1 = FF1(A,B,C) + D + SS2 + W1[j]; TT2 = GG1(E,F,G) + H + SS1 + W[j]; D = C; C = ROTL(B,9); B = A; A = TT1; H = G; G = ROTL(F,19); F = E; E = P0(TT2); }

ctx->state[0] ^= A; ctx->state[1] ^= B; ctx->state[2] ^= C; ctx->state[3] ^= D; ctx->state[4] ^= E; ctx->state[5] ^= F; ctx->state[6] ^= G; ctx->state[7] ^= H; }

//-----------------------------------------------------------------------------

// SM3 context setup

//----------------------------------------------------------------------------- void SM3_Init( SM3_CNTX *ctx ) {

ctx->total[0] = 0; ctx->total[1] = 0;

ctx->state[0] = 0x7380166F; ctx->state[1] = 0x4914B2B9; ctx->state[2] = 0x172442D7; ctx->state[3] = 0xDA8A0600; ctx->state[4] = 0xA96F30BC; ctx->state[5] = 0x163138AA; ctx->state[6] = 0xE38DEE4D; ctx->state[7] = 0xB0FB0E4E; }

void SM3_Update( SM3_CNTX *ctx, PCBYTE pbInput, DWORD nInpBytes ) {

DWORD fill; DWORD left;

if( nInpBytes <= 0 ) return;

left = ctx->total[0] & 0x3F; fill = 64 - left;

ctx->total[0] += nInpBytes; ctx->total[0] &= 0xFFFFFFFF;

if( ctx->total[0] < (unsigned long) nInpBytes ) ctx->total[1]++;

if( left && nInpBytes >= fill ) {

memcpy( ctx->buffer + left, pbInput, fill ); SM3_UpdateBlock( ctx, ctx->buffer ); pbInput += fill; nInpBytes -= fill; left = 0; }

while( nInpBytes >= 64 ) {

SM3_UpdateBlock( ctx, pbInput ); pbInput += 64; nInpBytes -= 64; }

if( nInpBytes > 0 ) {

memcpy( ctx->buffer + left, pbInput, nInpBytes ); } }

void SM3_Final( SM3_CNTX *ctx, BYTE abDigest[32] ) {

unsigned long last, padn; unsigned long high, low; unsigned char abBuf[8]; int i;

unsigned char padding[64];

high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 );

mfPutDWord( abBuf, high ); mfPutDWord( abBuf+4, low );

last = ctx->total[0] & 0x3F;

padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );

memset( padding, 0, 64 ); padding[0] = 0x80;

SM3_Update( ctx, (unsigned char *) padding, padn ); SM3_Update( ctx, abBuf, 8 );

for( i=0; i<8; i++) {

mfPutDWord( abDigest + 4*i, ctx->state[i] ); } }

void SM3_HashBinary( BYTE abDigest[32], PCBYTE pcData, DWORD nDataBytes ) {

SM3_CNTX ctx;

SM3_Init( &ctx );

SM3_Update( &ctx, pcData, nDataBytes );

SM3_Final( &ctx, abDigest );

memset( &ctx, 0, sizeof( SM3_CNTX ) ); }

VLONG.cpp

#include #include #include #include

//--------------------------------------------------------------------------------------- // Prime table for small integer

//--------------------------------------------------------------------------------------- static const WORD gawPrimeTable[] = {

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, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741,

1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999 };

void VLONG_Init( PVLONG N, long v ) {

if( v >= 0 )

VLONG_SetSignDigits(N,0,1); else

{ VLONG_SetSignDigits(N,DIGIT_MSB,1); v = -v; }

N[1] = v; }

void VLONG_Copy( PVLONG D, PCVLONG S ) {

#define VLONG_ACTUAL_BYTES(n) ( (1+(n)) * DIGIT_SIZE ) memcpy( D, S, VLONG_ACTUAL_BYTES( VLONG_Digits(S) ) ); }

void VLONG_Load( PVLONG N, PCBYTE pcbBuf, int dwBufSize ) {

DIGIT dwDigits = (dwBufSize+DIGIT_SIZE-1)/DIGIT_SIZE; int i;

if( ( dwBufSize % DIGIT_SIZE ) == 0 ) i = dwDigits; else {

N[dwDigits] = 0;

for( i=0; i < (int)(dwBufSize%DIGIT_SIZE); i++ ) N[dwDigits] = ( N[dwDigits] << 8 ) | *(pcbBuf++); i = dwDigits - 1; }

for( ; i>0; i-- ) {

N[i] = mfGetDWord( pcbBuf );

pcbBuf += 4; }

for( i=dwDigits; i>1 && N[i]==0; i-- ) {};

VLONG_SetSignDigits( N, 0, i ); }

void VLONG_Save( PCVLONG N, PBYTE pbBuf, int dwBufSize ) {

int dwBytes = VLONG_Digits(N) * 4; int i = 0;

if( dwBufSize > dwBytes ) {

dwBytes = dwBufSize - dwBytes; memset( pbBuf, 0, dwBytes ); pbBuf += dwBytes; }

for( i = VLONG_Digits(N); i > 0; i-- ) {

mfPutDWord( pbBuf, N[i] ); pbBuf += 4; } }

int VLONG_Bits( PCVLONG N ) {

int i, n;

n = VLONG_Digits(N); if( n != 0 ) {

for( i =DIGIT_BITS-1; i >= 0; i-- ) {

if( ( N[n] & (1<

n = (n-1) * DIGIT_BITS + i + 1; }

return n; }

DWORD VLONG_LoadHex( PVLONG N, const char *szHex ) {

BYTE abBuf[VLONG_DATA_BYTES_MAX]; int n;

memset( abBuf, 0, sizeof(abBuf) ); n = LoadHex( abBuf, szHex );

VLONG_Load( N, abBuf, n ); return n; }

DWORD VLONG_LoadHexLE( PVLONG N, const char *szHex ) {

// Liitle Endian Version of VLONG_LoadHex()

BYTE abBuf[VLONG_DATA_BYTES_MAX]; int n;

memset( abBuf, 0, sizeof(abBuf) ); n = LoadHex( abBuf, szHex ); memswap( abBuf, n );

VLONG_Load( N, abBuf, n ); return n; }

int VLONG_AbsCmp( PCVLONG N1, PCVLONG N2 ) {

int dwDigits1 = VLONG_Digits(N1); int dwDigits2 = VLONG_Digits(N2); int i;

if( dwDigits1 < dwDigits2 ) return -1;

else if( dwDigits1 > dwDigits2 ) return 1; else {

for( i=dwDigits1; i>0; i-- ) {

if( N1[i] < N2[i] ) return -1;

else if( N1[i] > N2[i] )

本文来源:https://www.bwwdw.com/article/j3m7.html

Top