实验2-2

实验2-2

在Ubuntu或openEuler中(推荐openEuler)中调试运行教材提供的源代码,至少运行SM2,SM3,SM4代码,使用GmSSL命令验证你代码的正确性,使用Markdown记录详细记录实践过程,每完成一项功能或者一个函数gitcommit一次。

sm2

加密解密
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ vim enc.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ vim enc.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ vim kdf.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ vim kdf.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ vim test.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ gcc -o test kdf.c enc.c test.c -m32 -lmiracl_32
In file included from kdf.c:1:
kdf.c: In function ‘CF’:
kdf.h:21:31: warning: result of ‘2055708042 << 16’ requires 48 bits to represent, but ‘int’ only has 32 bits [-Wshift-overflow=]
   21 | #define SM3_rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
      |                               ^~
kdf.c:87:269: note: in expansion of macro ‘SM3_rotl32’
   87 |                                                                                                 T = SM3_rotl32(SM3_T2, 16);
      |                                                                                                     ^~~~~~~~~~

test.c: In function ‘main’:
test.c:4:17: warning: implicit declaration of function ‘SM2_ENC_SelfTest’ [-Wimplicit-function-declaration]
    4 |                 SM2_ENC_SelfTest();
      |                 ^~~~~~~~~~~~~~~~
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ ./test
原文
0x65,0x6e,0x63,0x72,0x79,0x70,0x74,0x69,
0x6f,0x6e,0x20,0x73,0x74,0x61,0x6e,0x64,
0x61,0x72,0x64,

 密文:
0x4,0xeb,0xfc,0x71,0x8e,0x8d,0x17,0x98,
0x62,0x4,0x32,0x26,0x8e,0x77,0xfe,0xb6,
0x41,0x5e,0x2e,0xde,0xe,0x7,0x3c,0xf,
0x4f,0x64,0xe,0xcd,0x2e,0x14,0x9a,0x73,
0xe8,0x58,0xf9,0xd8,0x1e,0x54,0x30,0xa5,
0x7b,0x36,0xda,0xab,0x8f,0x95,0xa,0x3c,
0x64,0xe6,0xee,0x6a,0x63,0x9,0x4d,0x99,
0x28,0x3a,0xff,0x76,0x7e,0x12,0x4d,0xf0,
0x59,0x98,0x3c,0x18,0xf8,0x9,0xe2,0x62,
0x92,0x3c,0x53,0xae,0xc2,0x95,0xd3,0x3,
0x83,0xb5,0x4e,0x39,0xd6,0x9,0xd1,0x60,
0xaf,0xcb,0x19,0x8,0xd0,0xbd,0x87,0x66,
0x21,0x88,0x6c,0xa9,0x89,0xca,0x9c,0x7d,
0x58,0x8,0x73,0x7,0xca,0x93,0x9,0x2d,
0x65,0x1e,0xfa,

解密结果:
0x65,0x6e,0x63,0x72,0x79,0x70,0x74,0x69,
0x6f,0x6e,0x20,0x73,0x74,0x61,0x6e,0x64,
0x61,0x72,0x64,
解密成功
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/enc$ git commit -m "sm2_enc"
[master 14da136] sm2_enc
 6 files changed, 841 insertions(+)
 create mode 100644 shiyan2/2-2/sm2/enc/enc.c
 create mode 100644 shiyan2/2-2/sm2/enc/enc.h
 create mode 100644 shiyan2/2-2/sm2/enc/kdf.c
 create mode 100644 shiyan2/2-2/sm2/enc/kdf.h
 create mode 100755 shiyan2/2-2/sm2/enc/test
 create mode 100644 shiyan2/2-2/sm2/enc/test.c
  • enc.c
#include "miracl/miracl.h"
#include "miracl/mirdef.h"
#include "enc.h"
#include "kdf.h"

big para_p, para_a, para_b, para_n, para_Gx, para_Gy, para_h;
epoint *G;
miracl *mip;

unsigned char SM2_p[32] = { 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };
unsigned char SM2_a[32] = { 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC };
unsigned char SM2_b[32] = { 0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,0x9E,0x4B,0xCF,0x65,0x09,0xA7,
0xF3,0x97,0x89,0xF5,0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,0x0E,0x93 };
unsigned char SM2_n[32] = { 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x72,0x03,0xDF,0x6B,0x21,0xC6,0x05,0x2B,0x53,0xBB,0xF4,0x09,0x39,0xD5,0x41,0x23 };
unsigned char SM2_Gx[32] = { 0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,0x04,0x46,0x6A,0x39,0xC9,0x94,
0x8F,0xE3,0x0B,0xBF,0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C,0x74,0xC7 };
unsigned char SM2_Gy[32] = { 0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,0xCE,0xE3,0x6B,0x69,0x21,0x53,
0xD0,0xA9,0x87,0x7C,0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39,0xF0,0xA0 };
unsigned char SM2_h[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };


/****************************************************************
Function: Test_Point
Description: test if the given point is on SM2 curve
Calls:
Called By: SM2_Decrypt, Test_PubKey
Input: point
Output: null
Return: 0: sucess
3: not a valid point on curve
Others:
****************************************************************/
int Test_Point(epoint* point)
{
	big x, y, x_3, tmp;
	x = mirvar(0);
	y = mirvar(0);
	x_3 = mirvar(0);
	tmp = mirvar(0);
	epoint_get(point, x, y);
	power(x, 3, para_p, x_3);
	multiply(x, para_a, x);
	divide(x, para_p, tmp);
	add(x_3, x, x);
	add(x, para_b, x);
	divide(x, para_p, tmp);
	power(y, 2, para_p, y);
	if (mr_compare(x, y) != 0)
		return ERR_NOT_VALID_POINT;
	else
		return 0;
}
/****************************************************************
Function: SM2_TestPubKey
Description: test if the given point is valid
Calls:
Called By: SM2_Decrypt
Input: pubKey //a point
Output: null
Return: 0: sucess
1: a point at infinity
2: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
Others:
****************************************************************/
int Test_PubKey(epoint *pubKey)
{
	big x, y, x_3, tmp;
	epoint *nP;
	x = mirvar(0);
	y = mirvar(0);
	x_3 = mirvar(0);
	tmp = mirvar(0);
	nP = epoint_init();
	if (point_at_infinity(pubKey))
		return ERR_INFINITY_POINT;
	epoint_get(pubKey, x, y);
	if ((mr_compare(x, para_p) != -1) || (mr_compare(y, para_p) != -1))
		return ERR_NOT_VALID_ELEMENT;
	if (Test_Point(pubKey) != 0)
		return ERR_NOT_VALID_POINT;
	ecurve_mult(para_n, pubKey, nP);
	if (!point_at_infinity(nP))
		return ERR_ORDER;
	return 0;
}
/****************************************************************
Function: Test_Null
Description: test if the given array is all zero
Calls:
Called By: SM2_Encrypt
Input: array[len]
len //byte len of the array
Output: null
Return: 0: the given array is not all zero
1: the given array is all zero
Others:
****************************************************************/
int Test_Null(unsigned char array[], int len)
{
	int i = 0;
	for (i = 0; i < len; i++)
	{
		if (array[i] != 0x00)
			return 0;
	}
	return 1;
}
/****************************************************************
Function: SM2_Init
Description: Initiate SM2 curve
Calls: MIRACL functions
Called By:
Input: null
Output: null
Return: 0: sucess;
7: paremeter error;
4: the given point G is not a point of order n
Others:
****************************************************************/
int SM2_Init()
{
	epoint *nG;
	para_p = mirvar(0);
	para_a = mirvar(0);
	para_b = mirvar(0);
	para_n = mirvar(0);
	para_Gx = mirvar(0);
	para_Gy = mirvar(0);
	para_h = mirvar(0);
	G = epoint_init();
	nG = epoint_init();
	bytes_to_big(SM2_NUMWORD, SM2_p, para_p);
	bytes_to_big(SM2_NUMWORD, SM2_a, para_a);
	bytes_to_big(SM2_NUMWORD, SM2_b, para_b);
	bytes_to_big(SM2_NUMWORD, SM2_n, para_n);
	bytes_to_big(SM2_NUMWORD, SM2_Gx, para_Gx);
	bytes_to_big(SM2_NUMWORD, SM2_Gy, para_Gy);
	bytes_to_big(SM2_NUMWORD, SM2_h, para_h);
	ecurve_init(para_a, para_b, para_p, MR_PROJECTIVE);
		if (!epoint_set(para_Gx, para_Gy, 0, G))
		{
			return ERR_ECURVE_INIT;
		}
	ecurve_mult(para_n, G, nG);
	if (!point_at_infinity(nG))
	{
		return ERR_ORDER;
	}
	return 0;
}
/****************************************************************
Function: SM2_KeyGeneration
Description: calculate a pubKey out of a given priKey
Calls: SM2_TestPubKey
Called By:
Input: priKey // a big number lies in[1,n-2]
Output: pubKey // pubKey=[priKey]G
Return: 0: sucess
1: fail
Others:
****************************************************************/
int SM2_KeyGeneration(big priKey, epoint *pubKey)
{
	int i = 0;
	big x, y;
	x = mirvar(0);
	y = mirvar(0);
	ecurve_mult(priKey, G, pubKey);
	epoint_get(pubKey, x, y);
	if (Test_PubKey(pubKey) != 0)
		return 1;
	else
		return 0;
}
/****************************************************************
Function: SM2_Encrypt
Description: SM2 encryption
Calls: SM2_KDF,Test_null,Test_Point,SM3_init,SM3_process,SM3_done
Called By:
Input: randK[SM2_NUMWORD] // a random number K lies in [1,n-1]
pubKey // public key of the cipher receiver
M[klen] // original message
klen // byte len of original message
Output: C[klen+SM2_NUMWORD*3] // cipher C1||C3||C2
Return: 0: sucess
1: S is point at infinity
5: the KDF output is all zero
Others:
****************************************************************/
int SM2_Encrypt(unsigned char* randK, epoint *pubKey, unsigned char M[], int klen, unsigned char C[])
{
	big C1x, C1y, x2, y2, rand;
	epoint *C1, *kP, *S;
	int i = 0;
	unsigned char x2y2[SM2_NUMWORD * 2] = { 0 };
	SM3_STATE md;
	C1x = mirvar(0);
	C1y = mirvar(0);
	x2 = mirvar(0);
	y2 = mirvar(0);
	rand = mirvar(0);
	C1 = epoint_init();
	kP = epoint_init();
	S = epoint_init();
	bytes_to_big(SM2_NUMWORD, randK, rand);
	ecurve_mult(rand, G, C1);
	epoint_get(C1, C1x, C1y);
	big_to_bytes(SM2_NUMWORD, C1x, C, 1);
	big_to_bytes(SM2_NUMWORD, C1y, C + SM2_NUMWORD, 1);
	ecurve_mult(para_h, pubKey, S);
	if (point_at_infinity(S))
		return ERR_INFINITY_POINT;
	ecurve_mult(rand, pubKey, kP);
	epoint_get(kP, x2, y2);
	big_to_bytes(SM2_NUMWORD, x2, x2y2, 1);
	big_to_bytes(SM2_NUMWORD, y2, x2y2 + SM2_NUMWORD, 1);
	SM3_KDF(x2y2, SM2_NUMWORD * 2, klen, C + SM2_NUMWORD * 3);
	if (Test_Null(C + SM2_NUMWORD * 3, klen) != 0)
		return ERR_ARRAY_NULL;
	for (i = 0; i < klen; i++)
	{
		C[SM2_NUMWORD * 3 + i] = M[i] ^ C[SM2_NUMWORD * 3 + i];
	}
	SM3_init(&md);
	SM3_process(&md, x2y2, SM2_NUMWORD);
	SM3_process(&md, M, klen);
	SM3_process(&md, x2y2 + SM2_NUMWORD, SM2_NUMWORD);
	SM3_done(&md, C + SM2_NUMWORD * 2);
	return 0;
}
/****************************************************************
Function: SM2_Decrypt
Description: SM2 decryption
Calls: SM2_KDF,Test_Point,SM3_init,SM3_process,SM3_done
Called By:
Input: dB // a big number lies in [1,n-2]
pubKey // [dB]G
C[Clen] // cipher C1||C3||C2
Clen // byte len of cipher
Output: M[Clen-SM2_NUMWORD*3] // decrypted data
Return: 0: sucess
1: S is a point at finity
3: C1 is not a valid point
5: KDF output is all zero
6: C3 does not match
Others:
****************************************************************/
int SM2_Decrypt(big dB, unsigned char C[], int Clen, unsigned char M[])
{
	SM3_STATE md;
	int i = 0;
	unsigned char x2y2[SM2_NUMWORD * 2] = { 0 };
	unsigned char hash[SM2_NUMWORD] = { 0 };
	big C1x, C1y, x2, y2;
	epoint *C1, *S, *dBC1;
	C1x = mirvar(0);
	C1y = mirvar(0);
	x2 = mirvar(0);
	y2 = mirvar(0);
	C1 = epoint_init();
	S = epoint_init();
	dBC1 = epoint_init();
	bytes_to_big(SM2_NUMWORD, C, C1x);
	bytes_to_big(SM2_NUMWORD, C + SM2_NUMWORD, C1y);
	epoint_set(C1x, C1y, 0, C1);
	i = Test_Point(C1);
	if (i != 0)
		return i;
	ecurve_mult(para_h, C1, S);
	if (point_at_infinity(S))
		return ERR_INFINITY_POINT;
	ecurve_mult(dB, C1, dBC1);
	epoint_get(dBC1, x2, y2);
	big_to_bytes(SM2_NUMWORD, x2, x2y2, 1);
	big_to_bytes(SM2_NUMWORD, y2, x2y2 + SM2_NUMWORD, 1);
	SM3_KDF(x2y2, SM2_NUMWORD * 2, Clen - SM2_NUMWORD * 3, M);
	if (Test_Null(M, Clen - SM2_NUMWORD * 3) != 0)
		return ERR_ARRAY_NULL;
	for (i = 0; i < Clen - SM2_NUMWORD * 3; i++)
		M[i] = M[i] ^ C[SM2_NUMWORD * 3 + i];
	SM3_init(&md);
	SM3_process(&md, x2y2, SM2_NUMWORD);
	SM3_process(&md, M, Clen - SM2_NUMWORD * 3);
	SM3_process(&md, x2y2 + SM2_NUMWORD, SM2_NUMWORD);
	SM3_done(&md, hash);
	if (memcmp(hash, C + SM2_NUMWORD * 2, SM2_NUMWORD) != 0)
		return ERR_C3_MATCH;
	else
		return 0;
}
/****************************************************************
Function: SM2_ENC_SelfTest
Description: test whether the SM2 calculation is correct by comparing the result with the standard data
Calls: SM2_init,SM2_ENC,SM2_DEC
Called By:
Input: NULL
Output: NULL
Return: 0: sucess
1: S is a point at finity
2: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: the given point G is not a point of order n
5: KDF output is all zero
6: C3 does not match
8: public key generation error
9: SM2 encryption error
a: SM2 decryption error
Others:
****************************************************************/
int SM2_ENC_SelfTest()
{
	int tmp = 0, i = 0;
	unsigned char Cipher[115] = { 0 };
	unsigned char M[19] = { 0 };
	unsigned char kGxy[SM2_NUMWORD * 2] = { 0 };
	big ks, x, y;
	epoint *kG;
	unsigned char std_priKey[32] = { 0x39,0x45,0x20,0x8F,0x7B,0x21,0x44,0xB1,0x3F,0x36,0xE3,0x8A,0xC6,0xD3,0x9F,0x95,
	0x88,0x93,0x93,0x69,0x28,0x60,0xB5,0x1A,0x42,0xFB,0x81,0xEF,0x4D,0xF7,0xC5,0xB8 };
	unsigned char std_pubKey[64] = { 0x09,0xF9,0xDF,0x31,0x1E,0x54,0x21,0xA1,0x50,0xDD,0x7D,0x16,0x1E,0x4B,0xC5,0xC6,
	0x72,0x17,0x9F,0xAD,0x18,0x33,0xFC,0x07,0x6B,0xB0,0x8F,0xF3,0x56,0xF3,0x50,0x20,
	0xCC,0xEA,0x49,0x0C,0xE2,0x67,0x75,0xA5,0x2D,0xC6,0xEA,0x71,0x8C,0xC1,0xAA,0x60,
	0x0A,0xED,0x05,0xFB,0xF3,0x5E,0x08,0x4A,0x66,0x32,0xF6,0x07,0x2D,0xA9,0xAD,0x13 };
	unsigned char std_rand[32] = { 0x59,0x27,0x6E,0x27,0xD5,0x06,0x86,0x1A,0x16,0x68,0x0F,0x3A,0xD9,0xC0,0x2D,0xCC,
	0xEF,0x3C,0xC1,0xFA,0x3C,0xDB,0xE4,0xCE,0x6D,0x54,0xB8,0x0D,0xEA,0xC1,0xBC,0x21 };
	unsigned char std_Message[19] = { 0x65,0x6E,0x63,0x72,0x79,0x70,0x74,0x69,0x6F,0x6E,0x20,0x73,0x74,0x61,0x6E,
	0x64,0x61,0x72,0x64 };
	unsigned char std_Cipher[115] = { 0x04,0xEB,0xFC,0x71,0x8E,0x8D,0x17,0x98,0x62,0x04,0x32,0x26,0x8E,0x77,0xFE,0xB6,
	0x41,0x5E,0x2E,0xDE,0x0E,0x07,0x3C,0x0F,0x4F,0x64,0x0E,0xCD,0x2E,0x14,0x9A,0x73,
	0xE8,0x58,0xF9,0xD8,0x1E,0x54,0x30,0xA5,0x7B,0x36,0xDA,0xAB,0x8F,0x95,0x0A,0x3C,
	0x64,0xE6,0xEE,0x6A,0x63,0x09,0x4D,0x99,0x28,0x3A,0xFF,0x76,0x7E,0x12,0x4D,0xF0,
	0x59,0x98,0x3C,0x18,0xF8,0x09,0xE2,0x62,0x92,0x3C,0x53,0xAE,0xC2,0x95,0xD3,0x03,
	0x83,0xB5,0x4E,0x39,0xD6,0x09,0xD1,0x60,0xAF,0xCB,0x19,0x08,0xD0,0xBD,0x87,0x66,
	0x21,0x88,0x6C,0xA9,0x89,0xCA,0x9C,0x7D,0x58,0x08,0x73,0x07,0xCA,0x93,0x09,0x2D,0x65,0x1E,0xFA };
	mip = mirsys(1000, 16);
	mip->IOBASE = 16;
	x = mirvar(0);
	y = mirvar(0);
	ks = mirvar(0);
	kG = epoint_init();
	bytes_to_big(32, std_priKey, ks);
	SM2_Init();
	tmp = SM2_KeyGeneration(ks, kG);
	if (tmp != 0)
		return tmp;
	epoint_get(kG, x, y);
	big_to_bytes(SM2_NUMWORD, x, kGxy, 1);
	big_to_bytes(SM2_NUMWORD, y, kGxy + SM2_NUMWORD, 1);
	if (memcmp(kGxy, std_pubKey, SM2_NUMWORD * 2) != 0)
		return ERR_SELFTEST_KG;
	puts("原文");
	for (i = 0; i < 19; i++)
	{
		if (i > 0 && i % 8 == 0) printf("\n");
		printf("0x%x,", std_Message[i]);
	}
	tmp = SM2_Encrypt(std_rand, kG, std_Message, 19, Cipher);
	if (tmp != 0)
		return tmp;
	if (memcmp(Cipher, std_Cipher, 19 + SM2_NUMWORD * 3) != 0)
		return ERR_SELFTEST_ENC;


	puts("\n\n 密文:");
	for (i = 0; i < 19 + SM2_NUMWORD * 3; i++)
	{
		if (i > 0 && i % 8 == 0) printf("\n");
		printf("0x%x,", Cipher[i]);
	}

	tmp = SM2_Decrypt(ks, Cipher, 115, M);
	if (tmp != 0)
		return tmp;

	puts("\n\n解密结果:");
	for (i = 0; i < 19; i++)
	{
		if (i>0&&i%8 == 0) printf("\n");
		printf("0x%x,", M[i]);
	}

	if (memcmp(M, std_Message, 19) != 0)
		return ERR_SELFTEST_DEC;
	puts("\n解密成功");

	return 0;
}

  • enc.h
