20221403郑骁恒实验2-2

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

sm2

sm2加解密(14-2代码编译运行结果)

源代码

  • 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;//reg init,set ABCDEFGH=V0A = 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++){//SS1if (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);//SS2SS2 = SS1 ^ SM3_rotl32(A, 12);//TT1if (j <= 15){FF = SM3_ff0(A, B, C);}else{FF = SM3_ff1(A, B, C);}TT1 = FF + D + SS2 + *W1;W1++;//TT2if (j <= 15){GG = SM3_gg0(E, F, G);}else{GG = SM3_gg1(E, F, G);}TT2 = GG + H + SS1 + *W;W++;//DD = C;//CC = SM3_rotl32(B, 9);//BB = A;//AA = TT1;//HH = G;//GG = SM3_rotl32(F, 19);//FF = E;//EE = SM3_p0(TT2);}//update VV[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];//if CPU uses little-endian, BigEndian function is a necessary callBigEndian(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 tillit reaches 64 bytes, compress the current block, creat a newblock 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);//if CPU uses little-endian, BigEndian function is a necessary call
}
/******************************************************************************
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;elset = bitklen / SM2_NUMBITS;//s4: K=Ha1||Ha2||...for (i = 1; i < t; i++){//s2: Hai=Hv(Z||ct)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]++;}//s3: klen/v�������Ĵ���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 "SM2_ENC.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);
  • SM2_ENC.c
#include "miracl/miracl.h"
#include "miracl/mirdef.h"
#include "SM2_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);//test if y^2=x^3+ax+bepoint_get(point, x, y);power(x, 3, para_p, x_3); //x_3=x^3 mod pmultiply(x, para_a, x); //x=a*xdivide(x, para_p, tmp); //x=a*x mod p , tmp=a*x/padd(x_3, x, x); //x=x^3+axadd(x, para_b, x); //x=x^3+ax+bdivide(x, para_p, tmp); //x=x^3+ax+b mod ppower(y, 2, para_p, y); //y=y^2 mod pif (mr_compare(x, y) != 0)return ERR_NOT_VALID_POINT;elsereturn 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();//test if the pubKey is the point at infinityif (point_at_infinity(pubKey))// if pubKey is point at infinity, return error;return ERR_INFINITY_POINT;//test if x<p and y<p both holdepoint_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;//test if the order of pubKey is equal to necurve_mult(para_n, pubKey, nP); // nP=[n]Pif (!point_at_infinity(nP)) // if np is point NOT at infinity, return error;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);//Initialises GF(p) elliptic curve.//MR_PROJECTIVE specifying projective coordinatesif (!epoint_set(para_Gx, para_Gy, 0, G))//initialise point G{return ERR_ECURVE_INIT;}ecurve_mult(para_n, G, nG);if (!point_at_infinity(nG)) //test if the order of the point is n{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;elsereturn 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();//Step2. calculate C1=[k]G=(rGx,rGy)bytes_to_big(SM2_NUMWORD, randK, rand);ecurve_mult(rand, G, C1); //C1=[k]Gepoint_get(C1, C1x, C1y);big_to_bytes(SM2_NUMWORD, C1x, C, 1);big_to_bytes(SM2_NUMWORD, C1y, C + SM2_NUMWORD, 1);//Step3. test if S=[h]pubKey if the point at infinityecurve_mult(para_h, pubKey, S);if (point_at_infinity(S))// if S is point at infinity, return error;return ERR_INFINITY_POINT;//Step4. calculate [k]PB=(x2,y2)ecurve_mult(rand, pubKey, kP); //kP=[k]Pepoint_get(kP, x2, y2);//Step5. KDF(x2||y2,klen)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;//Step6. C2=M^tfor (i = 0; i < klen; i++){C[SM2_NUMWORD * 3 + i] = M[i] ^ C[SM2_NUMWORD * 3 + i];}//Step7. C3=hash(x2,M,y2)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();//Step1. test if C1 fits the curvebytes_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;//Step2. S=[h]C1 and test if S is the point at infinityecurve_mult(para_h, C1, S);if (point_at_infinity(S))// if S is point at infinity, return error;return ERR_INFINITY_POINT;//Step3. [dB]C1=(x2,y2)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);//Step4. t=KDF(x2||y2,klen)SM3_KDF(x2y2, SM2_NUMWORD * 2, Clen - SM2_NUMWORD * 3, M);if (Test_Null(M, Clen - SM2_NUMWORD * 3) != 0)return ERR_ARRAY_NULL;//Step5. M=C2^tfor (i = 0; i < Clen - SM2_NUMWORD * 3; i++)M[i] = M[i] ^ C[SM2_NUMWORD * 3 + i];//Step6. hash(x2,m,y2)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;elsereturn 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;//standard dataunsigned 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); //ks is the standard private key//initiate SM2 curveSM2_Init();//generate key pairtmp = 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]);}//encrypt data and compare the result with the standard datatmp = 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]);}//decrypt cipher and compare the result with the standard datatmp = 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;
}
  • SM2_ENC.h
// SM2_ENC.h
#pragma once#include "miracl/miracl.h"#define ECC_WORDSIZE 8
#define SM2_NUMBITS 256
#define SM2_NUMWORD (SM2_NUMBITS/ECC_WORDSIZE) //32
#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 0x0000000Aextern 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;
  • test.c
#include "SM2_ENC.h"void main()
{SM2_ENC_SelfTest();
}

过程

在这里插入图片描述
在这里插入图片描述

sm2签名验签(14-3代码编译运行结果)

源代码

  • kdf.c
#include "kdf.h"
#include "SM2_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;//reg init,set ABCDEFGH=V0A = 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++){//SS1if (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);//SS2SS2 = SS1 ^ SM3_rotl32(A, 12);//TT1if (j <= 15){FF = SM3_ff0(A, B, C);}else{FF = SM3_ff1(A, B, C);}TT1 = FF + D + SS2 + *W1;W1++;//TT2if (j <= 15){GG = SM3_gg0(E, F, G);}else{GG = SM3_gg1(E, F, G);}TT2 = GG + H + SS1 + *W;W++;//DD = C;//CC = SM3_rotl32(B, 9);//BB = A;//AA = TT1;//HH = G;//GG = SM3_rotl32(F, 19);//FF = E;//EE = SM3_p0(TT2);}//update VV[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];//if CPU uses little-endian, BigEndian function is a necessary callBigEndian(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 tillit reaches 64 bytes, compress the current block, creat a newblock 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);//if CPU uses little-endian, BigEndian function is a necessary call
}
/******************************************************************************
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;elset = bitklen / SM2_NUMBITS;//s4: K=Ha1||Ha2||...for (i = 1; i < t; i++){//s2: Hai=Hv(Z||ct)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]++;}//s3: klen/v�������Ĵ���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);
  • SM2_sv.c
 
#include "SM2_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))//initialise point G{return ERR_ECURVE_INIT;}ecurve_mult(n, G, nG);if (!point_at_infinity(nG)) //test if the order of the point is n{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);//test if y^2=x^3+ax+bepoint_get(point, x, y);power(x, 3, p, x_3); //x_3=x^3 mod pmultiply(x, a, x); //x=a*xdivide(x, p, tmp); //x=a*x mod p , tmp=a*x/padd(x_3, x, x); //x=x^3+axadd(x, b, x); //x=x^3+ax+bdivide(x, p, tmp); //x=x^3+ax+b mod ppower(y, 2, p, y); //y=y^2 mod pif (mr_compare(x, y) != 0)return ERR_NOT_VALID_POINT;elsereturn 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();//test if the pubKey is the point at infinityif (point_at_infinity(pubKey))// if pubKey is point at infinity, return error;return ERR_INFINITY_POINT;//test if x<p and y<p both holdepoint_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;//test if the order of pubKey is equal to necurve_mult(n, pubKey, nP); // nP=[n]Pif (!point_at_infinity(nP)) // if np is point NOT at infinity, return error;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)
{// bytes_to_big(32,SM2_n,n);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;elsereturn 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;//initiatedA = 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);//cinstr(dA,d);KG = epoint_init();//step1,set M=ZA||MM = (char *)malloc(sizeof(char)*(M_len + 1));memcpy(M, ZA, SM3_len / 8);memcpy(M + SM3_len / 8, message, len);//step2,generate e=H(M)SM3_256(M, M_len, hash);bytes_to_big(SM3_len / 8, hash, e);//step3:generate kbytes_to_big(SM3_len / 8, rand, k);//step4:calculate kGecurve_mult(k, G, KG);//step5:calculate repoint_get(KG, KGx, KGy);add(e, KGx, r);divide(r, n, rem);//judge r=0 or n+k=n?add(r, k, rk);if (Test_Zero(r) | Test_n(rk))return ERR_GENERATE_R;//step6:generate sincr(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);//judge s=0?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))//initialise public key{return ERR_PUBKEY_INIT;}//step1: test if r belong to [1,n-1]if (Test_Range(r))return ERR_OUTRANGE_R;//step2: test if s belong to [1,n-1]if (Test_Range(s))return ERR_OUTRANGE_S;//step3,generate MM = (char *)malloc(sizeof(char)*(M_len + 1));memcpy(M, ZA, SM3_len / 8);memcpy(M + SM3_len / 8, message, len);//step4,generate e=H(M)SM3_256(M, M_len, hash);bytes_to_big(SM3_len / 8, hash, e);//step5:generate tadd(r, s, t);divide(t, n, rem);if (Test_Zero(t))return ERR_GENERATE_T;//step 6: generate(x1,y1)ecurve_mult(s, G, sG);ecurve_mult(t, PA, tPA);ecurve_add(sG, tPA);epoint_get(tPA, x1, y1);//step7:generate RRadd(e, x1, RR);divide(RR, n, rem);free(M);if (mr_compare(RR, r) == 0)return 0;elsereturn 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()
{//the private keyunsigned 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 };//the public key/* 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];// Signatureunsigned char IDA[16] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38 };//ASCII code of userA's identificationint IDA_len = 16;unsigned char ENTLA[2] = { 0x00,0x80 };//the length of userA's identification,presentation in ASCII codeunsigned char *message = "message digest";//the message to be signedint len = strlen(message);//the length of messageunsigned char ZA[SM3_len / 8];//ZA=Hash(ENTLA|| IDA|| a|| b|| Gx || Gy || xA|| yA)unsigned char Msg[210]; //210=IDA_len+2+SM2_NUMWORD*6int temp;miracl *mip = mirsys(10000, 16);mip->IOBASE = 16;temp = SM2_KeyGeneration(dA, xA, yA);if (temp)return temp;// ENTLA|| IDA|| a|| b|| Gx || Gy || xA|| yAmemcpy(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;
}
  • SM2_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) //32
#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 0x0000000Cextern 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();
  • test.c

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

过程

在这里插入图片描述

sm3

一段式SM3算法(4-1)

源代码

  • test.cpp
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#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])
{// Bi 分为W0~W15for (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])
{// Bi 扩展为132个字unsigned long W[68] = { 0 };unsigned long W1[64] = { 0 };EB(Bi, W, W1);// 串联 ABCDEFGH = Viunsigned 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);}// Vi1 = ABCDEFGH 串联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;}// Vi1 = ABCDEFGH ^ Vifor (int i = 0; i < 256 / 8; ++i){Vi1[i] ^= Vi[i];}
}//参数 m 是原始数据,ml 是数据长度,r 是输出参数,存放hash结果
void SM3Hash(unsigned char* m, int ml, unsigned char r[32])
{int l = ml * 8;int k = 448 - 1 - l % 512; // 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数if (k <= 0){k += 512;}int n = (l + k + 65) / 512;int m1l = n * 512 / 8; // 填充后的长度,512位的倍数unsigned char* m1 = new unsigned char[m1l];memset(m1, 0, m1l);memcpy(m1, m, l / 8);m1[l / 8] = 0x80; // 消息后补1// 再添加一个64位比特串,该比特串是长度l的二进制表示unsigned long l1 = l;for (int i = 0; i < 64 / 8 && l1 > 0; ++i){m1[m1l - 1 - i] = l1 & 0xFF;l1 = l1 >> 8;}//将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n−1),其中n=(l+k+65)/512。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);}// 初始化 V0 = VImemcpy(V[0], IV, 256 / 8);// 压缩函数,V 与扩展的Bfor (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;// V[n]是结果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");elseprintf(" ");}printf("\n");
}int main() 
{// 输入数据unsigned char message[] = "abc";int message_len = strlen((char*)message);// 输出缓冲区unsigned char hash_result[32] = { 0 };// 调用 SM3 哈希函数SM3Hash(message, message_len, hash_result);// 输出哈希结果printf("SM3 Hash:\n");dumpbuf(hash_result, 32);return 0;
}

过程

在这里插入图片描述

实现三段式SM3算法(4-2)

源代码

  • sm3.h
#pragma oncetypedef 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
  • 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 _DEBUGint i;
#endif// 	for(j=0; j < 68; j++)// 		W[j] = 0;// 	for(j=0; j < 64; j++)// 		W1[j] = 0;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 _DEBUGprintf("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++){//W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^ ROTL(W[j - 13],7 ) ^ W[j-6];//Why thd release's result is different with the debug's ?//Below is okay. Interesting, Perhaps VC6 has a bug of Optimizaiton.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 _DEBUGprintf("Expanding message W0-67:\n");for (i = 0; i < 68; i++){printf("%08x ", W[i]);if (((i + 1) % 8) == 0) printf("\n");}printf("\n");
#endiffor (j = 0; j < 64; j++){W1[j] = W[j] ^ W[j + 4];}#ifdef _DEBUGprintf("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");
#endifA = 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 _DEBUGprintf("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);
#endiffor (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 _DEBUGprintf("%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 _DEBUGprintf("%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 _DEBUGprintf("   %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);
}
  • test.cpp
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <string.h>
#include <stdio.h>
#include "sm3.h"int main(int argc, char *argv[])
{unsigned char *input = (unsigned char*)"abc";int ilen = 3;unsigned char output[32];int i;sm3_context ctx;printf("Message: ");printf("%s\n", input);sm3(input, ilen, output);printf("Hash:   ");for (i = 0; i < 32; i++){printf("%02x", output[i]);if (((i + 1) % 4) == 0) printf(" ");}printf("\n");printf("Message: ");for (i = 0; i < 16; i++)printf("abcd");printf("\n");sm3_starts(&ctx);for (i = 0; i < 16; i++)sm3_update(&ctx, (unsigned char*)"abcd", 4);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");//getch();	
}

过程

在这里插入图片描述

基于openssl实现sm3(4-3)

源代码

  • sm3hash.h
#ifndef HEADER_C_FILE_SM3_HASH_H
#define HEADER_C_FILE_SM3_HASH_H#ifdef  __cplusplus
extern "C" {
#endifint sm3_hash(const unsigned char *message, size_t len, unsigned char *hash, unsigned int *hash_len);#ifdef  __cplusplus
}
#endif#endif
  • sm3hash.cpp
#include "openssl/evp.h"
#include "sm3hash.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;
}

过程

在这里插入图片描述

实现HMAC-SM3算法(4-4)

源代码

  • sm3.h
#pragma oncetypedef 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
  • 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 _DEBUGint i;
#endif// 	for(j=0; j < 68; j++)// 		W[j] = 0;// 	for(j=0; j < 64; j++)// 		W1[j] = 0;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 _DEBUGprintf("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++){//W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^ ROTL(W[j - 13],7 ) ^ W[j-6];//Why thd release's result is different with the debug's ?//Below is okay. Interesting, Perhaps VC6 has a bug of Optimizaiton.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 _DEBUGprintf("Expanding message W0-67:\n");for (i = 0; i < 68; i++){printf("%08x ", W[i]);if (((i + 1) % 8) == 0) printf("\n");}printf("\n");
#endiffor (j = 0; j < 64; j++){W1[j] = W[j] ^ W[j + 4];}#ifdef _DEBUGprintf("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");
#endifA = 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 _DEBUGprintf("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);
#endiffor (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 _DEBUGprintf("%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 _DEBUGprintf("%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 _DEBUGprintf("   %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;//keylen = ( is224 ) ? 28 : 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];//is224 = ctx->is224;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));
}
  • test.cpp
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <string.h>
#include <stdio.h>
#include "sm3.h"int main(int argc, char *argv[])
{unsigned char *input = (unsigned char*)"abc";unsigned char *key = (unsigned char*)"123456";int ilen = 3;unsigned char output[32];int i;sm3_context ctx;printf("Message: ");printf("%s\n", input);sm3_hmac(key, 6, input, 3, output);printf("HMAC:   ");for (i = 0; i < 32; i++){printf("%02x", output[i]);if (((i + 1) % 4) == 0) printf(" ");}printf("\n");}

过程

在这里插入图片描述

sm4

sm4_16字节版(3-6)

源代码

  • sm4.h
#pragma oncevoid 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.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];//nonlinear operationbuf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8| (SM4_Sbox[tmp & 0xFF]);//linear operationK[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];//nonlinear operationbuf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8| (SM4_Sbox[tmp & 0xFF]);//linear operationX[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];//nonlinear operationbuf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8| (SM4_Sbox[tmp & 0xFF]);//linear operationX[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;//Standard dataunsigned 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;
}
  • test.cpp
#include "sm4.h"int main()
{SM4_SelfCheck();
}

过程

在这里插入图片描述

实现SM4-ECBCBCCFBOFB 算法(大数据版)——(3-7)

源代码

  • sm4.h
#pragma once#define SM4_ENCRYPT    1
#define SM4_DECRYPT    0
#define SM4_BLOCK_SIZE 16void 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);
  • sm4check.cpp
#include "sm4.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;
}
  • sm4.cpp
#include "sm4.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];//nonlinear operationbuf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8| (SM4_Sbox[tmp & 0xFF]);//linear operationK[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];//nonlinear operationbuf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8| (SM4_Sbox[tmp & 0xFF]);//linear operationX[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];//nonlinear operationbuf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24| (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16| (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8| (SM4_Sbox[tmp & 0xFF]);//linear operationX[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;//Standard dataunsigned 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;
}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);elseSM4_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;}}
  • test.cpp
extern int sm4ecbcheck();
extern int sm4cbccheck();
extern int sm4cfbcheck();
extern int sm4ofbcheck();int main()
{sm4ecbcheck();sm4cbccheck();sm4cfbcheck();sm4ofbcheck();
}

过程

在这里插入图片描述
在这里插入图片描述

git log记录

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.在密标委网站http://www.gmbz.org.cn/main/bzlb.html查找SM2,SM3,SM4相关标准,分析代码实现与标准的对应关系。

sm2

sm2加解密(14-2)

  1. SM2参数初始化(SM2_Init)

    • 代码中的SM2_Init函数用于初始化SM2曲线参数,包括有限域参数pab和基点G的坐标GxGy。这些参数与SM2标准中定义的参数相对应。
  2. 密钥生成(SM2_KeyGeneration)

    • SM2_KeyGeneration函数用于从私钥计算公钥。这与SM2标准中的密钥生成过程相符,即公钥是私钥与基点G的椭圆曲线点乘结果。
  3. 加密(SM2_Encrypt)

    • SM2_Encrypt函数实现了SM2的加密过程,包括生成随机数k、计算点C1=[k]G、计算S=[h]C1、计算[k]PB=(x2,y2)、使用KDF(密钥派生函数)从x2||y2派生出密钥t,以及计算C2=M^tC3=hash(x2,M,y2)。这些步骤与SM2标准中的加密算法相匹配。
  4. 解密(SM2_Decrypt)

    • SM2_Decrypt函数实现了SM2的解密过程,包括验证C1的有效性、计算S=[h]C1、计算[dB]C1=(x2,y2)、使用KDF从x2||y2派生出密钥t,以及计算M=C2^t和验证C3=hash(x2,M,y2)。这些步骤与SM2标准中的解密算法相匹配。
  5. SM3哈希函数(SM3_256, SM3_KDF)

    • 代码中的SM3_256SM3_KDF函数实现了SM3哈希函数,这是SM2标准中用于消息摘要和密钥派生的部分。SM3_KDF函数用于从x2||y2派生出密钥t,这与SM2标准中的KDF过程相符。
  6. 点的验证(Test_Point, Test_PubKey)

    • Test_PointTest_PubKey函数用于验证椭圆曲线上的点是否有效,这与SM2标准中对点的验证要求相符。

sm2签名验签(14-3)

  1. SM2参数初始化(SM2_Init)

    • 代码中的SM2_Init函数用于初始化SM2曲线参数,包括有限域参数pab和基点G的坐标GxGy。这些参数与SM2标准中定义的参数相对应。
  2. 密钥生成(SM2_KeyGeneration)

    • SM2_KeyGeneration函数用于从私钥计算公钥。这与SM2标准中的密钥生成过程相符,即公钥是私钥与基点G的椭圆曲线点乘结果。
  3. 签名(SM2_Sign)

    • SM2_Sign函数实现了SM2的签名过程,包括生成随机数k、计算点kG、计算rs值。这些步骤与SM2标准中的签名算法相匹配。
  4. 签名验证(SM2_Verify)

    • SM2_Verify函数实现了SM2的签名验证过程,包括验证rs值的有效性。这些步骤与SM2标准中的验证算法相匹配。
  5. SM3哈希函数(SM3_256, SM3_KDF)

    • 代码中的SM3_256SM3_KDF函数实现了SM3哈希函数,这是SM2标准中用于消息摘要和密钥派生的部分。SM3_KDF函数用于从x2||y2派生出密钥t,这与SM2标准中的KDF过程相符。
  6. 点的验证(Test_Point, Test_PubKey)

    • Test_PointTest_PubKey函数用于验证椭圆曲线上的点是否有效,这与SM2标准中对点的验证要求相符。

sm3

(1) 一段式SM3算法(4-1)

  1. 初始化向量(IV)

    • 代码中的IV数组与SM3标准中定义的初始向量相对应。
  2. 循环左移(SL)

    • SL函数实现了SM3标准中的循环左移操作,这是SM3算法中的基本操作之一。
  3. Tj函数

    • Tj函数根据SM3标准中的Tj计算方法,返回不同的常数值。
  4. FFj和GGj函数

    • FFjGGj函数实现了SM3标准中的F和G函数,这些函数根据j的值选择不同的逻辑操作。
  5. P0和P1函数

    • P0P1函数实现了SM3标准中的P0和P1函数,这些函数用于对输入值进行特定的变换。
  6. 扩展函数(EB)

    • EB函数实现了SM3标准中的消息扩展步骤,将输入消息扩展为W和W1数组。
  7. 压缩函数(CF)

    • CF函数实现了SM3标准中的压缩函数,这是SM3算法的核心部分,用于计算消息的摘要。
  8. SM3Hash函数

    • SM3Hash函数实现了SM3算法的整个流程,包括消息填充、消息扩展、压缩函数和最终的摘要生成。
  9. 消息填充

    • SM3Hash函数中,消息填充步骤与SM3标准中定义的消息填充过程相符。
  10. 消息分组

    • 将填充后的消息按512比特进行分组,符合SM3标准的要求。
  11. 最终摘要生成

    • 最终,SM3Hash函数生成的摘要与SM3标准中定义的摘要生成过程相匹配。

(2) 实现三段式SM3算法(4-2)

  1. SM3上下文结构(sm3_context)

    • sm3_context结构体用于存储SM3算法的状态,包括总处理字节数、中间摘要状态和当前处理的数据块。
  2. SM3初始化(sm3_starts)

    • sm3_starts函数初始化SM3上下文,设置初始状态值,这些值与SM3标准中定义的初始向量相对应。
  3. SM3更新(sm3_update)

    • sm3_update函数处理输入数据,将数据分块处理,每块512位,并更新上下文中的摘要状态。
  4. SM3最终摘要(sm3_finish)

    • sm3_finish函数完成摘要计算,包括处理剩余数据块、添加填充,并输出最终的256位摘要。
  5. SM3散列计算(sm3)

    • sm3函数是一个便捷函数,它初始化上下文、处理输入数据并输出最终的摘要。
  6. SM3文件散列(sm3_file)

    • sm3_file函数计算文件的SM3散列值,它打开文件、读取内容并使用sm3_update更新摘要,最后调用sm3_finish输出摘要。
  7. 辅助宏定义(GET_ULONG_BE, PUT_ULONG_BE)

    • 这些宏定义用于从字节数组中提取和存储大端序的32位整数,符合SM3算法中对数据的处理方式。
  8. 消息扩展(sm3_process)

    • sm3_process函数实现了SM3算法的消息扩展和压缩函数,这是SM3算法的核心部分,用于计算消息的摘要。
  9. 循环左移(ROTL)

    • ROTL宏定义实现了循环左移操作,这是SM3算法中的基本操作之一。
  10. 逻辑函数(FF0, FF1, GG0, GG1, P0, P1)

    • 这些函数实现了SM3标准中的逻辑函数,用于在压缩函数中处理数据。

(3) 基于openssl实现sm3(4-3)

文件核心内容整理

sm3hash.h
  • 定义了一个函数sm3_hash,该函数用于计算SM3哈希值。
  • 函数原型:
    int sm3_hash(const unsigned char *message, size_t len, unsigned char *hash, unsigned int *hash_len);
    
    • message:输入的消息。
    • len:消息的长度。
    • hash:输出的哈希值。
    • hash_len:哈希值的长度。
sm3hash.cpp
  • 实现了sm3_hash函数,使用OpenSSL库中的EVP接口来计算SM3哈希值。
  • 核心步骤:
    1. 获取SM3算法的EVP_MD结构体。
    2. 创建一个新的EVP_MD_CTX上下文。
    3. 初始化摘要计算。
    4. 更新摘要计算,添加消息。
    5. 最终计算摘要,输出哈希值。
    6. 释放EVP_MD_CTX上下文。

代码实现与SM3标准的对应关系

  1. 算法选择

    • 使用EVP_sm3()从OpenSSL库中选择SM3算法,这对应于SM3标准的算法实现。
  2. 消息处理

    • 通过EVP_DigestInit_ex()初始化摘要计算,对应于SM3算法的初始化步骤。
    • 通过EVP_DigestUpdate()更新摘要计算,添加消息,对应于SM3算法的消息处理步骤。
  3. 摘要计算

    • 通过EVP_DigestFinal_ex()完成摘要计算,输出哈希值,对应于SM3算法的最终摘要输出步骤。
  4. 资源管理

    • 使用EVP_MD_CTX_new()EVP_MD_CTX_free()管理EVP_MD_CTX上下文的生命周期,确保资源正确释放。

通过使用OpenSSL库,sm3hash.cpp中的实现提供了一个高效且符合SM3标准的哈希计算方法。这种方法利用了OpenSSL库的加密算法实现,确保了与SM3标准的一致性。

(4) 实现HMAC-SM3算法(4-4)

  1. 初始化(sm3_starts)

    • 代码中的sm3_starts函数对应于SM3算法的初始化步骤,设置初始的哈希值和消息长度计数器。
  2. 处理消息(sm3_update)

    • sm3_update函数对应于SM3算法的消息处理步骤,它将输入的消息分块处理,每块64字节,直到所有消息都被处理。
  3. 消息扩展和压缩(sm3_process)

    • sm3_process函数实现了SM3算法的消息扩展和压缩函数,这是算法的核心部分,涉及到多轮的非线性变换和消息调度。
  4. 最终摘要(sm3_finish)

    • sm3_finish函数对应于SM3算法的最终摘要步骤,它将处理后的哈希值输出为最终的摘要。
  5. HMAC实现(sm3_hmac_*)

    • 代码还实现了基于SM3的HMAC(Hash-based Message Authentication Code),这是一种使用哈希函数和密钥来提供消息认证的机制。
  6. 文件摘要(sm3_file)

    • sm3_file函数提供了对文件内容进行SM3哈希的接口,它读取文件内容并使用sm3_update函数进行处理。

代码中的实现遵循了SM3算法的标准步骤,包括消息的分块处理、消息扩展、多轮压缩和最终摘要的生成。每个函数都对应于SM3算法的一个特定步骤,确保了算法的正确实现。

sm4

(1) sm4_16字节版(3-6)

  1. 密钥扩展(SM4_KeySchedule)

    • 代码中的SM4_KeySchedule函数对应于SM4算法的密钥扩展步骤,它根据给定的密钥生成32轮的轮密钥。
  2. 加密(SM4_Encrypt)

    • SM4_Encrypt函数对应于SM4算法的加密步骤,它使用密钥扩展得到的轮密钥对明文进行加密。
  3. 解密(SM4_Decrypt)

    • SM4_Decrypt函数对应于SM4算法的解密步骤,它使用密钥扩展得到的轮密钥对密文进行解密。
  4. 自检测试(SM4_SelfCheck)

    • SM4_SelfCheck函数提供了一个自检测试,用于验证算法实现的正确性。它使用标准数据进行加密和解密,并检查结果是否符合预期。

代码中的实现遵循了SM4算法的标准步骤,包括密钥扩展、轮函数应用、加密和解密。每个函数都对应于SM4算法的一个特定步骤,确保了算法的正确实现。

(2) 实现SM4-ECBCBCCFBOFB 算法(大数据版)——(3-7)

  1. 密钥扩展(SM4_KeySchedule)

    • 代码中的SM4_KeySchedule函数对应于SM4算法的密钥扩展步骤,它根据给定的密钥生成32轮的轮密钥。
  2. 加密(SM4_Encrypt)

    • SM4_Encrypt函数对应于SM4算法的加密步骤,它使用密钥扩展得到的轮密钥对明文进行加密。
  3. 解密(SM4_Decrypt)

    • SM4_Decrypt函数对应于SM4算法的解密步骤,它使用密钥扩展得到的轮密钥对密文进行解密。
  4. 自检测试(SM4_SelfCheck)

    • SM4_SelfCheck函数提供了一个自检测试,用于验证算法实现的正确性。它使用标准数据进行加密和解密,并检查结果是否符合预期。
  5. 加密模式(sm4ecb, sm4cbc, sm4cfb, sm4ofb)

    • 代码中还实现了SM4算法的多种工作模式,包括ECB模式(电子密码本模式)、CBC模式(密码块链模式)、CFB模式(密文反馈模式)和OFB模式(输出反馈模式)。这些模式提供了不同的安全性和性能特点,适用于不同的应用场景。

代码中的实现遵循了SM4算法的标准步骤,包括密钥扩展、轮函数应用、加密和解密。每个函数都对应于SM4算法的一个特定步骤,确保了算法的正确实现。

实验遇到的问腿

实验时发现sm2的编译一直不成功,后来通过询问同学了解到要在32位环境下编译,要加上-m32链接库,-lmiracl_32进行32位编译,最终编译成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1014.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

vite构建Vue3项目:封装公共组件,发布npm包,自定义组件库

文章目录 前言一、创建基础的vite 脚手架二、文件结构三、编写组件代码,本地测试四、配置项五、打包npm发布六、npm下载使用总结 前言 使用vue开发组件封装是一个很普遍的事情了&#xff0c;封装好一个组件可以在项目的任意地方去使用&#xff0c;我们还可以从npm仓库下载别人…

外包功能测试就干了4周,技术退步太明显了。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;21年通过校招进入武汉某软件公司&#xff0c;干了差不多3个星期的功能测试&#xff0c;那年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我才在一个外包企业干了4周的功…

基于LORA的一主多从监测系统_实物设计

最近代码写的差不多了&#xff0c;基本一主一从已经定下&#xff0c;并且经过24小时测试还算比较稳定&#xff0c;所以打算把硬件实物定下&#xff0c;之前用的杜邦线&#xff0c;看着也比较杂乱不是很好看&#xff0c;于是打算使用pcb来替代&#xff0c;这样也比较整洁可靠&am…

qt QRadioButton详解

QRadioButton 是一个可以切换选中&#xff08;checked&#xff09;或未选中&#xff08;unchecked&#xff09;状态的选项按钮。单选按钮通常呈现给用户一个“多选一”的选择&#xff0c;即在一组单选按钮中&#xff0c;一次只能选中一个按钮。 重要方法 QRadioButton(QWidget…

三:LoadBalancer负载均衡服务调用

LoadBalancer负载均衡服务调用 1.LB负载均衡(Load Balance)是什么2.loadbalancer本地负载均衡客户端 与 Nginx服务端负载均衡区别3.实现loadbalancer负载均衡实例3-1.首先应模拟启动多个服务提供者应用实例&#xff1a;3-2.在服务消费项目引入LoadBalancer3-3&#xff1a;测试用…

“农田奇迹:如何用遥感技术实现作物分类与产量精准估算“

在科技飞速发展的时代&#xff0c;遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究&#xff0c;空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而&#xff0c;对于许多专业人士而言&#xff0c;如何高效地处…

LeetCode :21. 合并两个有序链表(Java)

目录 题目描述: 代码: 第一种: 第二种: 题目描述: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; …

Spring Boot框架在信息学科平台建设中的实战技巧

3系统分析 3.1可行性分析 通过对本基于保密信息学科平台系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于保密信息学科平台系统采用Spring Boot框架&a…

「Mac畅玩鸿蒙与硬件26」UI互动应用篇3 - 倒计时和提醒功能实现

本篇将带领你实现一个倒计时和提醒功能的应用&#xff0c;用户可以设置倒计时时间并开始计时。当倒计时结束时&#xff0c;应用会显示提醒。该项目涉及时间控制、状态管理和用户交互&#xff0c;是学习鸿蒙应用开发的绝佳实践项目。 关键词 UI互动应用倒计时器状态管理用户交互…

【升华】自然语言处理架构

自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是指让计算机接受用户自然语言形式的输入&#xff0c;并在内部通过人类所定义的算法进行加工、计算等系列操作&#xff0c;以模拟人类对自然语言的理解&#xff0c;并返回用户所期望的结果。自…

Android OpenGL ES详解——模板Stencil

目录 一、概念 1、模板测试 2、模板缓冲 二、模板测试如何使用 1、开启和关闭模板测试 2、开启/禁止模板缓冲区写入 3、模板测试策略函数 4、更新模板缓冲 5、模板测试应用——物体轮廓 三、模板缓冲如何使用 1、创建模板缓冲 2、使用模板缓冲 3、模板缓冲应用——…

RHCE笔记-DNS服务器

一.DNS简介 DNS&#xff08;域名系统&#xff09;是一种互联网服务&#xff0c;负责将我们熟悉的域名&#xff08;比如 www.example.com&#xff09;转换为计算机能理解的IP地址&#xff08;比如 192.0.2.1&#xff09;。这样&#xff0c;当你在浏览器中输入网址时&#xff0c;…

高效自动化测试,引领汽车座舱新纪元——实车篇

引言 作为智能网联汽车的核心组成部分&#xff0c;智能座舱不仅是驾驶者与车辆互动的桥梁&#xff0c;更是个性化、智能化体验的源泉。实车测试作为验证智能座舱功能实现、用户体验、行车安全及法规符合性的关键环节&#xff0c;能够最直接地模拟真实驾驶场景&#xff0c;确保…

数智税务 | 大企业税务管理,即将面临哪些需求变革?

大企业税务管理&#xff0c;即将面临哪些需求变革&#xff1f; 随着“金税四期”的推进和发票电子化的发展&#xff0c;中国税务机关的税收征管模式逐步从传统的“经验管税”、“以票控税”转向“以数治税”的精准监管模式。这一转变既为大企业供应链加速升级带来了便利&#…

数字IC后端实现之Innovus Place跑完density爆涨案例分析

下图所示为咱们社区a7core后端训练营学员的floorplan。 数字IC后端实现 | Innovus各个阶段常用命令汇总 该学员跑placement前density是59.467%&#xff0c;但跑完place后density飙升到87.68%。 仔细查看place过程中的log就可以发现Density一路飙升&#xff01; 数字IC后端物…

[SAP ABAP] 自定义字段提供F4帮助

在SAP系统中&#xff0c;F4帮助是一个强大的功能&#xff0c;它允许用户在输入字段值时快速搜索和选择数 我们可以通过编写代码来为自定义字段提供F4帮助 程序代码 REPORT z437_test_2024.* 自定义数据类型 TYPES: BEGIN OF ty_mara,matnr TYPE mara-matnr, " 物料编号…

c怎么与python交互

ctypes是Python的一个外部库&#xff0c;可以使用python语言调用已经编译好的C语言函数以及数据类型并进行数据交换等。ctypes的官方文档在https://docs.python.org/3/library/ctypes.html 1、ctypes基本数据类型映射表 2、python调用c语言的函数库 &#xff08;1&#xff09…

ssm042在线云音乐系统的设计与实现+jsp(论文+源码)_kaic

摘 要 随着移动互联网时代的发展&#xff0c;网络的使用越来越普及&#xff0c;用户在获取和存储信息方面也会有激动人心的时刻。音乐也将慢慢融入人们的生活中。影响和改变我们的生活。随着当今各种流行音乐的流行&#xff0c;人们在日常生活中经常会用到的就是在线云音乐系统…

使用TypeORM进行数据库操作

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用TypeORM进行数据库操作 引言 TypeORM 简介 安装 TypeORM 配置 TypeORM 定义实体 连接数据库 运行项目 高级功能 事务管理 关…

【2024】强网杯

web&#xff1a; PyBlockly&#xff1a; ​ 网站是一个通过block的堆积木的形式编程&#xff0c;有两种数据类型以及四种函数&#xff0c;分别是正常运算&#xff0c;print输出&#xff0c;min和max功能&#xff0c;随便写一些代码&#xff0c;发现结果会回显出来。 ​ 再来…