#pragma once

#include "miracl/miracl.h"

#define ECC_WORDSIZE 8
#define SM2_NUMBITS 256
#define SM2_NUMWORD (SM2_NUMBITS/ECC_WORDSIZE)
#define ERR_INFINITY_POINT 0x00000001
#define ERR_NOT_VALID_ELEMENT 0x00000002
#define ERR_NOT_VALID_POINT 0x00000003
#define ERR_ORDER 0x00000004
#define ERR_ARRAY_NULL 0x00000005
#define ERR_C3_MATCH 0x00000006
#define ERR_ECURVE_INIT 0x00000007
#define ERR_SELFTEST_KG 0x00000008
#define ERR_SELFTEST_ENC 0x00000009
#define ERR_SELFTEST_DEC 0x0000000A

extern unsigned char SM2_p[32];
extern unsigned char SM2_a[32];
extern unsigned char SM2_b[32];
extern unsigned char SM2_n[32];
extern unsigned char SM2_Gx[32];
extern unsigned char SM2_Gy[32];
extern unsigned char SM2_h[32];

extern big para_p, para_a, para_b, para_n, para_Gx, para_Gy, para_h;
extern epoint *G;
extern miracl *mip;

  • kdf.c
#include "kdf.h"
/****************************************************************
Function: BiToW
Description: calculate W from Bi
Calls:
Called By: SM3_compress
Input: Bi[16] //a block of a message
Output: W[68]
Return: null
Others:
****************************************************************/
void BiToW(unsigned long Bi[], unsigned long W[])
{
	int i;
	unsigned long tmp;
	for (i = 0; i <= 15; i++)
	{
		W[i] = Bi[i];
	}
	for (i = 16; i <= 67; i++)
	{
		tmp = W[i - 16]
			^ W[i - 9]
			^ SM3_rotl32(W[i - 3], 15);
		W[i] = SM3_p1(tmp)
			^ (SM3_rotl32(W[i - 13], 7))
			^ W[i - 6];
	}
}
/*****************************************************************
Function: WToW1
Description: calculate W1 from W
Calls:
Called By: SM3_compress
Input: W[68]
Output: W1[64]
Return: null
Others:
*****************************************************************/
void WToW1(unsigned long W[], unsigned long W1[])
{
	int i;
	for (i = 0; i <= 63; i++)
	{
		W1[i] = W[i] ^ W[i + 4];
	}
}
/******************************************************************
Function: CF
Description: calculate the CF compress function and update V
Calls:
Called By: SM3_compress
Input: W[68]
W1[64]
V[8]
Output: V[8]
Return: null
Others:
********************************************************************/
void CF(unsigned long W[], unsigned long W1[], unsigned long V[])
{
	unsigned long SS1;
	unsigned long SS2;
	unsigned long TT1;
	unsigned long TT2;
	unsigned long A, B, C, D, E, F, G, H;
	unsigned long T = SM3_T1;
	unsigned long FF;
	unsigned long GG;
	int j;
	A = V[0];
	B = V[1];
	C = V[2];
	D = V[3];
	E = V[4];
	F = V[5];
	G = V[6];
	H = V[7];
	for (j = 0; j <= 63; j++)
	{
		if (j == 0)
		{
			T = SM3_T1;
		}
		else if (j == 16)
		{
			T = SM3_rotl32(SM3_T2, 16);
		}
		else
		{
			T = SM3_rotl32(T, 1);
		}
		SS1 = SM3_rotl32((SM3_rotl32(A, 12) + E + T), 7);
		SS2 = SS1 ^ SM3_rotl32(A, 12);
		if (j <= 15)
		{
			FF = SM3_ff0(A, B, C);
		}
		else
		{
			FF = SM3_ff1(A, B, C);
		}
		TT1 = FF + D + SS2 + *W1;
		W1++;
		if (j <= 15)
		{
			GG = SM3_gg0(E, F, G);
		}
		else
		{
			GG = SM3_gg1(E, F, G);
		}
		TT2 = GG + H + SS1 + *W;
		W++;
		D = C;
		C = SM3_rotl32(B, 9);
		B = A;
		A = TT1;
		H = G;
		G = SM3_rotl32(F, 19);
		F = E;
		E = SM3_p0(TT2);
	}
	V[0] = A ^ V[0];
	V[1] = B ^ V[1];
	V[2] = C ^ V[2];
	V[3] = D ^ V[3];
	V[4] = E ^ V[4];
	V[5] = F ^ V[5];
	V[6] = G ^ V[6];
	V[7] = H ^ V[7];
}
/******************************************************************************
Function: BigEndian
Description: unsigned int endian converse.GM/T 0004-2012 requires to use big-endian.
if CPU uses little-endian, BigEndian function is a necessary
call to change the little-endian format into big-endian format.
Calls:
Called By: SM3_compress, SM3_done
Input: src[bytelen]
bytelen
Output: des[bytelen]
Return: null
Others: src and des could implies the same address
*******************************************************************************/
void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[])
{
	unsigned char tmp = 0;
	unsigned long i = 0;
	for (i = 0; i < bytelen / 4; i++)
	{
		tmp = des[4 * i];
		des[4 * i] = src[4 * i + 3];
		src[4 * i + 3] = tmp;
		tmp = des[4 * i + 1];
		des[4 * i + 1] = src[4 * i + 2];
		des[4 * i + 2] = tmp;
	}
}
/******************************************************************************
Function: SM3_init
Description: initiate SM3 state
Calls:
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_init(SM3_STATE *md)
{
	md->curlen = md->length = 0;
	md->state[0] = SM3_IVA;
	md->state[1] = SM3_IVB;
	md->state[2] = SM3_IVC;
	md->state[3] = SM3_IVD;
	md->state[4] = SM3_IVE;
	md->state[5] = SM3_IVF;
	md->state[6] = SM3_IVG;
	md->state[7] = SM3_IVH;
}
/******************************************************************************
Function: SM3_compress
Description: compress a single block of message
Calls: BigEndian
BiToW
WToW1
CF
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_compress(SM3_STATE * md)
{
	unsigned long W[68];
	unsigned long W1[64];
	BigEndian(md->buf, 64, md->buf);
	BiToW((unsigned long *)md->buf, W);
	WToW1(W, W1);
	CF(W, W1, md->state);
}
/******************************************************************************
Function: SM3_process
Description: compress the first (len/64) blocks of message
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
unsigned char buf[len] //the input message
int len //bytelen of message
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_process(SM3_STATE * md, unsigned char *buf, int len)
{
	while (len--)
	{
		/* copy byte */
		md->buf[md->curlen] = *buf++;
		md->curlen++;
		/* is 64 bytes full? */
		if (md->curlen == 64)
		{
			SM3_compress(md);
			md->length += 512;
			md->curlen = 0;
		}
	}
}
/******************************************************************************
Function: SM3_done
Description: compress the rest message that the SM3_process has left behind
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
Output: unsigned char *hash
Return: null
Others:
*******************************************************************************/
void SM3_done(SM3_STATE *md, unsigned char hash[])
{
	int i;
	unsigned char tmp = 0;
	/* increase the bit length of the message */
	md->length += md->curlen << 3;
	/* append the '1' bit */
	md->buf[md->curlen] = 0x80;
	md->curlen++;
	/* if the length is currently above 56 bytes, appends zeros till
	it reaches 64 bytes, compress the current block, creat a new
	block by appending zeros and length,and then compress it
	*/
	if (md->curlen > 56)
	{
		for (; md->curlen < 64;)
		{
			md->buf[md->curlen] = 0;
			md->curlen++;
		}
		SM3_compress(md);
		md->curlen = 0;
	}
	/* if the length is less than 56 bytes, pad upto 56 bytes of zeroes */
	for (; md->curlen < 56;)
	{
		md->buf[md->curlen] = 0;
		md->curlen++;
	}
	/* since all messages are under 2^32 bits we mark the top bits zero */
	for (i = 56; i < 60; i++)
	{
		md->buf[i] = 0;
	}
	/* append length */
	md->buf[63] = md->length & 0xff;
	md->buf[62] = (md->length >> 8) & 0xff;
	md->buf[61] = (md->length >> 16) & 0xff;
	md->buf[60] = (md->length >> 24) & 0xff;
	SM3_compress(md);
	/* copy output */
	memcpy(hash, md->state, SM3_len / 8);
	BigEndian(hash, SM3_len / 8, hash);
}
/******************************************************************************
Function: SM3_256
Description: calculate a hash value from a given message
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char buf[len] //the input message
int len //bytelen of the message
Output: unsigned char hash[32]
Return: null
Others:
*******************************************************************************/
void SM3_256(unsigned char buf[], int len, unsigned char hash[])
{
	SM3_STATE md;
	SM3_init(&md);
	SM3_process(&md, buf, len);
	SM3_done(&md, hash);
}
/******************************************************************************
Function: SM3_KDF
Description: key derivation function
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char Z[zlen]
unsigned short zlen //bytelen of Z
unsigned short klen //bytelen of K
Output: unsigned char K[klen] //shared secret key
Return: null
Others:
*******************************************************************************/
void SM3_KDF(unsigned char Z[], unsigned short zlen, unsigned short klen, unsigned char K[])
{
	unsigned short i, j, t;
	unsigned int bitklen;
	SM3_STATE md;
	unsigned char Ha[SM2_NUMWORD];
	unsigned char ct[4] = { 0,0,0,1 };
	bitklen = klen * 8;
	if (bitklen%SM2_NUMBITS)
		t = bitklen / SM2_NUMBITS + 1;
	else
		t = bitklen / SM2_NUMBITS;
	for (i = 1; i < t; i++)
	{
		SM3_init(&md);
		SM3_process(&md, Z, zlen);
		SM3_process(&md, ct, 4);
		SM3_done(&md, Ha);
		memcpy((K + SM2_NUMWORD * (i - 1)), Ha, SM2_NUMWORD);
		if (ct[3] == 0xff)
		{
			ct[3] = 0;
			if (ct[2] == 0xff)
			{
				ct[2] = 0;
				if (ct[1] == 0xff)
				{
					ct[1] = 0;
					ct[0]++;
				}
				else ct[1]++;
			}
			else ct[2]++;
		}
		else ct[3]++;
	}
	SM3_init(&md);
	SM3_process(&md, Z, zlen);
	SM3_process(&md, ct, 4);
	SM3_done(&md, Ha);
	if (bitklen%SM2_NUMBITS)
	{
		i = (SM2_NUMBITS - bitklen + SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8;
		j = (bitklen - SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8;
		memcpy((K + SM2_NUMWORD * (t - 1)), Ha, j);
	}
	else
	{
		memcpy((K + SM2_NUMWORD * (t - 1)), Ha, SM2_NUMWORD);
	}
}
签名验签
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ nano sv.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ nano sv.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ vim kdf.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ vim kdf.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ vim test.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ gcc -o test test.c sv.c kdf.c -lmiracl_32 -m32
In file included from kdf.c:1:
kdf.c: In function ‘CF’:
kdf.h:22:31: warning: result of ‘2055708042 << 16’ requires 48 bits to represent, but ‘int’ only has 32 bits [-Wshift-overflow=]
   22 | #define SM3_rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
      |                               ^~
kdf.c:90:269: note: in expansion of macro ‘SM3_rotl32’
   90 |                                                                                                 T = SM3_rotl32(SM3_T2, 16);
      |                                                                                                     ^~~~~~~~~~

ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ ./test
SM2 签名验签成功
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ git commit -m "sm2_sv"
[master 0b23ef7] sm2_sv
 6 files changed, 906 insertions(+)
 create mode 100644 shiyan2/2-2/sm2/sv/kdf.c
 create mode 100644 shiyan2/2-2/sm2/sv/kdf.h
 create mode 100644 shiyan2/2-2/sm2/sv/sv.c
 create mode 100644 shiyan2/2-2/sm2/sv/sv.h
 create mode 100755 shiyan2/2-2/sm2/sv/test
 create mode 100644 shiyan2/2-2/sm2/sv/test.c
  • sv.c
 #include "sv.h"
#include "kdf.h"

big Gx, Gy, p, a, b, n;
epoint *G, *nG;

unsigned char SM2_p[32] = { 0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff };
unsigned char SM2_a[32] = { 0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xfc };
unsigned char SM2_b[32] = { 0x28,0xe9,0xfa,0x9e, 0x9d,0x9f,0x5e,0x34, 0x4d,0x5a,0x9e,0x4b,0xcf,0x65,0x09,0xa7,
0xf3,0x97,0x89,0xf5, 0x15,0xab,0x8f,0x92, 0xdd,0xbc,0xbd,0x41,0x4d,0x94,0x0e,0x93 };
unsigned char SM2_Gx[32] = { 0x32,0xc4,0xae,0x2c, 0x1f,0x19,0x81,0x19,0x5f,0x99,0x04,0x46,0x6a,0x39,0xc9,0x94,
0x8f,0xe3,0x0b,0xbf,0xf2,0x66,0x0b,0xe1,0x71,0x5a,0x45,0x89,0x33,0x4c,0x74,0xc7 };
unsigned char SM2_Gy[32] = { 0xbc,0x37,0x36,0xa2,0xf4,0xf6,0x77,0x9c,0x59,0xbd,0xce,0xe3,0x6b,0x69,0x21,0x53,0xd0,
0xa9,0x87,0x7c,0xc6,0x2a,0x47,0x40,0x02,0xdf,0x32,0xe5,0x21,0x39,0xf0,0xa0 };
unsigned char SM2_n[32] = { 0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x72,0x03,0xdf,0x6b,0x21,0xc6,0x05,0x2b,0x53,0xbb,0xf4,0x09,0x39,0xd5,0x41,0x23 };


/****************************************************************
Function: SM2_Init
Description: Initiate SM2 curve
Calls: MIRACL functions
Called By: SM2_KeyGeneration,SM2_Sign,SM2_Verify,SM2_SelfCheck
Input: null
Output: null
Return: 0: sucess;
1: parameter initialization error;
4: the given point G is not a point of order n
Others:
****************************************************************/
int SM2_Init()
{
	Gx = mirvar(0);
	Gy = mirvar(0);
	p = mirvar(0);
	a = mirvar(0);
	b = mirvar(0);
	n = mirvar(0);
	bytes_to_big(SM2_NUMWORD, SM2_Gx, Gx);
	bytes_to_big(SM2_NUMWORD, SM2_Gy, Gy);
	bytes_to_big(SM2_NUMWORD, SM2_p, p);
	bytes_to_big(SM2_NUMWORD, SM2_a, a);
	bytes_to_big(SM2_NUMWORD, SM2_b, b);
	bytes_to_big(SM2_NUMWORD, SM2_n, n);
	ecurve_init(a, b, p, MR_PROJECTIVE);
	G = epoint_init();
	nG = epoint_init();
	if (!epoint_set(Gx, Gy, 0, G))
	{
		return ERR_ECURVE_INIT;
	}
	ecurve_mult(n, G, nG);
	if (!point_at_infinity(nG))
	{
		return ERR_ORDER;
	}
	return 0;
}
/****************************************************************
Function: Test_Point
Description: test if the given point is on SM2 curve
Calls:
Called By: SM2_KeyGeneration
Input: point
Output: null
Return: 0: sucess
3: not a valid point on curve
Others:
****************************************************************/
int Test_Point(epoint* point)
{
	big x, y, x_3, tmp;
	x = mirvar(0);
	y = mirvar(0);
	x_3 = mirvar(0);
	tmp = mirvar(0);
	epoint_get(point, x, y);
	power(x, 3, p, x_3);
	multiply(x, a, x);
	divide(x, p, tmp);
	add(x_3, x, x);
	add(x, b, x);
	divide(x, p, tmp);
	power(y, 2, p, y);
	if (mr_compare(x, y) != 0)
		return ERR_NOT_VALID_POINT;
	else
		return 0;
}
/****************************************************************
Function: Test_PubKey
Description: test if the given public key is valid
Calls:
Called By: SM2_KeyGeneration
Input: pubKey //a point
Output: null
Return: 0: sucess
2: a point at infinity
5: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
Others:
****************************************************************/
int Test_PubKey(epoint *pubKey)
{
	big x, y, x_3, tmp;
	epoint *nP;
	x = mirvar(0);
	y = mirvar(0);
	x_3 = mirvar(0);
	tmp = mirvar(0);
	nP = epoint_init();
	if (point_at_infinity(pubKey))
		return ERR_INFINITY_POINT;
	epoint_get(pubKey, x, y);
	if ((mr_compare(x, p) != -1) || (mr_compare(y, p) != -1))
		return ERR_NOT_VALID_ELEMENT;
	if (Test_Point(pubKey) != 0)
		return ERR_NOT_VALID_POINT;
	ecurve_mult(n, pubKey, nP);
	if (!point_at_infinity(nP))
		return ERR_ORDER;
	return 0;
}
/****************************************************************
Function: Test_Zero
Description: test if the big x is zero
Calls:
Called By: SM2_Sign
Input: pubKey //a point
Output: null
Return: 0: x!=0
1: x==0
Others:
****************************************************************/
int Test_Zero(big x)
{
	big zero;
	zero = mirvar(0);
	if (mr_compare(x, zero) == 0)
		return 1;
	else return 0;
}
/****************************************************************
Function: Test_n
Description: test if the big x is order n
Calls:
Called By: SM2_Sign
Input: big x //a miracl data type
Output: null
Return: 0: sucess
1: x==n,fail
Others:
****************************************************************/
int Test_n(big x)
{
	if (mr_compare(x, n) == 0)
		return 1;
	else return 0;
}
/****************************************************************
Function: Test_Range
Description: test if the big x belong to the range[1,n-1]
Calls:
Called By: SM2_Verify
Input: big x ///a miracl data type
Output: null
Return: 0: sucess
1: fail
Others:
****************************************************************/
int Test_Range(big x)
{
	big one, decr_n;
	one = mirvar(0);
	decr_n = mirvar(0);
	convert(1, one);
	decr(n, 1, decr_n);
	if ((mr_compare(x, one) < 0) | (mr_compare(x, decr_n) > 0))
		return 1;
	return 0;
}
/****************************************************************
Function: SM2_KeyGeneration
Description: calculate a pubKey out of a given priKey
Calls: SM2_SelfCheck()
Called By: SM2_Init()
Input: priKey // a big number lies in[1,n-2]
Output: pubKey // pubKey=[priKey]G
Return: 0: sucess
2: a point at infinity
5: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
Others:
****************************************************************/
int SM2_KeyGeneration(unsigned char PriKey[], unsigned char Px[], unsigned char Py[])
{
	int i = 0;
	big d, PAx, PAy;
	epoint *PA;
	SM2_Init();
	PA = epoint_init();
	d = mirvar(0);
	PAx = mirvar(0);
	PAy = mirvar(0);
	bytes_to_big(SM2_NUMWORD, PriKey, d);
	ecurve_mult(d, G, PA);
	epoint_get(PA, PAx, PAy);
	big_to_bytes(SM2_NUMWORD, PAx, Px, TRUE);
	big_to_bytes(SM2_NUMWORD, PAy, Py, TRUE);
	i = Test_PubKey(PA);
	if (i)
		return i;
	else
		return 0;
}
/****************************************************************
Function: SM2_Sign
Description: SM2 signature algorithm
Calls: SM2_Init(),Test_Zero(),Test_n(), SM3_256()
Called By: SM2_SelfCheck()
Input: message //the message to be signed
len //the length of message
ZA // ZA=Hash(ENTLA|| IDA|| a|| b|| Gx || Gy || xA|| yA)
rand //a random number K lies in [1,n-1]
d //the private key
Output: R,S //signature result
Return: 0: sucess
1: parameter initialization error;
4: the given point G is not a point of order n
6: the signed r equals 0 or r+rand equals n
7 the signed s equals 0
Others:
****************************************************************/
int SM2_Sign(unsigned char *message, int len, unsigned char ZA[], unsigned char rand[], unsigned char d[], unsigned char R[], unsigned char S[])
{
	unsigned char hash[SM3_len / 8];
	int M_len = len + SM3_len / 8;
	unsigned char *M = NULL;
	int i;
	big dA, r, s, e, k, KGx, KGy;
	big rem, rk, z1, z2;
	epoint *KG;
	i = SM2_Init();
	if (i) return i;
	dA = mirvar(0);
	e = mirvar(0);
	k = mirvar(0);
	KGx = mirvar(0);
	KGy = mirvar(0);
	r = mirvar(0);
	s = mirvar(0);
	rem = mirvar(0);
	rk = mirvar(0);
	z1 = mirvar(0);
	z2 = mirvar(0);
	bytes_to_big(SM2_NUMWORD, d, dA);
	KG = epoint_init();
	M = (char *)malloc(sizeof(char)*(M_len + 1));
	memcpy(M, ZA, SM3_len / 8);
	memcpy(M + SM3_len / 8, message, len);
	SM3_256(M, M_len, hash);
	bytes_to_big(SM3_len / 8, hash, e);
	bytes_to_big(SM3_len / 8, rand, k);
	ecurve_mult(k, G, KG);
	epoint_get(KG, KGx, KGy);
	add(e, KGx, r);
	divide(r, n, rem);
	add(r, k, rk);
	if (Test_Zero(r) | Test_n(rk))
		return ERR_GENERATE_R;
	incr(dA, 1, z1);
	xgcd(z1, n, z1, z1, z1);
	multiply(r, dA, z2);
	divide(z2, n, rem);
	subtract(k, z2, z2);
	add(z2, n, z2);
	multiply(z1, z2, s);
	divide(s, n, rem);
	if (Test_Zero(s))
		return ERR_GENERATE_S;
	big_to_bytes(SM2_NUMWORD, r, R, TRUE);
	big_to_bytes(SM2_NUMWORD, s, S, TRUE);
	free(M);
	return 0;
}
/****************************************************************
Function: SM2_Verify
Description: SM2 verification algorithm
Calls: SM2_Init(),Test_Range(), Test_Zero(),SM3_256()
Called By: SM2_SelfCheck()
Input: message //the message to be signed
len //the length of message
ZA //ZA=Hash(ENTLA|| IDA|| a|| b|| Gx || Gy || xA|| yA)
Px,Py //the public key
R,S //signature result
Output:
Return: 0: sucess
1: parameter initialization error;
4: the given point G is not a point of order n
B: public key error
8: the signed R out of range [1,n-1]
9: the signed S out of range [1,n-1]
A: the intermediate data t equals 0
C: verification fail
Others:
****************************************************************/
int SM2_Verify(unsigned char *message, int len, unsigned char ZA[], unsigned char Px[], unsigned char Py[], unsigned char R[], unsigned char S[])
{
	unsigned char hash[SM3_len / 8];
	int M_len = len + SM3_len / 8;
	unsigned char *M = NULL;
	int i;
	big PAx, PAy, r, s, e, t, rem, x1, y1;
	big RR;
	epoint *PA, *sG, *tPA;
	i = SM2_Init();
	if (i) return i;
	PAx = mirvar(0);
	PAy = mirvar(0);
	r = mirvar(0);
	s = mirvar(0);
	e = mirvar(0);
	t = mirvar(0);
	x1 = mirvar(0);
	y1 = mirvar(0);
	rem = mirvar(0);
	RR = mirvar(0);
	PA = epoint_init();
	sG = epoint_init();
	tPA = epoint_init();
	bytes_to_big(SM2_NUMWORD, Px, PAx);
	bytes_to_big(SM2_NUMWORD, Py, PAy);
	bytes_to_big(SM2_NUMWORD, R, r);
	bytes_to_big(SM2_NUMWORD, S, s);
	if (!epoint_set(PAx, PAy, 0, PA))
	{
		return ERR_PUBKEY_INIT;
	}
	if (Test_Range(r))
		return ERR_OUTRANGE_R;
	if (Test_Range(s))
		return ERR_OUTRANGE_S;
	M = (char *)malloc(sizeof(char)*(M_len + 1));
	memcpy(M, ZA, SM3_len / 8);
	memcpy(M + SM3_len / 8, message, len);
	SM3_256(M, M_len, hash);
	bytes_to_big(SM3_len / 8, hash, e);
	add(r, s, t);
	divide(t, n, rem);
	if (Test_Zero(t))
		return ERR_GENERATE_T;
	ecurve_mult(s, G, sG);
	ecurve_mult(t, PA, tPA);
	ecurve_add(sG, tPA);
	epoint_get(tPA, x1, y1);
	add(e, x1, RR);
	divide(RR, n, rem);
	free(M);
	if (mr_compare(RR, r) == 0)
		return 0;
	else
		return ERR_DATA_MEMCMP;
}
/****************************************************************
Function: SM2_SelfCheck
Description: SM2 self check
Calls: SM2_Init(), SM2_KeyGeneration,SM2_Sign, SM2_Verify,SM3_256()
Called By:
Input:
Output:
Return: 0: sucess
1: paremeter initialization error
2: a point at infinity
5: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
B: public key error
8: the signed R out of range [1,n-1]
9: the signed S out of range [1,n-1]
A: the intermediate data t equals 0
C: verification fail
Others:
****************************************************************/
int SM2_SelfCheck()
{
	unsigned char dA[32] = { 0x39,0x45,0x20,0x8f,0x7b,0x21,0x44,0xb1,0x3f,0x36,0xe3,0x8a,0xc6,0xd3,0x9f,
	0x95,0x88,0x93,0x93,0x69,0x28,0x60,0xb5,0x1a,0x42,0xfb,0x81,0xef,0x4d,0xf7,0xc5,0xb8 };
	unsigned char rand[32] = { 0x59,0x27,0x6E,0x27,0xD5,0x06,0x86,0x1A,0x16,0x68,0x0F,0x3A,0xD9,0xC0,0x2D,
	0xCC,0xEF,0x3C,0xC1,0xFA,0x3C,0xDB,0xE4,0xCE,0x6D,0x54,0xB8,0x0D,0xEA,0xC1,0xBC,0x21 };
	/* unsigned char xA[32]={0x09,0xf9,0xdf,0x31,0x1e,0x54,0x21,0xa1,0x50,0xdd,0x7d,0x16,0x1e,0x4b,0xc5,
	0xc6,0x72,0x17,0x9f,0xad,0x18,0x33,0xfc,0x07,0x6b,0xb0,0x8f,0xf3,0x56,0xf3,0x50,0x20};
	unsigned char yA[32]={0xcc,0xea,0x49,0x0c,0xe2,0x67,0x75,0xa5,0x2d,0xc6,0xea,0x71,0x8c,0xc1,0xaa,
	0x60,0x0a,0xed,0x05,0xfb,0xf3,0x5e,0x08,0x4a,0x66,0x32,0xf6,0x07,0x2d,0xa9,0xad,0x13};*/
	unsigned char xA[32], yA[32];
	unsigned char r[32], s[32];
	unsigned char IDA[16] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,
	0x34,0x35,0x36,0x37,0x38 };	int IDA_len = 16;
	unsigned char ENTLA[2] = { 0x00,0x80 };
	unsigned char *message = "message digest";
	int len = strlen(message);
	unsigned char ZA[SM3_len / 8];
	unsigned char Msg[210];
	int temp;
	miracl *mip = mirsys(10000, 16);
	mip->IOBASE = 16;
	temp = SM2_KeyGeneration(dA, xA, yA);
	if (temp)
		return temp;
	memcpy(Msg, ENTLA, 2);
	memcpy(Msg + 2, IDA, IDA_len);
	memcpy(Msg + 2 + IDA_len, SM2_a, SM2_NUMWORD);
	memcpy(Msg + 2 + IDA_len + SM2_NUMWORD, SM2_b, SM2_NUMWORD);
	memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 2, SM2_Gx, SM2_NUMWORD);
	memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 3, SM2_Gy, SM2_NUMWORD);
	memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 4, xA, SM2_NUMWORD);
	memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 5, yA, SM2_NUMWORD);
	SM3_256(Msg, 210, ZA);
	temp = SM2_Sign(message, len, ZA, rand, dA, r, s);
	if (temp)
		return temp;
	temp = SM2_Verify(message, len, ZA, xA, yA, r, s);
	if (temp)
		return temp;
	return 0;
}

  • sv,h
#pragma once
 
 
#include<string.h>
#include<malloc.h>
#include "miracl/miracl.h"

#define SM2_WORDSIZE 8
#define SM2_NUMBITS 256
#define SM2_NUMWORD (SM2_NUMBITS/SM2_WORDSIZE)
#define ERR_ECURVE_INIT 0x00000001
#define ERR_INFINITY_POINT 0x00000002
#define ERR_NOT_VALID_POINT 0x00000003
#define ERR_ORDER 0x00000004
#define ERR_NOT_VALID_ELEMENT 0x00000005
#define ERR_GENERATE_R 0x00000006
#define ERR_GENERATE_S 0x00000007
#define ERR_OUTRANGE_R 0x00000008
#define ERR_OUTRANGE_S 0x00000009
#define ERR_GENERATE_T 0x0000000A
#define ERR_PUBKEY_INIT 0x0000000B
#define ERR_DATA_MEMCMP 0x0000000C



extern unsigned char SM2_p[32];
extern unsigned char SM2_a[32];
extern unsigned char SM2_b[32];
extern unsigned char SM2_n[32];
extern unsigned char SM2_Gx[32];
extern unsigned char SM2_Gy[32];
extern unsigned char SM2_h[32];




extern big Gx, Gy, p, a, b, n;
extern epoint *G, *nG;
int SM2_Init();
int Test_Point(epoint* point);
int Test_PubKey(epoint *pubKey);
int Test_Zero(big x);
int Test_n(big x);
int Test_Range(big x);
int SM2_KeyGeneration(unsigned char PriKey[], unsigned char Px[], unsigned char Py[]);
int SM2_Sign(unsigned char *message, int len, unsigned char ZA[], unsigned char rand[], unsigned char d[], unsigned char R[], unsigned char S[]);
int SM2_Verify(unsigned char *message, int len, unsigned char ZA[], unsigned char Px[], unsigned char Py[], unsigned char R[], unsigned char S[]);
int SM2_SelfCheck();
  • kdf.c
#include "kdf.h"
#include "sv.h"


/****************************************************************
Function: BiToW
Description: calculate W from Bi
Calls:
Called By: SM3_compress
Input: Bi[16] //a block of a message
Output: W[68]
Return: null
Others:
****************************************************************/
void BiToW(unsigned long Bi[], unsigned long W[])
{
	int i;
	unsigned long tmp;
	for (i = 0; i <= 15; i++)
	{
		W[i] = Bi[i];
	}
	for (i = 16; i <= 67; i++)
	{
		tmp = W[i - 16]
			^ W[i - 9]
			^ SM3_rotl32(W[i - 3], 15);
		W[i] = SM3_p1(tmp)
			^ (SM3_rotl32(W[i - 13], 7))
			^ W[i - 6];
	}
}
/*****************************************************************
Function: WToW1
Description: calculate W1 from W
Calls:
Called By: SM3_compress
Input: W[68]
Output: W1[64]
Return: null
Others:
*****************************************************************/
void WToW1(unsigned long W[], unsigned long W1[])
{
	int i;
	for (i = 0; i <= 63; i++)
	{
		W1[i] = W[i] ^ W[i + 4];
	}
}
/******************************************************************
Function: CF
Description: calculate the CF compress function and update V
Calls:
Called By: SM3_compress
Input: W[68]
W1[64]
V[8]
Output: V[8]
Return: null
Others:
********************************************************************/
void CF(unsigned long W[], unsigned long W1[], unsigned long V[])
{
	unsigned long SS1;
	unsigned long SS2;
	unsigned long TT1;
	unsigned long TT2;
	unsigned long A, B, C, D, E, F, G, H;
	unsigned long T = SM3_T1;
	unsigned long FF;
	unsigned long GG;
	int j;
	A = V[0];
	B = V[1];
	C = V[2];
	D = V[3];
	E = V[4];
	F = V[5];
	G = V[6];
	H = V[7];
	for (j = 0; j <= 63; j++)
	{
		if (j == 0)
		{
			T = SM3_T1;
		}
		else if (j == 16)
		{
			T = SM3_rotl32(SM3_T2, 16);
		}
		else
		{
			T = SM3_rotl32(T, 1);
		}
		SS1 = SM3_rotl32((SM3_rotl32(A, 12) + E + T), 7);
		SS2 = SS1 ^ SM3_rotl32(A, 12);
		if (j <= 15)
		{
			FF = SM3_ff0(A, B, C);
		}
		else
		{
			FF = SM3_ff1(A, B, C);
		}
		TT1 = FF + D + SS2 + *W1;
		W1++;
		if (j <= 15)
		{
			GG = SM3_gg0(E, F, G);
		}
		else
		{
			GG = SM3_gg1(E, F, G);
		}
		TT2 = GG + H + SS1 + *W;
		W++;
		D = C;
		C = SM3_rotl32(B, 9);
		B = A;
		A = TT1;
		H = G;
		G = SM3_rotl32(F, 19);
		F = E;
		E = SM3_p0(TT2);
	}
	V[0] = A ^ V[0];
	V[1] = B ^ V[1];
	V[2] = C ^ V[2];
	V[3] = D ^ V[3];
	V[4] = E ^ V[4];
	V[5] = F ^ V[5];
	V[6] = G ^ V[6];
	V[7] = H ^ V[7];
}
/******************************************************************************
Function: BigEndian
Description: unsigned int endian converse.GM/T 0004-2012 requires to use big-endian.
if CPU uses little-endian, BigEndian function is a necessary
call to change the little-endian format into big-endian format.
Calls:
Called By: SM3_compress, SM3_done
Input: src[bytelen]
bytelen
Output: des[bytelen]
Return: null
Others: src and des could implies the same address
*******************************************************************************/
void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[])
{
	unsigned char tmp = 0;
	unsigned long i = 0;
	for (i = 0; i < bytelen / 4; i++)
	{
		tmp = des[4 * i];
		des[4 * i] = src[4 * i + 3];
		src[4 * i + 3] = tmp;
		tmp = des[4 * i + 1];
		des[4 * i + 1] = src[4 * i + 2];
		des[4 * i + 2] = tmp;
	}
}
/******************************************************************************
Function: SM3_init
Description: initiate SM3 state
Calls:
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_init(SM3_STATE *md)
{
	md->curlen = md->length = 0;
	md->state[0] = SM3_IVA;
	md->state[1] = SM3_IVB;
	md->state[2] = SM3_IVC;
	md->state[3] = SM3_IVD;
	md->state[4] = SM3_IVE;
	md->state[5] = SM3_IVF;
	md->state[6] = SM3_IVG;
	md->state[7] = SM3_IVH;
}
/******************************************************************************
Function: SM3_compress
Description: compress a single block of message
Calls: BigEndian
BiToW
WToW1
CF
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_compress(SM3_STATE * md)
{
	unsigned long W[68];
	unsigned long W1[64];
	BigEndian(md->buf, 64, md->buf);
	BiToW((unsigned long *)md->buf, W);
	WToW1(W, W1);
	CF(W, W1, md->state);
}
/******************************************************************************
Function: SM3_process
Description: compress the first (len/64) blocks of message
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
unsigned char buf[len] //the input message
int len //bytelen of message
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_process(SM3_STATE * md, unsigned char *buf, int len)
{
	while (len--)
	{
		/* copy byte */
		md->buf[md->curlen] = *buf++;
		md->curlen++;
		/* is 64 bytes full? */
		if (md->curlen == 64)
		{
			SM3_compress(md);
			md->length += 512;
			md->curlen = 0;
		}
	}
}
/******************************************************************************
Function: SM3_done
Description: compress the rest message that the SM3_process has left behind
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
Output: unsigned char *hash
Return: null
Others:
*******************************************************************************/
void SM3_done(SM3_STATE *md, unsigned char hash[])
{
	int i;
	unsigned char tmp = 0;
	/* increase the bit length of the message */
	md->length += md->curlen << 3;
	/* append the '1' bit */
	md->buf[md->curlen] = 0x80;
	md->curlen++;
	/* if the length is currently above 56 bytes, appends zeros till
	it reaches 64 bytes, compress the current block, creat a new
	block by appending zeros and length,and then compress it
	*/
	if (md->curlen > 56)
	{
		for (; md->curlen < 64;)
		{
			md->buf[md->curlen] = 0;
			md->curlen++;
		}
		SM3_compress(md);
		md->curlen = 0;
	}
	/* if the length is less than 56 bytes, pad upto 56 bytes of zeroes */
	for (; md->curlen < 56;)
	{
		md->buf[md->curlen] = 0;
		md->curlen++;
	}
	/* since all messages are under 2^32 bits we mark the top bits zero */
	for (i = 56; i < 60; i++)
	{
		md->buf[i] = 0;
	}
	/* append length */
	md->buf[63] = md->length & 0xff;
	md->buf[62] = (md->length >> 8) & 0xff;
	md->buf[61] = (md->length >> 16) & 0xff;
	md->buf[60] = (md->length >> 24) & 0xff;
	SM3_compress(md);
	/* copy output */
	memcpy(hash, md->state, SM3_len / 8);
	BigEndian(hash, SM3_len / 8, hash);
}
/******************************************************************************
Function: SM3_256
Description: calculate a hash value from a given message
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char buf[len] //the input message
int len //bytelen of the message
Output: unsigned char hash[32]
Return: null
Others:
*******************************************************************************/
void SM3_256(unsigned char buf[], int len, unsigned char hash[])
{
	SM3_STATE md;
	SM3_init(&md);
	SM3_process(&md, buf, len);
	SM3_done(&md, hash);
}
/******************************************************************************
Function: SM3_KDF
Description: key derivation function
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char Z[zlen]
unsigned short zlen //bytelen of Z
unsigned short klen //bytelen of K
Output: unsigned char K[klen] //shared secret key
Return: null
Others:
*******************************************************************************/
void SM3_KDF(unsigned char Z[], unsigned short zlen, unsigned short klen, unsigned char K[])
{
	unsigned short i, j, t;
	unsigned int bitklen;
	SM3_STATE md;
	unsigned char Ha[SM2_NUMWORD];
	unsigned char ct[4] = { 0,0,0,1 };
	bitklen = klen * 8;
	if (bitklen%SM2_NUMBITS)
		t = bitklen / SM2_NUMBITS + 1;
	else
		t = bitklen / SM2_NUMBITS;
	for (i = 1; i < t; i++)
	{
		SM3_init(&md);
		SM3_process(&md, Z, zlen);
		SM3_process(&md, ct, 4);
		SM3_done(&md, Ha);
		memcpy((K + SM2_NUMWORD * (i - 1)), Ha, SM2_NUMWORD);
		if (ct[3] == 0xff)
		{
			ct[3] = 0;
			if (ct[2] == 0xff)
			{
				ct[2] = 0;
				if (ct[1] == 0xff)
				{
					ct[1] = 0;
					ct[0]++;
				}
				else ct[1]++;
			}
			else ct[2]++;
		}
		else ct[3]++;
	}
	SM3_init(&md);
	SM3_process(&md, Z, zlen);
	SM3_process(&md, ct, 4);
	SM3_done(&md, Ha);
	if (bitklen%SM2_NUMBITS)
	{
		i = (SM2_NUMBITS - bitklen + SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8;
		j = (bitklen - SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8;
		memcpy((K + SM2_NUMWORD * (t - 1)), Ha, j);
	}
	else
	{
		memcpy((K + SM2_NUMWORD * (t - 1)), Ha, SM2_NUMWORD);
	}
}

  • kdf.h

 
#include <string.h>
#define SM3_len 256
#define SM3_T1 0x79CC4519
#define SM3_T2 0x7A879D8A
#define SM3_IVA 0x7380166f
#define SM3_IVB 0x4914b2b9
#define SM3_IVC 0x172442d7
#define SM3_IVD 0xda8a0600
#define SM3_IVE 0xa96f30bc
#define SM3_IVF 0x163138aa
#define SM3_IVG 0xe38dee4d
#define SM3_IVH 0xb0fb0e4e
/* Various logical functions */
#define SM3_p1(x) (x^SM3_rotl32(x,15)^SM3_rotl32(x,23))
#define SM3_p0(x) (x^SM3_rotl32(x,9)^SM3_rotl32(x,17))
#define SM3_ff0(a,b,c) (a^b^c)
#define SM3_ff1(a,b,c) ((a&b)|(a&c)|(b&c))
#define SM3_gg0(e,f,g) (e^f^g)
#define SM3_gg1(e,f,g) ((e&f)|((~e)&g))
#define SM3_rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
#define SM3_rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
typedef struct {
	unsigned long state[8];
	unsigned long length;
	unsigned long curlen;
	unsigned char buf[64];
} SM3_STATE;
void BiToWj(unsigned long Bi[], unsigned long Wj[]);
void WjToWj1(unsigned long Wj[], unsigned long Wj1[]);
void CF(unsigned long Wj[], unsigned long Wj1[], unsigned long V[]);
void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[]);
void SM3_init(SM3_STATE *md);
void SM3_process(SM3_STATE * md, unsigned char buf[], int len);
void SM3_done(SM3_STATE *md, unsigned char *hash);
void SM3_compress(SM3_STATE * md);
void SM3_256(unsigned char buf[], int len, unsigned char hash[]);
void SM3_KDF(unsigned char *Z, unsigned short zlen, unsigned short klen, unsigned char *K);
  • test.c

#include "sv.h"

void main()
{
	if (SM2_SelfCheck())
	{
		puts("SM2 签名验签出错");
		return;
	}
	puts("SM2 签名验签成功");
}

sm3

一段式SM3算法
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/1$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/1$ g++ -o test test.cpp -m32
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/1$ ./test
SM3 Hash:
66 c7 f0 f4 62 ee ed d9 d1 f2 d4 6b dc 10 e4 e2
41 67 c4 87 5c f2 f7 a2 29 7d a0 2b 8f 4b a8 e0
  • test.cpp
#include <stdio.h>
#include <memory>
#include <cstring>
#include <cstdint>
unsigned char IV[256 / 8] = { 0x73,0x80,0x16,0x6f,0x49,0x14,0xb2,0xb9,0x17,0x24,0x42,0xd7,0xda,0x8a,0x06,0x00,0xa9,0x6f,0x30,0xbc,0x16,0x31,0x38,0xaa,0xe3,0x8d,0xee,0x4d,0xb0,0xfb,0x0e,0x4e };

unsigned long SL(unsigned long X, int n)
{
	uint64_t x = X;
	x = x << (n % 32);
	unsigned long l = (unsigned long)(x >> 32);
	return x | l;
}

unsigned long Tj(int j)
{
	if (j <= 15)
	{
		return 0x79cc4519;
	}
	else
	{
		return 0x7a879d8a;
	}
}

unsigned long FFj(int j, unsigned long X, unsigned long Y, unsigned long Z)
{
	if (j <= 15)
	{
		return X ^ Y ^ Z;
	}
	else
	{
		return (X & Y) | (X & Z) | (Y & Z);
	}
}

unsigned long GGj(int j, unsigned long X, unsigned long Y, unsigned long Z)
{
	if (j <= 15)
	{
		return X ^ Y ^ Z;
	}
	else
	{
		return (X & Y) | (~X & Z);
	}
}

unsigned long P0(unsigned long X)
{
	return X ^ SL(X, 9) ^ SL(X, 17);
}

unsigned long P1(unsigned long X)
{
	return X ^ SL(X, 15) ^ SL(X, 23);
}

void EB(unsigned char Bi[512 / 8], unsigned long W[68], unsigned long W1[64])
{
	for (int i = 0; i < 16; ++i)
	{
		W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3];
	}

	for (int j = 16; j <= 67; ++j)
	{
		W[j] = P1(W[j - 16] ^ W[j - 9] ^ SL(W[j - 3], 15)) ^ SL(W[j - 13], 7) ^ W[j - 6];
	}

	for (int j = 0; j <= 63; ++j)
	{
		W1[j] = W[j] ^ W[j + 4];
	}
}

void CF(unsigned char Vi[256 / 8], unsigned char Bi[512 / 8], unsigned char Vi1[256 / 8])
{
	unsigned long W[68] = { 0 };
	unsigned long W1[64] = { 0 };

	EB(Bi, W, W1);

	unsigned long R[8] = { 0 };
	for (int i = 0; i < 8; ++i)
	{
		R[i] = ((unsigned long)Vi[i * 4]) << 24 | ((unsigned long)Vi[i * 4 + 1]) << 16 | ((unsigned long)Vi[i * 4 + 2]) << 8 | ((unsigned long)Vi[i * 4 + 3]);
	}

	unsigned long A = R[0], B = R[1], C = R[2], D = R[3], E = R[4], F = R[5], G = R[6], H = R[7];

	unsigned long SS1, SS2, TT1, TT2;
	for (int j = 0; j <= 63; ++j)
	{
		SS1 = SL(SL(A, 12) + E + SL(Tj(j), j), 7);
		SS2 = SS1 ^ SL(A, 12);
		TT1 = FFj(j, A, B, C) + D + SS2 + W1[j];
		TT2 = GGj(j, E, F, G) + H + SS1 + W[j];
		D = C;
		C = SL(B, 9);
		B = A;
		A = TT1;
		H = G;
		G = SL(F, 19);
		F = E;
		E = P0(TT2);
	}

	R[0] = A, R[1] = B, R[2] = C, R[3] = D, R[4] = E, R[5] = F, R[6] = G, R[7] = H;
	for (int i = 0; i < 8; ++i)
	{
		Vi1[i * 4] = (R[i] >> 24) & 0xFF;
		Vi1[i * 4 + 1] = (R[i] >> 16) & 0xFF;
		Vi1[i * 4 + 2] = (R[i] >> 8) & 0xFF;
		Vi1[i * 4 + 3] = (R[i]) & 0xFF;
	}
	for (int i = 0; i < 256 / 8; ++i)
	{
		Vi1[i] ^= Vi[i];
	}
}

void SM3Hash(unsigned char* m, int ml, unsigned char r[32])
{
	int l = ml * 8;
	int k = 448 - 1 - l % 512;
	if (k <= 0)
	{
		k += 512;
	}

	int n = (l + k + 65) / 512;

	int m1l = n * 512 / 8;
	unsigned char* m1 = new unsigned char[m1l];
	memset(m1, 0, m1l);
	memcpy(m1, m, l / 8);

	m1[l / 8] = 0x80;

	unsigned long l1 = l;
	for (int i = 0; i < 64 / 8 && l1 > 0; ++i)
	{
		m1[m1l - 1 - i] = l1 & 0xFF;
		l1 = l1 >> 8;
	}

	unsigned char** B = new unsigned char*[n];
	for (int i = 0; i < n; ++i)
	{
		B[i] = new unsigned char[512 / 8];
		memcpy(B[i], m1 + (512 / 8)*i, 512 / 8);
	}

	delete[] m1;

	unsigned char** V = new unsigned char*[n + 1];
	for (int i = 0; i <= n; ++i)
	{
		V[i] = new unsigned char[256 / 8];
		memset(V[i], 0, 256 / 8);
	}

	memcpy(V[0], IV, 256 / 8);

	for (int i = 0; i < n; ++i)
	{
		CF(V[i], B[i], V[i + 1]);
	}

	for (int i = 0; i < n; ++i)
	{
		delete[] B[i];
	}
	delete[] B;

	memcpy(r, V[n], 32);

	for (int i = 0; i <= n; ++i)
	{
		delete[] V[i];
	}
	delete[] V;
}

void dumpbuf(unsigned char* buf, int len) 
{
	for (int i = 0; i < len; ++i) {
		printf("%02x", buf[i]);
		if ((i + 1) % 16 == 0) 
		printf("\n");
		else
			printf(" ");
	}
	printf("\n");
}

int main() 
{
	unsigned char message[] = "abc";
	int message_len = strlen((char*)message);

	unsigned char hash_result[32] = { 0 };

	SM3Hash(message, message_len, hash_result);

	printf("SM3 Hash:\n");
	dumpbuf(hash_result, 32);

	return 0;
}

手工实现三段式SM3算法
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ vim sm3.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ vim sm3.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ g++ -o test sm3.cpp  test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ ./test
Message: 20221408
Hash:   9e872ba4 b3dbecea e133ff79 b5f5d8c1 a94c690d b8795d07 9ae27a1f 0d5c0e0a
Message: 20221408liudi
Hash:   d8471d36 d9378cc0 aa9b8e06 6525d404 2b1030fd b5f36cf8 1c72dea1 02077672
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/2$ git commit -m "2"
[master 07af214] 2
 4 files changed, 457 insertions(+)
 create mode 100644 shiyan2/2-2/sm3/2/sm3.cpp
 create mode 100644 shiyan2/2-2/sm3/2/sm3.h
 create mode 100755 shiyan2/2-2/sm3/2/test
 create mode 100644 shiyan2/2-2/sm3/2/test.cpp
  • sm3.cpp
#include "sm3.h"
#include <string.h>
#include <stdio.h>

/*
 * 32-bit integer manipulation macros (big endian)
 */
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i)                             \
    {                                                       \
        (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
            | ( (unsigned long) (b)[(i) + 1] << 16 )        \
            | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
            | ( (unsigned long) (b)[(i) + 3]       );       \
    }
#endif

#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i)                             \
    {                                                       \
        (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
        (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
        (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
        (b)[(i) + 3] = (unsigned char) ( (n)       );       \
    }
#endif

 /*
  * SM3 context setup
  */
void sm3_starts(sm3_context *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;

}

static void sm3_process(sm3_context *ctx, unsigned char 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 Temp1, Temp2, Temp3, Temp4, Temp5;
	int j;
#ifdef _DEBUG
	int i;
#endif


	for (j = 0; j < 16; j++)
		T[j] = 0x79CC4519;
	for (j = 16; j < 64; j++)
		T[j] = 0x7A879D8A;

	GET_ULONG_BE(W[0], data, 0);
	GET_ULONG_BE(W[1], data, 4);
	GET_ULONG_BE(W[2], data, 8);
	GET_ULONG_BE(W[3], data, 12);
	GET_ULONG_BE(W[4], data, 16);
	GET_ULONG_BE(W[5], data, 20);
	GET_ULONG_BE(W[6], data, 24);
	GET_ULONG_BE(W[7], data, 28);
	GET_ULONG_BE(W[8], data, 32);
	GET_ULONG_BE(W[9], data, 36);
	GET_ULONG_BE(W[10], data, 40);
	GET_ULONG_BE(W[11], data, 44);
	GET_ULONG_BE(W[12], data, 48);
	GET_ULONG_BE(W[13], data, 52);
	GET_ULONG_BE(W[14], data, 56);
	GET_ULONG_BE(W[15], data, 60);

#ifdef _DEBUG
	printf("Message with padding:\n");
	for (i = 0; i < 8; i++)
		printf("%08x ", W[i]);
	printf("\n");
	for (i = 8; i < 16; i++)
		printf("%08x ", W[i]);
	printf("\n");
#endif

#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))

	for (j = 16; j < 68; j++)
	{

		Temp1 = W[j - 16] ^ W[j - 9];
		Temp2 = ROTL(W[j - 3], 15);
		Temp3 = Temp1 ^ Temp2;
		Temp4 = P1(Temp3);
		Temp5 = ROTL(W[j - 13], 7) ^ W[j - 6];
		W[j] = Temp4 ^ Temp5;
	}

#ifdef _DEBUG
	printf("Expanding message W0-67:\n");
	for (i = 0; i < 68; i++)
	{
		printf("%08x ", W[i]);
		if (((i + 1) % 8) == 0) printf("\n");
	}
	printf("\n");
#endif

	for (j = 0; j < 64; j++)
	{
		W1[j] = W[j] ^ W[j + 4];
	}

#ifdef _DEBUG
	printf("Expanding message W'0-63:\n");
	for (i = 0; i < 64; i++)
	{
		printf("%08x ", W1[i]);
		if (((i + 1) % 8) == 0) printf("\n");
	}
	printf("\n");
#endif

	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];
#ifdef _DEBUG
	printf("j     A       B        C         D         E        F        G       H\n");
	printf("   %08x %08x %08x %08x %08x %08x %08x %08x\n", A, B, C, D, E, F, G, H);
#endif

	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);
#ifdef _DEBUG
		printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n", j, A, B, C, D, E, F, G, H);
#endif
	}

	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);
#ifdef _DEBUG
		printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n", j, A, B, C, D, E, F, G, H);
#endif
	}

	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;
#ifdef _DEBUG
	printf("   %08x %08x %08x %08x %08x %08x %08x %08x\n", ctx->state[0], ctx->state[1], ctx->state[2],
		ctx->state[3], ctx->state[4], ctx->state[5], ctx->state[6], ctx->state[7]);
#endif
}

/*
 * SM3 process buffer
 */
void sm3_update(sm3_context *ctx, unsigned char *input, int ilen)
{
	int fill;
	unsigned long left;

	if (ilen <= 0)
		return;

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

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

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

	if (left && ilen >= fill)
	{
		memcpy((void *)(ctx->buffer + left),
			(void *)input, fill);
		sm3_process(ctx, ctx->buffer);
		input += fill;
		ilen -= fill;
		left = 0;
	}

	while (ilen >= 64)
	{
		sm3_process(ctx, input);
		input += 64;
		ilen -= 64;
	}

	if (ilen > 0)
	{
		memcpy((void *)(ctx->buffer + left),
			(void *)input, ilen);
	}
}

static const unsigned char sm3_padding[64] =
{
 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

/*
 * SM3 final digest
 */
void sm3_finish(sm3_context *ctx, unsigned char output[32])
{
	unsigned long last, padn;
	unsigned long high, low;
	unsigned char msglen[8];

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

	PUT_ULONG_BE(high, msglen, 0);
	PUT_ULONG_BE(low, msglen, 4);

	last = ctx->total[0] & 0x3F;
	padn = (last < 56) ? (56 - last) : (120 - last);

	sm3_update(ctx, (unsigned char *)sm3_padding, padn);
	sm3_update(ctx, msglen, 8);

	PUT_ULONG_BE(ctx->state[0], output, 0);
	PUT_ULONG_BE(ctx->state[1], output, 4);
	PUT_ULONG_BE(ctx->state[2], output, 8);
	PUT_ULONG_BE(ctx->state[3], output, 12);
	PUT_ULONG_BE(ctx->state[4], output, 16);
	PUT_ULONG_BE(ctx->state[5], output, 20);
	PUT_ULONG_BE(ctx->state[6], output, 24);
	PUT_ULONG_BE(ctx->state[7], output, 28);
}

/*
 * output = SM3( input buffer )
 */
void sm3(unsigned char *input, int ilen,
	unsigned char output[32])
{
	sm3_context ctx;

	sm3_starts(&ctx);
	sm3_update(&ctx, input, ilen);
	sm3_finish(&ctx, output);

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

/*
 * output = SM3( file contents )
 */
int sm3_file(char *path, unsigned char output[32])
{
	FILE *f;
	size_t n;
	sm3_context ctx;
	unsigned char buf[1024];

	if ((f = fopen(path, "rb")) == NULL)
		return(1);

	sm3_starts(&ctx);

	while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
		sm3_update(&ctx, buf, (int)n);

	sm3_finish(&ctx, output);

	memset(&ctx, 0, sizeof(sm3_context));

	if (ferror(f) != 0)
	{
		fclose(f);
		return(2);
	}

	fclose(f);
	return(0);
}
 


  • sm3.h
#pragma once

typedef struct
{
	unsigned long total[2];     /*!< number of bytes processed  */
	unsigned long state[8];     /*!< intermediate digest state  */
	unsigned char buffer[64];   /*!< data block being processed */

	unsigned char ipad[64];     /*!< HMAC: inner padding        */
	unsigned char opad[64];     /*!< HMAC: outer padding        */

}
sm3_context;

#ifdef __cplusplus
extern "C" {
#endif

	/**
	 * \brief          SM3 context setup
	 *
	 * \param ctx      context to be initialized
	 */
	void sm3_starts(sm3_context *ctx);

	/**
	 * \brief          SM3 process buffer
	 *
	 * \param ctx      SM3 context
	 * \param input    buffer holding the  data
	 * \param ilen     length of the input data
	 */
	void sm3_update(sm3_context *ctx, unsigned char *input, int ilen);

	/**
	 * \brief          SM3 final digest
	 *
	 * \param ctx      SM3 context
	 */
	void sm3_finish(sm3_context *ctx, unsigned char output[32]);

	/**
	 * \brief          Output = SM3( input buffer )
	 *
	 * \param input    buffer holding the  data
	 * \param ilen     length of the input data
	 * \param output   SM3 checksum result
	 */
	void sm3(unsigned char *input, int ilen,
		unsigned char output[32]);


	/**
	 * \brief          Output = SM3( file contents )
	 *
	 * \param path     input file name
	 * \param output   SM3 checksum result
	 *
	 * \return         0 if successful, 1 if fopen failed,
	 *                 or 2 if fread failed
	 */
	int sm3_file(char *path, unsigned char output[32]);
#ifdef __cplusplus
}
#endif
  • test.cpp
#include <string.h>
#include <stdio.h>
#include "sm3.h"

int main(int argc, char *argv[])
{
    unsigned char *input1 = (unsigned char*)"20221408";
    int ilen1 = 8;
    unsigned char output[32];
    int i;
    sm3_context ctx;

    printf("Message: ");
    printf("%s\n", input1);

    sm3(input1, ilen1, output);
    printf("Hash:   ");
    for (i = 0; i < 32; i++)
    {
        printf("%02x", output[i]);
        if (((i + 1) % 4) == 0) printf(" ");
    }
    printf("\n");

    unsigned char *input2 = (unsigned char*)"20221408liudi";
    int ilen2 = 16;

    printf("Message: ");
    printf("%s\n", input2);

    sm3_starts(&ctx);
    sm3_update(&ctx, input2, ilen2);
    sm3_finish(&ctx, output);
    memset(&ctx, 0, sizeof(sm3_context));

    printf("Hash:   ");
    for (i = 0; i < 32; i++)
    {
        printf("%02x", output[i]);
        if (((i + 1) % 4) == 0) printf(" ");
    }
    printf("\n");

    return 0;
}
基于openssl实现sm3
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ vim sm3.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ vim sm3.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ g++ -o test test.cpp sm3.cpp -lssl -lcrypto
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ ./test
raw data: 20221408
hash length: 32 bytes.
hash value:
0xa7  0xa5  0x80  0x40  0xb2  0x45  0x86  0x63  0xf2  0x27  0x63  0x52  0x67  0xe3  0xd3  0x19  0xd7  0x2d  0x8a  0xa5  0x6b  0xea  0xed  0xb4  0x0f  0x8b  0x74  0x31  0x0d  0xda  0x5b  0x0e

raw data:
0x32  0x30  0x32  0x32  0x31  0x34  0x30  0x38  0x6c  0x69  0x75  0x64
hash length: 32 bytes.
hash value:
0x0c  0x98  0x7d  0x15  0x5e  0x72  0x0f  0xcc  0x7d  0x86  0xc1  0xd4  0x0f  0xbd  0x05  0x90  0xef  0x32  0x2d  0x11  0x9a  0x9d  0xea  0x5e  0x18  0x7b  0x0b  0xbb  0x8a  0xaf  0xb5  0xd4
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/3$ git commit -m "3"
[master 3e92425] 3
 4 files changed, 72 insertions(+)
 create mode 100644 shiyan2/2-2/sm3/3/sm3.cpp
 create mode 100644 shiyan2/2-2/sm3/3/sm3.h
 create mode 100755 shiyan2/2-2/sm3/3/test
 create mode 100644 shiyan2/2-2/sm3/3/test.cpp
  • sm3.cpp
#include "openssl/evp.h"
#include "sm3.h"

int sm3_hash(const unsigned char *message, size_t len, unsigned char *hash, unsigned int *hash_len)
{
	EVP_MD_CTX *md_ctx;
	const EVP_MD *md;

	md = EVP_sm3();
	md_ctx = EVP_MD_CTX_new();
	EVP_DigestInit_ex(md_ctx, md, NULL);
	EVP_DigestUpdate(md_ctx, message, len);
	EVP_DigestFinal_ex(md_ctx, hash, hash_len);
	EVP_MD_CTX_free(md_ctx);
	return 0;
}

  • sm3.h
#ifndef HEADER_C_FILE_SM3_HASH_H
#define HEADER_C_FILE_SM3_HASH_H

#ifdef  __cplusplus
extern "C" {
#endif

	int sm3_hash(const unsigned char *message, size_t len, unsigned char *hash, unsigned int *hash_len);

#ifdef  __cplusplus
}
#endif

#endif
  • test.cpp
#include <stdio.h>
#include <string.h>
#include "sm3.h"

int main(void)
{
	const unsigned char sample1[] = { 'a', 'b', 'c', 0 };
	unsigned int sample1_len = strlen((char *)sample1);
	const unsigned char sample2[] = { 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
										 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64 };
	unsigned int sample2_len = sizeof(sample2);
	unsigned char hash_value[64];
	unsigned int i, hash_len;

	sm3_hash(sample1, sample1_len, hash_value, &hash_len);
	printf("raw data: %s\n", sample1);
	printf("hash length: %d bytes.\n", hash_len);
	printf("hash value:\n");
	for (i = 0; i < hash_len; i++)
	{
		printf("0x%x  ", hash_value[i]);
	}
	printf("\n\n");

	sm3_hash(sample2, sample2_len, hash_value, &hash_len);
	printf("raw data:\n");
	for (i = 0; i < sample2_len; i++)
	{
		printf("0x%x  ", sample2[i]);
	}
	printf("\n");
	printf("hash length: %d bytes.\n", hash_len);
	printf("hash value:\n");
	for (i = 0; i < hash_len; i++)
	{
		printf("0x%x  ", hash_value[i]);
	}
	printf("\n");

	return 0;
}
 
HMAC-SM3算法
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ vim sm3.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ vim sm3.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ g++ -o test test.cpp sm3.cpp -m32
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ ./test
Message: liudi
HMAC:   ae22ae5b 810d5d7a 5b8b3202 3583c25b d0b23784 46c42329 a61d6c37 97531016
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/4$ git commit -m "4"
[master f67c783] 4
 4 files changed, 550 insertions(+)
 create mode 100644 shiyan2/2-2/sm3/4/sm3.cpp
 create mode 100644 shiyan2/2-2/sm3/4/sm3.h
 create mode 100755 shiyan2/2-2/sm3/4/test
 create mode 100644 shiyan2/2-2/sm3/4/test.cpp
  • sm3.cpp
#include "sm3.h"
#include <string.h>
#include <stdio.h>

/*
 * 32-bit integer manipulation macros (big endian)
 */
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i)                             \
    {                                                       \
        (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
            | ( (unsigned long) (b)[(i) + 1] << 16 )        \
            | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
            | ( (unsigned long) (b)[(i) + 3]       );       \
    }
#endif

#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i)                             \
    {                                                       \
        (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
        (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
        (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
        (b)[(i) + 3] = (unsigned char) ( (n)       );       \
    }
#endif

 /*
  * SM3 context setup
  */
void sm3_starts(sm3_context *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;

}

static void sm3_process(sm3_context *ctx, unsigned char 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 Temp1, Temp2, Temp3, Temp4, Temp5;
	int j;
#ifdef _DEBUG
	int i;
#endif

	for (j = 0; j < 16; j++)
		T[j] = 0x79CC4519;
	for (j = 16; j < 64; j++)
		T[j] = 0x7A879D8A;

	GET_ULONG_BE(W[0], data, 0);
	GET_ULONG_BE(W[1], data, 4);
	GET_ULONG_BE(W[2], data, 8);
	GET_ULONG_BE(W[3], data, 12);
	GET_ULONG_BE(W[4], data, 16);
	GET_ULONG_BE(W[5], data, 20);
	GET_ULONG_BE(W[6], data, 24);
	GET_ULONG_BE(W[7], data, 28);
	GET_ULONG_BE(W[8], data, 32);
	GET_ULONG_BE(W[9], data, 36);
	GET_ULONG_BE(W[10], data, 40);
	GET_ULONG_BE(W[11], data, 44);
	GET_ULONG_BE(W[12], data, 48);
	GET_ULONG_BE(W[13], data, 52);
	GET_ULONG_BE(W[14], data, 56);
	GET_ULONG_BE(W[15], data, 60);

#ifdef _DEBUG
	printf("Message with padding:\n");
	for (i = 0; i < 8; i++)
		printf("%08x ", W[i]);
	printf("\n");
	for (i = 8; i < 16; i++)
		printf("%08x ", W[i]);
	printf("\n");
#endif

#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))

	for (j = 16; j < 68; j++)
	{

		Temp1 = W[j - 16] ^ W[j - 9];
		Temp2 = ROTL(W[j - 3], 15);
		Temp3 = Temp1 ^ Temp2;
		Temp4 = P1(Temp3);
		Temp5 = ROTL(W[j - 13], 7) ^ W[j - 6];
		W[j] = Temp4 ^ Temp5;
	}

#ifdef _DEBUG
	printf("Expanding message W0-67:\n");
	for (i = 0; i < 68; i++)
	{
		printf("%08x ", W[i]);
		if (((i + 1) % 8) == 0) printf("\n");
	}
	printf("\n");
#endif

	for (j = 0; j < 64; j++)
	{
		W1[j] = W[j] ^ W[j + 4];
	}

#ifdef _DEBUG
	printf("Expanding message W'0-63:\n");
	for (i = 0; i < 64; i++)
	{
		printf("%08x ", W1[i]);
		if (((i + 1) % 8) == 0) printf("\n");
	}
	printf("\n");
#endif

	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];
#ifdef _DEBUG
	printf("j     A       B        C         D         E        F        G       H\n");
	printf("   %08x %08x %08x %08x %08x %08x %08x %08x\n", A, B, C, D, E, F, G, H);
#endif

	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);
#ifdef _DEBUG
		printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n", j, A, B, C, D, E, F, G, H);
#endif
	}

	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);
#ifdef _DEBUG
		printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n", j, A, B, C, D, E, F, G, H);
#endif
	}

	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;
#ifdef _DEBUG
	printf("   %08x %08x %08x %08x %08x %08x %08x %08x\n", ctx->state[0], ctx->state[1], ctx->state[2],
		ctx->state[3], ctx->state[4], ctx->state[5], ctx->state[6], ctx->state[7]);
#endif
}

/*
 * SM3 process buffer
 */
void sm3_update(sm3_context *ctx, unsigned char *input, int ilen)
{
	int fill;
	unsigned long left;

	if (ilen <= 0)
		return;

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

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

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

	if (left && ilen >= fill)
	{
		memcpy((void *)(ctx->buffer + left),
			(void *)input, fill);
		sm3_process(ctx, ctx->buffer);
		input += fill;
		ilen -= fill;
		left = 0;
	}

	while (ilen >= 64)
	{
		sm3_process(ctx, input);
		input += 64;
		ilen -= 64;
	}

	if (ilen > 0)
	{
		memcpy((void *)(ctx->buffer + left),
			(void *)input, ilen);
	}
}

static const unsigned char sm3_padding[64] =
{
 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

/*
 * SM3 final digest
 */
void sm3_finish(sm3_context *ctx, unsigned char output[32])
{
	unsigned long last, padn;
	unsigned long high, low;
	unsigned char msglen[8];

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

	PUT_ULONG_BE(high, msglen, 0);
	PUT_ULONG_BE(low, msglen, 4);

	last = ctx->total[0] & 0x3F;
	padn = (last < 56) ? (56 - last) : (120 - last);

	sm3_update(ctx, (unsigned char *)sm3_padding, padn);
	sm3_update(ctx, msglen, 8);

	PUT_ULONG_BE(ctx->state[0], output, 0);
	PUT_ULONG_BE(ctx->state[1], output, 4);
	PUT_ULONG_BE(ctx->state[2], output, 8);
	PUT_ULONG_BE(ctx->state[3], output, 12);
	PUT_ULONG_BE(ctx->state[4], output, 16);
	PUT_ULONG_BE(ctx->state[5], output, 20);
	PUT_ULONG_BE(ctx->state[6], output, 24);
	PUT_ULONG_BE(ctx->state[7], output, 28);
}

/*
 * output = SM3( input buffer )
 */
void sm3(unsigned char *input, int ilen,
	unsigned char output[32])
{
	sm3_context ctx;

	sm3_starts(&ctx);
	sm3_update(&ctx, input, ilen);
	sm3_finish(&ctx, output);

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

/*
 * output = SM3( file contents )
 */
int sm3_file(char *path, unsigned char output[32])
{
	FILE *f;
	size_t n;
	sm3_context ctx;
	unsigned char buf[1024];

	if ((f = fopen(path, "rb")) == NULL)
		return(1);

	sm3_starts(&ctx);

	while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
		sm3_update(&ctx, buf, (int)n);

	sm3_finish(&ctx, output);

	memset(&ctx, 0, sizeof(sm3_context));

	if (ferror(f) != 0)
	{
		fclose(f);
		return(2);
	}

	fclose(f);
	return(0);
}
 



/*
 * SM3 HMAC context setup
 */
void sm3_hmac_starts(sm3_context *ctx, unsigned char *key, int keylen)
{
	int i;
	unsigned char sum[32];

	if (keylen > 64)
	{
		sm3(key, keylen, sum);
		keylen = 32;
		key = sum;
	}

	memset(ctx->ipad, 0x36, 64);
	memset(ctx->opad, 0x5C, 64);

	for (i = 0; i < keylen; i++)
	{
		ctx->ipad[i] = (unsigned char)(ctx->ipad[i] ^ key[i]);
		ctx->opad[i] = (unsigned char)(ctx->opad[i] ^ key[i]);
	}

	sm3_starts(ctx);
	sm3_update(ctx, ctx->ipad, 64);

	memset(sum, 0, sizeof(sum));
}

/*
 * SM3 HMAC process buffer
 */
void sm3_hmac_update(sm3_context *ctx, unsigned char *input, int ilen)
{
	sm3_update(ctx, input, ilen);
}

/*
 * SM3 HMAC final digest
 */
void sm3_hmac_finish(sm3_context *ctx, unsigned char output[32])
{
	int hlen;
	unsigned char tmpbuf[32];

	hlen = 32;

	sm3_finish(ctx, tmpbuf);
	sm3_starts(ctx);
	sm3_update(ctx, ctx->opad, 64);
	sm3_update(ctx, tmpbuf, hlen);
	sm3_finish(ctx, output);

	memset(tmpbuf, 0, sizeof(tmpbuf));
}

/*
 * output = HMAC-SM#( hmac key, input buffer )
 */
void sm3_hmac(unsigned char *key, int keylen,
	unsigned char *input, int ilen,
	unsigned char output[32])
{
	sm3_context ctx;

	sm3_hmac_starts(&ctx, key, keylen);
	sm3_hmac_update(&ctx, input, ilen);
	sm3_hmac_finish(&ctx, output);

	memset(&ctx, 0, sizeof(sm3_context));
}
  • sm3.h
#pragma once

typedef struct
{
	unsigned long total[2];     /*!< number of bytes processed  */
	unsigned long state[8];     /*!< intermediate digest state  */
	unsigned char buffer[64];   /*!< data block being processed */

	unsigned char ipad[64];     /*!< HMAC: inner padding        */
	unsigned char opad[64];     /*!< HMAC: outer padding        */

}
sm3_context;

#ifdef __cplusplus
extern "C" {
#endif

	/**
	 * \brief          SM3 context setup
	 *
	 * \param ctx      context to be initialized
	 */
	void sm3_starts(sm3_context *ctx);

	/**
	 * \brief          SM3 process buffer
	 *
	 * \param ctx      SM3 context
	 * \param input    buffer holding the  data
	 * \param ilen     length of the input data
	 */
	void sm3_update(sm3_context *ctx, unsigned char *input, int ilen);

	/**
	 * \brief          SM3 final digest
	 *
	 * \param ctx      SM3 context
	 */
	void sm3_finish(sm3_context *ctx, unsigned char output[32]);

	/**
	 * \brief          Output = SM3( input buffer )
	 *
	 * \param input    buffer holding the  data
	 * \param ilen     length of the input data
	 * \param output   SM3 checksum result
	 */
	void sm3(unsigned char *input, int ilen,
		unsigned char output[32]);


	/**
	 * \brief          Output = SM3( file contents )
	 *
	 * \param path     input file name
	 * \param output   SM3 checksum result
	 *
	 * \return         0 if successful, 1 if fopen failed,
	 *                 or 2 if fread failed
	 */
	int sm3_file(char *path, unsigned char output[32]);
	 

	/**
	 * \brief          SM3 HMAC context setup
	 *
	 * \param ctx      HMAC context to be initialized
	 * \param key      HMAC secret key
	 * \param keylen   length of the HMAC key
	 */
	void sm3_hmac_starts(sm3_context *ctx, unsigned char *key, int keylen);

	/**
	 * \brief          SM3 HMAC process buffer
	 *
	 * \param ctx      HMAC context
	 * \param input    buffer holding the  data
	 * \param ilen     length of the input data
	 */
	void sm3_hmac_update(sm3_context *ctx, unsigned char *input, int ilen);

	/**
	 * \brief          SM3 HMAC final digest
	 *
	 * \param ctx      HMAC context
	 * \param output   SM3 HMAC checksum result
	 */
	void sm3_hmac_finish(sm3_context *ctx, unsigned char output[32]);

	/**
	 * \brief          Output = HMAC-SM3( hmac key, input buffer )
	 *
	 * \param key      HMAC secret key
	 * \param keylen   length of the HMAC key
	 * \param input    buffer holding the  data
	 * \param ilen     length of the input data
	 * \param output   HMAC-SM3 result
	 */
	void sm3_hmac(unsigned char *key, int keylen,
		unsigned char *input, int ilen,
		unsigned char output[32]);


#ifdef __cplusplus
}
#endif
  • test.cpp
#include <string.h>
#include <stdio.h>
#include "sm3.h"

int main(int argc, char *argv[])
{
    unsigned char *input = (unsigned char*)"liudi";
    unsigned char *key = (unsigned char*)"1408";
    int ilen = 5;
    unsigned char output[32];
    int i;
    sm3_context ctx;

    printf("Message: ");
    printf("%s\n", input);

    sm3_hmac(key, 4, input, ilen, output);
    printf("HMAC:   ");
    for (i = 0; i < 32; i++)
    {
        printf("%02x", output[i]);
        if (((i + 1) % 4) == 0) printf(" ");
    }
    printf("\n");

    return 0;
}

sm4

16字节
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim sm4.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim sm4.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ g++ -o test test.cpp sm4.cpp -m32
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ ./test
sm4(16字节)自检成功

ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ git commit -m "16byte"
[master 701dea9] 16byte
 4 files changed, 156 insertions(+)
 create mode 100644 shiyan2/2-2/sm4/sm4.cpp
 create mode 100644 shiyan2/2-2/sm4/sm4.h
 create mode 100755 shiyan2/2-2/sm4/test
 create mode 100644 shiyan2/2-2/sm4/test.cpp
  • sm4.cpp
#include "sm4.h"
#include <stdio.h>

#define SM4_Rotl32(buf, n) (((buf)<<n)|((buf)>>(32-n)))



unsigned int SM4_CK[32] = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };


unsigned int SM4_FK[4] = { 0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC };

unsigned char SM4_Sbox[256] =
{ 0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 };



void SM4_KeySchedule(unsigned char MK[], unsigned int rk[])
{
	unsigned int tmp, buf, K[36];
	int i;
	for (i = 0; i < 4; i++)
	{
		K[i] = SM4_FK[i] ^ ((MK[4 * i] << 24) | (MK[4 * i + 1] << 16)
			| (MK[4 * i + 2] << 8) | (MK[4 * i + 3]));
	}
	for (i = 0; i < 32; i++)
	{
		tmp = K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ SM4_CK[i];
		buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
			| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
			| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
			| (SM4_Sbox[tmp & 0xFF]);
		K[i + 4] = K[i] ^ ((buf) ^ (SM4_Rotl32((buf), 13)) ^ (SM4_Rotl32((buf), 23)));
		rk[i] = K[i + 4];
	}
}


void SM4_Encrypt(unsigned char MK[], unsigned char PlainText[], unsigned char CipherText[])
{
	unsigned int rk[32], X[36], tmp, buf;
	int i, j;
	SM4_KeySchedule(MK, rk);
	for (j = 0; j < 4; j++)
	{
		X[j] = (PlainText[j * 4] << 24) | (PlainText[j * 4 + 1] << 16)
			| (PlainText[j * 4 + 2] << 8) | (PlainText[j * 4 + 3]);
	}
	for (i = 0; i < 32; i++)
	{
		tmp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[i];
		buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
			| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
			| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
			| (SM4_Sbox[tmp & 0xFF]);
		X[i + 4] = X[i] ^ (buf^SM4_Rotl32((buf), 2) ^ SM4_Rotl32((buf), 10)
			^ SM4_Rotl32((buf), 18) ^ SM4_Rotl32((buf), 24));
	}
	for (j = 0; j < 4; j++)
	{
		CipherText[4 * j] = (X[35 - j] >> 24) & 0xFF;
		CipherText[4 * j + 1] = (X[35 - j] >> 16) & 0xFF;
		CipherText[4 * j + 2] = (X[35 - j] >> 8) & 0xFF;
		CipherText[4 * j + 3] = (X[35 - j]) & 0xFF;
	}
}

void SM4_Decrypt(unsigned char MK[], unsigned char CipherText[], unsigned char PlainText[])
{
	unsigned int rk[32], X[36], tmp, buf;
	int i, j;
	SM4_KeySchedule(MK, rk);
	for (j = 0; j < 4; j++)
	{
		X[j] = (CipherText[j * 4] << 24) | (CipherText[j * 4 + 1] << 16) |
			(CipherText[j * 4 + 2] << 8) | (CipherText[j * 4 + 3]);
	}
	for (i = 0; i < 32; i++)
	{
		tmp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[31 - i];
		buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
			| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
			| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
			| (SM4_Sbox[tmp & 0xFF]);
		X[i + 4] = X[i] ^ (buf^SM4_Rotl32((buf), 2) ^ SM4_Rotl32((buf), 10)
			^ SM4_Rotl32((buf), 18) ^ SM4_Rotl32((buf), 24));
	}
	for (j = 0; j < 4; j++)
	{
		PlainText[4 * j] = (X[35 - j] >> 24) & 0xFF;
		PlainText[4 * j + 1] = (X[35 - j] >> 16) & 0xFF;
		PlainText[4 * j + 2] = (X[35 - j] >> 8) & 0xFF;
		PlainText[4 * j + 3] = (X[35 - j]) & 0xFF;
	}
}

int SM4_SelfCheck()
{
	int i;
	unsigned char key[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char plain[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char cipher[16] = { 0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46 };
	unsigned char En_output[16];
	unsigned char De_output[16];
	SM4_Encrypt(key, plain, En_output);
	SM4_Decrypt(key, cipher, De_output);
	for (i = 0; i < 16; i++)
	{
		if ((En_output[i] != cipher[i]) | (De_output[i] != plain[i]))
		{
			printf("Self-check error");
			return 1;
		}
	}
	printf("sm4(16字节)自检成功\n\n");
	return 0;
}

  • sm4.h
#pragma once

void SM4_KeySchedule(unsigned char MK[], unsigned int rk[]);
void SM4_Encrypt(unsigned char MK[], unsigned char PlainText[], unsigned char CipherText[]);
void SM4_Decrypt(unsigned char MK[], unsigned char CipherText[], unsigned char PlainText[]);
int SM4_SelfCheck();

  • test.cpp
#pragma once

void SM4_KeySchedule(unsigned char MK[], unsigned int rk[]);
void SM4_Encrypt(unsigned char MK[], unsigned char PlainText[], unsigned char CipherText[]);
void SM4_Decrypt(unsigned char MK[], unsigned char CipherText[], unsigned char PlainText[]);
int SM4_SelfCheck();

实现SM4-ECBCBCCFBOFB 算法
  • 命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim sm4_2.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim sm4_2.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim sm4c.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ vim test_2.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ g++ -o test_2 test_2.cpp sm4c.cpp sm4_2.cpp -m32
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ ./test_2
ecb enc(len=16) memcmp ok
ecb dec(len=16) memcmp ok
ecb enc/dec(len=32) memcmp ok
ecb enc/dec(len=64) memcmp ok
ecb enc/dec(len=128) memcmp ok
ecb enc/dec(len=256) memcmp ok
ecb enc/dec(len=512) memcmp ok
ecb enc/dec(len=1024) memcmp ok
ecb enc/dec(len=2048) memcmp ok
ecb enc/dec(len=4096) memcmp ok
cbc enc(len=32) memcmp ok
cbc dec(len=32) memcmp ok
cbc enc/dec(len=32) memcmp ok
cbc enc/dec(len=64) memcmp ok
cbc enc/dec(len=128) memcmp ok
cbc enc/dec(len=256) memcmp ok
cbc enc/dec(len=512) memcmp ok
cbc enc/dec(len=1024) memcmp ok
cbc enc/dec(len=2048) memcmp ok
cbc enc/dec(len=4096) memcmp ok
cfb enc/dec(len=16) memcmp ok
cfb enc/dec(len=32) memcmp ok
cfb enc/dec(len=64) memcmp ok
cfb enc/dec(len=128) memcmp ok
cfb enc/dec(len=256) memcmp ok
cfb enc/dec(len=512) memcmp ok
cfb enc/dec(len=1024) memcmp ok
cfb enc/dec(len=2048) memcmp ok
cfb enc/dec(len=4096) memcmp ok
ofb enc/dec(len=16) memcmp ok
ofb enc/dec(len=32) memcmp ok
ofb enc/dec(len=64) memcmp ok
ofb enc/dec(len=128) memcmp ok
ofb enc/dec(len=256) memcmp ok
ofb enc/dec(len=512) memcmp ok
ofb enc/dec(len=1024) memcmp ok
ofb enc/dec(len=2048) memcmp ok
ofb enc/dec(len=4096) memcmp ok
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ git commit -m "sm4"
[master 21ab0fb] sm4
 5 files changed, 447 insertions(+)
 create mode 100644 shiyan2/2-2/sm4/sm4_2.cpp
 create mode 100644 shiyan2/2-2/sm4/sm4_2.h
 create mode 100644 shiyan2/2-2/sm4/sm4c.cpp
 create mode 100755 shiyan2/2-2/sm4/test_2
 create mode 100644 shiyan2/2-2/sm4/test_2.cpp
  • sm4_2.cpp
#include "sm4_2.h"
#include <stdio.h>
#include <string.h>

#define SM4_Rotl32(buf, n) (((buf)<<n)|((buf)>>(32-n)))



unsigned int SM4_CK[32] = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };


unsigned int SM4_FK[4] = { 0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC };

unsigned char SM4_Sbox[256] =
{ 0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 };



void SM4_KeySchedule(unsigned char MK[], unsigned int rk[])
{
	unsigned int tmp, buf, K[36];
	int i;
	for (i = 0; i < 4; i++)
	{
		K[i] = SM4_FK[i] ^ ((MK[4 * i] << 24) | (MK[4 * i + 1] << 16)
			| (MK[4 * i + 2] << 8) | (MK[4 * i + 3]));
	}
	for (i = 0; i < 32; i++)
	{
		tmp = K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ SM4_CK[i];
		buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
			| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
			| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
			| (SM4_Sbox[tmp & 0xFF]);
		K[i + 4] = K[i] ^ ((buf) ^ (SM4_Rotl32((buf), 13)) ^ (SM4_Rotl32((buf), 23)));
		rk[i] = K[i + 4];
	}
}


void SM4_Encrypt(unsigned char MK[], unsigned char PlainText[], unsigned char CipherText[])
{
	unsigned int rk[32], X[36], tmp, buf;
	int i, j;
	SM4_KeySchedule(MK, rk);
	for (j = 0; j < 4; j++)
	{
		X[j] = (PlainText[j * 4] << 24) | (PlainText[j * 4 + 1] << 16)
			| (PlainText[j * 4 + 2] << 8) | (PlainText[j * 4 + 3]);
	}
	for (i = 0; i < 32; i++)
	{
		tmp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[i];
		buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
			| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
			| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
			| (SM4_Sbox[tmp & 0xFF]);
		X[i + 4] = X[i] ^ (buf^SM4_Rotl32((buf), 2) ^ SM4_Rotl32((buf), 10)
			^ SM4_Rotl32((buf), 18) ^ SM4_Rotl32((buf), 24));
	}
	for (j = 0; j < 4; j++)
	{
		CipherText[4 * j] = (X[35 - j] >> 24) & 0xFF;
		CipherText[4 * j + 1] = (X[35 - j] >> 16) & 0xFF;
		CipherText[4 * j + 2] = (X[35 - j] >> 8) & 0xFF;
		CipherText[4 * j + 3] = (X[35 - j]) & 0xFF;
	}
}

void SM4_Decrypt(unsigned char MK[], unsigned char CipherText[], unsigned char PlainText[])
{
	unsigned int rk[32], X[36], tmp, buf;
	int i, j;
	SM4_KeySchedule(MK, rk);
	for (j = 0; j < 4; j++)
	{
		X[j] = (CipherText[j * 4] << 24) | (CipherText[j * 4 + 1] << 16) |
			(CipherText[j * 4 + 2] << 8) | (CipherText[j * 4 + 3]);
	}
	for (i = 0; i < 32; i++)
	{
		tmp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[31 - i];
		buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24
			| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16
			| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8
			| (SM4_Sbox[tmp & 0xFF]);
		X[i + 4] = X[i] ^ (buf^SM4_Rotl32((buf), 2) ^ SM4_Rotl32((buf), 10)
			^ SM4_Rotl32((buf), 18) ^ SM4_Rotl32((buf), 24));
	}
	for (j = 0; j < 4; j++)
	{
		PlainText[4 * j] = (X[35 - j] >> 24) & 0xFF;
		PlainText[4 * j + 1] = (X[35 - j] >> 16) & 0xFF;
		PlainText[4 * j + 2] = (X[35 - j] >> 8) & 0xFF;
		PlainText[4 * j + 3] = (X[35 - j]) & 0xFF;
	}
}

int SM4_SelfCheck()
{
	int i;
	unsigned char key[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char plain[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char cipher[16] = { 0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46 };
	unsigned char En_output[16];
	unsigned char De_output[16];
	SM4_Encrypt(key, plain, En_output);
	SM4_Decrypt(key, cipher, De_output);
	for (i = 0; i < 16; i++)
	{
		if ((En_output[i] != cipher[i]) | (De_output[i] != plain[i]))
		{
			printf("Self-check error");
			return 1;
		}
	}
	printf("sm4\n\n");
	return 0;
}






void sm4ecb(  unsigned char *in, unsigned char *out,  unsigned int length,  unsigned char *key,  unsigned int enc)
{
	unsigned int len = length;

	if ((in == NULL) || (out == NULL) || (key == NULL)|| (length% SM4_BLOCK_SIZE != 0))
		return;

	if ((SM4_ENCRYPT != enc) && (SM4_DECRYPT != enc))
		return;

	 
	while (len >= SM4_BLOCK_SIZE)
	{
		if (SM4_ENCRYPT == enc)
			SM4_Encrypt(key,in, out);
		else
			SM4_Decrypt(key,in, out);

		len -= SM4_BLOCK_SIZE;
		in += SM4_BLOCK_SIZE;
		out += SM4_BLOCK_SIZE;
	}

}



void sm4cbc(  unsigned char *in, unsigned char *out,unsigned int length,  unsigned char *key,unsigned char *ivec,  unsigned int enc)
{
	unsigned int n;
	unsigned int len = length;
	unsigned char tmp[SM4_BLOCK_SIZE];
	const unsigned char *iv = ivec;
	unsigned char iv_tmp[SM4_BLOCK_SIZE];


	if ((in == NULL) || (out == NULL) || (key == NULL) || (ivec == NULL)||(length% SM4_BLOCK_SIZE != 0)) 
		return;

	if ((SM4_ENCRYPT != enc) && (SM4_DECRYPT != enc))
		return;


	if (SM4_ENCRYPT == enc)
	{
		while (len >= SM4_BLOCK_SIZE)
		{
			for (n = 0; n < SM4_BLOCK_SIZE; ++n)
				out[n] = in[n] ^ iv[n];
			SM4_Encrypt(key,out, out);
			iv = out;
			len -= SM4_BLOCK_SIZE;
			in += SM4_BLOCK_SIZE;
			out += SM4_BLOCK_SIZE;
		}
	}
	else if (in != out)
	{
		while (len >= SM4_BLOCK_SIZE)
		{
			SM4_Decrypt(key,in, out);
			for (n = 0; n < SM4_BLOCK_SIZE; ++n)
				out[n] ^= iv[n];
			iv = in;
			len -= SM4_BLOCK_SIZE;
			in += SM4_BLOCK_SIZE;
			out += SM4_BLOCK_SIZE;
		}
	}
	else
	{
		memcpy(iv_tmp, ivec, SM4_BLOCK_SIZE);
		while (len >= SM4_BLOCK_SIZE)
		{
			memcpy(tmp, in, SM4_BLOCK_SIZE);
			SM4_Decrypt(key,in, out);
			for (n = 0; n < SM4_BLOCK_SIZE; ++n)
				out[n] ^= iv_tmp[n];
			memcpy(iv_tmp, tmp, SM4_BLOCK_SIZE);
			len -= SM4_BLOCK_SIZE;
			in += SM4_BLOCK_SIZE;
			out += SM4_BLOCK_SIZE;
		}
	}
}



void sm4cfb(const unsigned char *in, unsigned char *out,const unsigned int length,   unsigned char *key,
	const unsigned char *ivec, const unsigned int enc)
{
	unsigned int n = 0;
	unsigned int l = length;
	unsigned char c;
	unsigned char iv[SM4_BLOCK_SIZE];

	if ((in == NULL) || (out == NULL) || (key == NULL) || (ivec == NULL))
		return;

	if ((SM4_ENCRYPT != enc) && (SM4_DECRYPT != enc))
		return;

	memcpy(iv, ivec, SM4_BLOCK_SIZE);

	if (enc == SM4_ENCRYPT)
	{
		while (l--)
		{
			if (n == 0)
			{
				SM4_Encrypt(key,iv, iv);
			}
			iv[n] = *(out++) = *(in++) ^ iv[n];
			n = (n + 1) % SM4_BLOCK_SIZE;
		}
	}
	else
	{
		while (l--)
		{
			if (n == 0)
			{
				SM4_Encrypt(key,iv, iv);
			}
			c = *(in);
			*(out++) = *(in++) ^ iv[n];
			iv[n] = c;
			n = (n + 1) % SM4_BLOCK_SIZE;
		}
	}

}


void sm4ofb(const unsigned char *in, unsigned char *out,const unsigned int length,   unsigned char *key,const unsigned char *ivec)
{
	unsigned int n = 0;
	unsigned int l = length;
	unsigned char iv[SM4_BLOCK_SIZE];

	if ((in == NULL) || (out == NULL) || (key == NULL) || (ivec == NULL))
		return;


	memcpy(iv, ivec, SM4_BLOCK_SIZE);

	while (l--)
	{
		if (n == 0)
		{
			SM4_Encrypt(key,iv, iv);
		}
		*(out++) = *(in++) ^ iv[n];
		n = (n + 1) % SM4_BLOCK_SIZE;
	}

}

  • sm4_2.h
#pragma once



#define SM4_ENCRYPT    1
#define SM4_DECRYPT    0
#define SM4_BLOCK_SIZE 16

void SM4_KeySchedule(unsigned char MK[], unsigned int rk[]);
void SM4_Encrypt(unsigned char MK[], unsigned char PlainText[], unsigned char CipherText[]);
void SM4_Decrypt(unsigned char MK[], unsigned char CipherText[], unsigned char PlainText[]);
int SM4_SelfCheck();

void sm4ecb(unsigned char *in, unsigned char *out, unsigned int length, unsigned char *key, unsigned int enc);
void sm4cbc(unsigned char *in, unsigned char *out, unsigned int length, unsigned char *key, unsigned char *ivec, unsigned int enc);
void sm4cfb(const unsigned char *in, unsigned char *out, const unsigned int length, unsigned char *key, const unsigned char *ivec, const unsigned int enc);
void sm4ofb(const unsigned char *in, unsigned char *out, const unsigned int length, unsigned char *key, const unsigned char *ivec);

  • sm4c.cpp
#include "sm4_2.h"
#include <stdio.h>
#include <string.h>


int sm4ecbcheck()
{
	int i,len,ret = 0;
	unsigned char key[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char plain[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char cipher[16] = { 0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46 };
	unsigned char En_output[16];
	unsigned char De_output[16];
	unsigned char in[4096], out[4096], chk[4096];

	sm4ecb(plain, En_output, 16, key, SM4_ENCRYPT);
	if (memcmp(En_output, cipher, 16)) puts("ecb enc(len=16) memcmp failed");
	else puts("ecb enc(len=16) memcmp ok");

	sm4ecb(cipher, De_output, SM4_BLOCK_SIZE, key, SM4_DECRYPT);
	if (memcmp(De_output, plain, SM4_BLOCK_SIZE)) puts("ecb dec(len=16) memcmp failed");
	else puts("ecb dec(len=16) memcmp ok");

	len = 32;
	for (i = 0; i < 8; i++)
	{
		memset(in, i, len);
		sm4ecb(in, out, len, key, SM4_ENCRYPT);
		sm4ecb(out, chk, len, key, SM4_DECRYPT);
		if (memcmp(in, chk, len))  printf("ecb enc/dec(len=%d) memcmp failed\n", len);
		else printf("ecb enc/dec(len=%d) memcmp ok\n", len);
		len = 2 * len;
	}
	return 0;
}


int sm4cbccheck()
{
	int i, len, ret = 0;
	unsigned char key[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char iv[16] = { 0xeb,0xee,0xc5,0x68,0x58,0xe6,0x04,0xd8,0x32,0x7b,0x9b,0x3c,0x10,0xc9,0x0c,0xa7 };
	unsigned char plain[32] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0x29,0xbe,0xe1,0xd6,0x52,0x49,0xf1,0xe9,0xb3,0xdb,0x87,0x3e,0x24,0x0d,0x06,0x47 };
	unsigned char cipher[32] = { 0x3f,0x1e,0x73,0xc3,0xdf,0xd5,0xa1,0x32,0x88,0x2f,0xe6,0x9d,0x99,0x6c,0xde,0x93,0x54,0x99,0x09,0x5d,0xde,0x68,0x99,0x5b,0x4d,0x70,0xf2,0x30,0x9f,0x2e,0xf1,0xb7 };

	unsigned char En_output[32];
	unsigned char De_output[32];
	unsigned char in[4096], out[4096], chk[4096];

	sm4cbc(plain, En_output, sizeof(plain), key,iv, SM4_ENCRYPT);
	if (memcmp(En_output, cipher, 16)) puts("cbc enc(len=32) memcmp failed");
	else puts("cbc enc(len=32) memcmp ok");

	sm4cbc(cipher, De_output, SM4_BLOCK_SIZE, key,iv, SM4_DECRYPT);
	if (memcmp(De_output, plain, SM4_BLOCK_SIZE)) puts("cbc dec(len=32) memcmp failed");
	else puts("cbc dec(len=32) memcmp ok");

 
	len = 32;
	for (i = 0; i < 8; i++)
	{
		memset(in, i, len);
		sm4cbc(in, out, len, key,iv, SM4_ENCRYPT);
		sm4cbc(out, chk, len, key,iv, SM4_DECRYPT);
		if (memcmp(in, chk, len))  printf("cbc enc/dec(len=%d) memcmp failed\n", len);
		else printf("cbc enc/dec(len=%d) memcmp ok\n", len);
		len = 2 * len;
	}
	return 0;
}

int sm4cfbcheck()
{
	int i, len, ret = 0;
	unsigned char key[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char iv[16] = { 0xeb,0xee,0xc5,0x68,0x58,0xe6,0x04,0xd8,0x32,0x7b,0x9b,0x3c,0x10,0xc9,0x0c,0xa7 };
	unsigned char in[4096], out[4096], chk[4096];
	len = 16;
	for (i = 0; i < 9; i++)
	{
		memset(in, i, len);
		sm4cfb(in, out, len, key, iv, SM4_ENCRYPT);
		sm4cfb(out, chk, len, key, iv, SM4_DECRYPT);
		if (memcmp(in, chk, len))  printf("cfb enc/dec(len=%d) memcmp failed\n", len);
		else printf("cfb enc/dec(len=%d) memcmp ok\n", len);
		len = 2 * len;
	}
	return 0;
}

int sm4ofbcheck()
{
	int i, len, ret = 0;
	unsigned char key[16] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
	unsigned char iv[16] = { 0xeb,0xee,0xc5,0x68,0x58,0xe6,0x04,0xd8,0x32,0x7b,0x9b,0x3c,0x10,0xc9,0x0c,0xa7 };
	unsigned char in[4096], out[4096], chk[4096];
	len = 16;
	for (i = 0; i < 9; i++)
	{
		memset(in, i, len);
		sm4ofb(in, out, len, key, iv);
		sm4ofb(out, chk, len, key, iv);
		if (memcmp(in, chk, len))  printf("ofb enc/dec(len=%d) memcmp failed\n", len);
		else printf("ofb enc/dec(len=%d) memcmp ok\n", len);
		len = 2 * len;
	}
	return 0;
}


  • test_2.cpp
extern int sm4ecbcheck();
extern int sm4cbccheck();
extern int sm4cfbcheck();
extern int sm4ofbcheck();

int main()
{
	sm4ecbcheck();
	sm4cbccheck();
	sm4cfbcheck();
	sm4ofbcheck();
}
 

在密标委网站查找SM2,SM3,SM4相关标准,分析代码实现与标准的对应关系。

SM2

标准
  • 密钥交换:SM2标准定义了一套基于椭圆曲线密码学(ECC)的公钥密码系统,用于密钥交换、数字签名和数据加密等安全服务。
  • 数字签名:标准规定了如何使用私钥生成签名,并用对应的公钥验证该签名。
  • 数据加密:标准描述了如何利用公钥对数据进行加密,以及如何使用私钥解密这些数据。
代码实现
  • 密钥操作SM2_ENC_SelfTest 函数中使用了 std_priKeystd_pubKey 进行测试,这与标准中定义的密钥生成和管理相对应。
  • 加密解密:代码实现了 SM2 加密解密的功能,如 SM2_ENCSM2_DEC 函数,这与标准中的数据加密部分直接相关。
  • KDF(密钥派生函数):在加密过程中使用了 SM3_KDF 函数来从椭圆曲线上点的坐标生成密钥材料,这符合标准中对KDF的要求。

SM3

标准
  • 哈希函数:SM3 是一种密码散列函数,能够将任意长度的消息转换为固定长度的输出。标准中详细描述了消息处理、压缩函数和最终输出的计算方法。
代码实现
  • 消息处理sm3_startssm3_updatesm3_finish 函数分别初始化上下文、更新消息块和完成哈希计算,这些步骤与标准中的消息处理流程一致。
  • 压缩函数sm3_hash 函数通过调用 OpenSSL 库中的 EVP_sm3() 函数来实现 SM3 哈希函数的核心逻辑,即压缩函数的计算。
  • 测试test.cpp 中提供了测试用例,包括对不同长度消息的哈希值计算,确保实现与标准规定的输出相匹配。

SM4

标准
  • 分组密码:SM4 是一种分组密码算法,使用128位密钥对128位的数据块进行加密或解密。标准中定义了密钥扩展、轮函数和模式操作等细节。
代码实现
  • 密钥扩展SM4_FK 数组表示了密钥扩展过程中使用的固定常量,这与标准中的密钥调度算法相对应。
  • 轮函数SM4_CK 数组包含了轮函数中使用的常量,反映了标准中定义的非线性变换。
  • 模式操作:代码中实现了多种模式下的加解密操作,如ECB、CBC、CFB和OFB等,这些都遵循了标准中关于操作模式的规定。
  • 测试:通过比较加密解密前后的数据是否一致来验证算法的正确性,这与标准中要求的测试案例和结果验证相吻合。

gitee课程项目链接

链接

git log

ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm4$ git log
commit 21ab0fb804d0ba8c323ac9244c24116c7c0a3874 (HEAD -> master)
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 14:52:45 2024 +0800

    sm4

commit 701dea92f9f4834dbd589af07cbdf7241d5e2d85
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 14:24:31 2024 +0800

    16byte

commit f67c78330393f05c18cc4a2427cea698089ac0d6
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 14:05:48 2024 +0800

    4

commit 3e92425ae9975e8bc393f6c61de22320fbd8859d
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 13:35:21 2024 +0800

    3

commit 07af2147845b7be5347628c5cefbbe2e89b1cf06
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 13:10:44 2024 +0800

    2

commit a84e6ce4e10ac5d56779cc464024695319b3105b
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 12:16:03 2024 +0800

    1

commit 0b23ef7baf390fbdef4bf6742cd280e1eecf9627
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 12:02:55 2024 +0800

    sm2_sv

commit 14da13666c72d31ea78f52c5e3fe329fbc22ee79
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Nov 3 10:59:36 2024 +0800

    sm2_enc

commit aeb6d87c3567720218c054d45949104426ec87b0 (origin/master)
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Oct 27 21:02:42 2024 +0800

    sm4yanzheng

commit 5737c1dc08d6966a4ce6bb553867cb7d84b1a758
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Oct 27 19:09:12 2024 +0800

    sm2

commit 4b45c98e650af1ea181016a3b54cb7fe01da6d1d
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Sun Oct 27 17:09:36 2024 +0800

    sm2

commit 5864f7f82bd611300e7cc8f51e1d7a37b63ac223
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Fri Oct 25 22:46:36 2024 +0800

    mjsm4

commit 1aabf709a07bc4da62ace7c03b91f1a07e81a0dd
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Fri Oct 25 22:39:30 2024 +0800

    mjsm3

commit 12e46aeeac448ad304300cc8b0b8e9e18b45a9f4
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Thu Oct 24 21:45:05 2024 +0800

    test 3

commit 130b382c7bebc17822b9c6d3fd5f58a8fd5a3f30
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Thu Oct 24 17:16:45 2024 +0800

    test2

commit a953291c72825e03e27790e032b9b69fb59604cb
Author: 柳笛 <11537298+liudi20221408@user.noreply.gitee.com>
Date:   Thu Oct 24 16:58:36 2024 +0800

    test1

commit 3e1d254b3a3eb6c69e6b0d55535e6fe11ec82a24
Author: userName <userEmail>
Date:   Tue Oct 8 14:41:01 2024 +0800

    Add hello world program
(END)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值