#include "kdf.h"
/****************************************************************
Function: BiToW
Description: calculate W from Bi
Calls:
Called By: SM3_compress
Input: Bi[16] //a block of a message
Output: W[68]
Return: null
Others:
****************************************************************/
void BiToW(unsigned long Bi[], unsigned long W[])
{
int i;
unsigned long tmp;
for (i = 0; i <= 15; i++)
{
W[i] = Bi[i];
}
for (i = 16; i <= 67; i++)
{
tmp = W[i - 16]
^ W[i - 9]
^ SM3_rotl32(W[i - 3], 15);
W[i] = SM3_p1(tmp)
^ (SM3_rotl32(W[i - 13], 7))
^ W[i - 6];
}
}
/*****************************************************************
Function: WToW1
Description: calculate W1 from W
Calls:
Called By: SM3_compress
Input: W[68]
Output: W1[64]
Return: null
Others:
*****************************************************************/
void WToW1(unsigned long W[], unsigned long W1[])
{
int i;
for (i = 0; i <= 63; i++)
{
W1[i] = W[i] ^ W[i + 4];
}
}
/******************************************************************
Function: CF
Description: calculate the CF compress function and update V
Calls:
Called By: SM3_compress
Input: W[68]
W1[64]
V[8]
Output: V[8]
Return: null
Others:
********************************************************************/
void CF(unsigned long W[], unsigned long W1[], unsigned long V[])
{
unsigned long SS1;
unsigned long SS2;
unsigned long TT1;
unsigned long TT2;
unsigned long A, B, C, D, E, F, G, H;
unsigned long T = SM3_T1;
unsigned long FF;
unsigned long GG;
int j;
A = V[0];
B = V[1];
C = V[2];
D = V[3];
E = V[4];
F = V[5];
G = V[6];
H = V[7];
for (j = 0; j <= 63; j++)
{
if (j == 0)
{
T = SM3_T1;
}
else if (j == 16)
{
T = SM3_rotl32(SM3_T2, 16);
}
else
{
T = SM3_rotl32(T, 1);
}
SS1 = SM3_rotl32((SM3_rotl32(A, 12) + E + T), 7);
SS2 = SS1 ^ SM3_rotl32(A, 12);
if (j <= 15)
{
FF = SM3_ff0(A, B, C);
}
else
{
FF = SM3_ff1(A, B, C);
}
TT1 = FF + D + SS2 + *W1;
W1++;
if (j <= 15)
{
GG = SM3_gg0(E, F, G);
}
else
{
GG = SM3_gg1(E, F, G);
}
TT2 = GG + H + SS1 + *W;
W++;
D = C;
C = SM3_rotl32(B, 9);
B = A;
A = TT1;
H = G;
G = SM3_rotl32(F, 19);
F = E;
E = SM3_p0(TT2);
}
V[0] = A ^ V[0];
V[1] = B ^ V[1];
V[2] = C ^ V[2];
V[3] = D ^ V[3];
V[4] = E ^ V[4];
V[5] = F ^ V[5];
V[6] = G ^ V[6];
V[7] = H ^ V[7];
}
/******************************************************************************
Function: BigEndian
Description: unsigned int endian converse.GM/T 0004-2012 requires to use big-endian.
if CPU uses little-endian, BigEndian function is a necessary
call to change the little-endian format into big-endian format.
Calls:
Called By: SM3_compress, SM3_done
Input: src[bytelen]
bytelen
Output: des[bytelen]
Return: null
Others: src and des could implies the same address
*******************************************************************************/
void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[])
{
unsigned char tmp = 0;
unsigned long i = 0;
for (i = 0; i < bytelen / 4; i++)
{
tmp = des[4 * i];
des[4 * i] = src[4 * i + 3];
src[4 * i + 3] = tmp;
tmp = des[4 * i + 1];
des[4 * i + 1] = src[4 * i + 2];
des[4 * i + 2] = tmp;
}
}
/******************************************************************************
Function: SM3_init
Description: initiate SM3 state
Calls:
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_init(SM3_STATE *md)
{
md->curlen = md->length = 0;
md->state[0] = SM3_IVA;
md->state[1] = SM3_IVB;
md->state[2] = SM3_IVC;
md->state[3] = SM3_IVD;
md->state[4] = SM3_IVE;
md->state[5] = SM3_IVF;
md->state[6] = SM3_IVG;
md->state[7] = SM3_IVH;
}
/******************************************************************************
Function: SM3_compress
Description: compress a single block of message
Calls: BigEndian
BiToW
WToW1
CF
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_compress(SM3_STATE * md)
{
unsigned long W[68];
unsigned long W1[64];
BigEndian(md->buf, 64, md->buf);
BiToW((unsigned long *)md->buf, W);
WToW1(W, W1);
CF(W, W1, md->state);
}
/******************************************************************************
Function: SM3_process
Description: compress the first (len/64) blocks of message
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
unsigned char buf[len] //the input message
int len //bytelen of message
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_process(SM3_STATE * md, unsigned char *buf, int len)
{
while (len--)
{
/* copy byte */
md->buf[md->curlen] = *buf++;
md->curlen++;
/* is 64 bytes full? */
if (md->curlen == 64)
{
SM3_compress(md);
md->length += 512;
md->curlen = 0;
}
}
}
/******************************************************************************
Function: SM3_done
Description: compress the rest message that the SM3_process has left behind
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
Output: unsigned char *hash
Return: null
Others:
*******************************************************************************/
void SM3_done(SM3_STATE *md, unsigned char hash[])
{
int i;
unsigned char tmp = 0;
/* increase the bit length of the message */
md->length += md->curlen << 3;
/* append the '1' bit */
md->buf[md->curlen] = 0x80;
md->curlen++;
/* if the length is currently above 56 bytes, appends zeros till
it reaches 64 bytes, compress the current block, creat a new
block by appending zeros and length,and then compress it
*/
if (md->curlen > 56)
{
for (; md->curlen < 64;)
{
md->buf[md->curlen] = 0;
md->curlen++;
}
SM3_compress(md);
md->curlen = 0;
}
/* if the length is less than 56 bytes, pad upto 56 bytes of zeroes */
for (; md->curlen < 56;)
{
md->buf[md->curlen] = 0;
md->curlen++;
}
/* since all messages are under 2^32 bits we mark the top bits zero */
for (i = 56; i < 60; i++)
{
md->buf[i] = 0;
}
/* append length */
md->buf[63] = md->length & 0xff;
md->buf[62] = (md->length >> 8) & 0xff;
md->buf[61] = (md->length >> 16) & 0xff;
md->buf[60] = (md->length >> 24) & 0xff;
SM3_compress(md);
/* copy output */
memcpy(hash, md->state, SM3_len / 8);
BigEndian(hash, SM3_len / 8, hash);
}
/******************************************************************************
Function: SM3_256
Description: calculate a hash value from a given message
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char buf[len] //the input message
int len //bytelen of the message
Output: unsigned char hash[32]
Return: null
Others:
*******************************************************************************/
void SM3_256(unsigned char buf[], int len, unsigned char hash[])
{
SM3_STATE md;
SM3_init(&md);
SM3_process(&md, buf, len);
SM3_done(&md, hash);
}
/******************************************************************************
Function: SM3_KDF
Description: key derivation function
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char Z[zlen]
unsigned short zlen //bytelen of Z
unsigned short klen //bytelen of K
Output: unsigned char K[klen] //shared secret key
Return: null
Others:
*******************************************************************************/
void SM3_KDF(unsigned char Z[], unsigned short zlen, unsigned short klen, unsigned char K[])
{
unsigned short i, j, t;
unsigned int bitklen;
SM3_STATE md;
unsigned char Ha[SM2_NUMWORD];
unsigned char ct[4] = { 0,0,0,1 };
bitklen = klen * 8;
if (bitklen%SM2_NUMBITS)
t = bitklen / SM2_NUMBITS + 1;
else
t = bitklen / SM2_NUMBITS;
for (i = 1; i < t; i++)
{
SM3_init(&md);
SM3_process(&md, Z, zlen);
SM3_process(&md, ct, 4);
SM3_done(&md, Ha);
memcpy((K + SM2_NUMWORD * (i - 1)), Ha, SM2_NUMWORD);
if (ct[3] == 0xff)
{
ct[3] = 0;
if (ct[2] == 0xff)
{
ct[2] = 0;
if (ct[1] == 0xff)
{
ct[1] = 0;
ct[0]++;
}
else ct[1]++;
}
else ct[2]++;
}
else ct[3]++;
}
SM3_init(&md);
SM3_process(&md, Z, zlen);
SM3_process(&md, ct, 4);
SM3_done(&md, Ha);
if (bitklen%SM2_NUMBITS)
{
i = (SM2_NUMBITS - bitklen + SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8;
j = (bitklen - SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8;
memcpy((K + SM2_NUMWORD * (t - 1)), Ha, j);
}
else
{
memcpy((K + SM2_NUMWORD * (t - 1)), Ha, SM2_NUMWORD);
}
}
签名验签
命令行
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ nano sv.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ nano sv.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ vim kdf.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ vim kdf.h
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ vim test.c
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ gcc -o test test.c sv.c kdf.c -lmiracl_32 -m32
In file included from kdf.c:1:
kdf.c: In function ‘CF’:
kdf.h:22:31: warning: result of ‘2055708042 << 16’ requires 48 bits to represent, but ‘int’ only has 32 bits [-Wshift-overflow=]
22 | #define SM3_rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
| ^~
kdf.c:90:269: note: in expansion of macro ‘SM3_rotl32’
90 | T = SM3_rotl32(SM3_T2, 16);
| ^~~~~~~~~~
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ ./test
SM2 签名验签成功
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ git add .
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm2/sv$ git commit -m "sm2_sv"
[master 0b23ef7] sm2_sv
6 files changed, 906 insertions(+)
create mode 100644 shiyan2/2-2/sm2/sv/kdf.c
create mode 100644 shiyan2/2-2/sm2/sv/kdf.h
create mode 100644 shiyan2/2-2/sm2/sv/sv.c
create mode 100644 shiyan2/2-2/sm2/sv/sv.h
create mode 100755 shiyan2/2-2/sm2/sv/test
create mode 100644 shiyan2/2-2/sm2/sv/test.c
sv.c
#include "sv.h"
#include "kdf.h"
big Gx, Gy, p, a, b, n;
epoint *G, *nG;
unsigned char SM2_p[32] = { 0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff };
unsigned char SM2_a[32] = { 0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xfc };
unsigned char SM2_b[32] = { 0x28,0xe9,0xfa,0x9e, 0x9d,0x9f,0x5e,0x34, 0x4d,0x5a,0x9e,0x4b,0xcf,0x65,0x09,0xa7,
0xf3,0x97,0x89,0xf5, 0x15,0xab,0x8f,0x92, 0xdd,0xbc,0xbd,0x41,0x4d,0x94,0x0e,0x93 };
unsigned char SM2_Gx[32] = { 0x32,0xc4,0xae,0x2c, 0x1f,0x19,0x81,0x19,0x5f,0x99,0x04,0x46,0x6a,0x39,0xc9,0x94,
0x8f,0xe3,0x0b,0xbf,0xf2,0x66,0x0b,0xe1,0x71,0x5a,0x45,0x89,0x33,0x4c,0x74,0xc7 };
unsigned char SM2_Gy[32] = { 0xbc,0x37,0x36,0xa2,0xf4,0xf6,0x77,0x9c,0x59,0xbd,0xce,0xe3,0x6b,0x69,0x21,0x53,0xd0,
0xa9,0x87,0x7c,0xc6,0x2a,0x47,0x40,0x02,0xdf,0x32,0xe5,0x21,0x39,0xf0,0xa0 };
unsigned char SM2_n[32] = { 0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x72,0x03,0xdf,0x6b,0x21,0xc6,0x05,0x2b,0x53,0xbb,0xf4,0x09,0x39,0xd5,0x41,0x23 };
/****************************************************************
Function: SM2_Init
Description: Initiate SM2 curve
Calls: MIRACL functions
Called By: SM2_KeyGeneration,SM2_Sign,SM2_Verify,SM2_SelfCheck
Input: null
Output: null
Return: 0: sucess;
1: parameter initialization error;
4: the given point G is not a point of order n
Others:
****************************************************************/
int SM2_Init()
{
Gx = mirvar(0);
Gy = mirvar(0);
p = mirvar(0);
a = mirvar(0);
b = mirvar(0);
n = mirvar(0);
bytes_to_big(SM2_NUMWORD, SM2_Gx, Gx);
bytes_to_big(SM2_NUMWORD, SM2_Gy, Gy);
bytes_to_big(SM2_NUMWORD, SM2_p, p);
bytes_to_big(SM2_NUMWORD, SM2_a, a);
bytes_to_big(SM2_NUMWORD, SM2_b, b);
bytes_to_big(SM2_NUMWORD, SM2_n, n);
ecurve_init(a, b, p, MR_PROJECTIVE);
G = epoint_init();
nG = epoint_init();
if (!epoint_set(Gx, Gy, 0, G))
{
return ERR_ECURVE_INIT;
}
ecurve_mult(n, G, nG);
if (!point_at_infinity(nG))
{
return ERR_ORDER;
}
return 0;
}
/****************************************************************
Function: Test_Point
Description: test if the given point is on SM2 curve
Calls:
Called By: SM2_KeyGeneration
Input: point
Output: null
Return: 0: sucess
3: not a valid point on curve
Others:
****************************************************************/
int Test_Point(epoint* point)
{
big x, y, x_3, tmp;
x = mirvar(0);
y = mirvar(0);
x_3 = mirvar(0);
tmp = mirvar(0);
epoint_get(point, x, y);
power(x, 3, p, x_3);
multiply(x, a, x);
divide(x, p, tmp);
add(x_3, x, x);
add(x, b, x);
divide(x, p, tmp);
power(y, 2, p, y);
if (mr_compare(x, y) != 0)
return ERR_NOT_VALID_POINT;
else
return 0;
}
/****************************************************************
Function: Test_PubKey
Description: test if the given public key is valid
Calls:
Called By: SM2_KeyGeneration
Input: pubKey //a point
Output: null
Return: 0: sucess
2: a point at infinity
5: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
Others:
****************************************************************/
int Test_PubKey(epoint *pubKey)
{
big x, y, x_3, tmp;
epoint *nP;
x = mirvar(0);
y = mirvar(0);
x_3 = mirvar(0);
tmp = mirvar(0);
nP = epoint_init();
if (point_at_infinity(pubKey))
return ERR_INFINITY_POINT;
epoint_get(pubKey, x, y);
if ((mr_compare(x, p) != -1) || (mr_compare(y, p) != -1))
return ERR_NOT_VALID_ELEMENT;
if (Test_Point(pubKey) != 0)
return ERR_NOT_VALID_POINT;
ecurve_mult(n, pubKey, nP);
if (!point_at_infinity(nP))
return ERR_ORDER;
return 0;
}
/****************************************************************
Function: Test_Zero
Description: test if the big x is zero
Calls:
Called By: SM2_Sign
Input: pubKey //a point
Output: null
Return: 0: x!=0
1: x==0
Others:
****************************************************************/
int Test_Zero(big x)
{
big zero;
zero = mirvar(0);
if (mr_compare(x, zero) == 0)
return 1;
else return 0;
}
/****************************************************************
Function: Test_n
Description: test if the big x is order n
Calls:
Called By: SM2_Sign
Input: big x //a miracl data type
Output: null
Return: 0: sucess
1: x==n,fail
Others:
****************************************************************/
int Test_n(big x)
{
if (mr_compare(x, n) == 0)
return 1;
else return 0;
}
/****************************************************************
Function: Test_Range
Description: test if the big x belong to the range[1,n-1]
Calls:
Called By: SM2_Verify
Input: big x ///a miracl data type
Output: null
Return: 0: sucess
1: fail
Others:
****************************************************************/
int Test_Range(big x)
{
big one, decr_n;
one = mirvar(0);
decr_n = mirvar(0);
convert(1, one);
decr(n, 1, decr_n);
if ((mr_compare(x, one) < 0) | (mr_compare(x, decr_n) > 0))
return 1;
return 0;
}
/****************************************************************
Function: SM2_KeyGeneration
Description: calculate a pubKey out of a given priKey
Calls: SM2_SelfCheck()
Called By: SM2_Init()
Input: priKey // a big number lies in[1,n-2]
Output: pubKey // pubKey=[priKey]G
Return: 0: sucess
2: a point at infinity
5: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
Others:
****************************************************************/
int SM2_KeyGeneration(unsigned char PriKey[], unsigned char Px[], unsigned char Py[])
{
int i = 0;
big d, PAx, PAy;
epoint *PA;
SM2_Init();
PA = epoint_init();
d = mirvar(0);
PAx = mirvar(0);
PAy = mirvar(0);
bytes_to_big(SM2_NUMWORD, PriKey, d);
ecurve_mult(d, G, PA);
epoint_get(PA, PAx, PAy);
big_to_bytes(SM2_NUMWORD, PAx, Px, TRUE);
big_to_bytes(SM2_NUMWORD, PAy, Py, TRUE);
i = Test_PubKey(PA);
if (i)
return i;
else
return 0;
}
/****************************************************************
Function: SM2_Sign
Description: SM2 signature algorithm
Calls: SM2_Init(),Test_Zero(),Test_n(), SM3_256()
Called By: SM2_SelfCheck()
Input: message //the message to be signed
len //the length of message
ZA // ZA=Hash(ENTLA|| IDA|| a|| b|| Gx || Gy || xA|| yA)
rand //a random number K lies in [1,n-1]
d //the private key
Output: R,S //signature result
Return: 0: sucess
1: parameter initialization error;
4: the given point G is not a point of order n
6: the signed r equals 0 or r+rand equals n
7 the signed s equals 0
Others:
****************************************************************/
int SM2_Sign(unsigned char *message, int len, unsigned char ZA[], unsigned char rand[], unsigned char d[], unsigned char R[], unsigned char S[])
{
unsigned char hash[SM3_len / 8];
int M_len = len + SM3_len / 8;
unsigned char *M = NULL;
int i;
big dA, r, s, e, k, KGx, KGy;
big rem, rk, z1, z2;
epoint *KG;
i = SM2_Init();
if (i) return i;
dA = mirvar(0);
e = mirvar(0);
k = mirvar(0);
KGx = mirvar(0);
KGy = mirvar(0);
r = mirvar(0);
s = mirvar(0);
rem = mirvar(0);
rk = mirvar(0);
z1 = mirvar(0);
z2 = mirvar(0);
bytes_to_big(SM2_NUMWORD, d, dA);
KG = epoint_init();
M = (char *)malloc(sizeof(char)*(M_len + 1));
memcpy(M, ZA, SM3_len / 8);
memcpy(M + SM3_len / 8, message, len);
SM3_256(M, M_len, hash);
bytes_to_big(SM3_len / 8, hash, e);
bytes_to_big(SM3_len / 8, rand, k);
ecurve_mult(k, G, KG);
epoint_get(KG, KGx, KGy);
add(e, KGx, r);
divide(r, n, rem);
add(r, k, rk);
if (Test_Zero(r) | Test_n(rk))
return ERR_GENERATE_R;
incr(dA, 1, z1);
xgcd(z1, n, z1, z1, z1);
multiply(r, dA, z2);
divide(z2, n, rem);
subtract(k, z2, z2);
add(z2, n, z2);
multiply(z1, z2, s);
divide(s, n, rem);
if (Test_Zero(s))
return ERR_GENERATE_S;
big_to_bytes(SM2_NUMWORD, r, R, TRUE);
big_to_bytes(SM2_NUMWORD, s, S, TRUE);
free(M);
return 0;
}
/****************************************************************
Function: SM2_Verify
Description: SM2 verification algorithm
Calls: SM2_Init(),Test_Range(), Test_Zero(),SM3_256()
Called By: SM2_SelfCheck()
Input: message //the message to be signed
len //the length of message
ZA //ZA=Hash(ENTLA|| IDA|| a|| b|| Gx || Gy || xA|| yA)
Px,Py //the public key
R,S //signature result
Output:
Return: 0: sucess
1: parameter initialization error;
4: the given point G is not a point of order n
B: public key error
8: the signed R out of range [1,n-1]
9: the signed S out of range [1,n-1]
A: the intermediate data t equals 0
C: verification fail
Others:
****************************************************************/
int SM2_Verify(unsigned char *message, int len, unsigned char ZA[], unsigned char Px[], unsigned char Py[], unsigned char R[], unsigned char S[])
{
unsigned char hash[SM3_len / 8];
int M_len = len + SM3_len / 8;
unsigned char *M = NULL;
int i;
big PAx, PAy, r, s, e, t, rem, x1, y1;
big RR;
epoint *PA, *sG, *tPA;
i = SM2_Init();
if (i) return i;
PAx = mirvar(0);
PAy = mirvar(0);
r = mirvar(0);
s = mirvar(0);
e = mirvar(0);
t = mirvar(0);
x1 = mirvar(0);
y1 = mirvar(0);
rem = mirvar(0);
RR = mirvar(0);
PA = epoint_init();
sG = epoint_init();
tPA = epoint_init();
bytes_to_big(SM2_NUMWORD, Px, PAx);
bytes_to_big(SM2_NUMWORD, Py, PAy);
bytes_to_big(SM2_NUMWORD, R, r);
bytes_to_big(SM2_NUMWORD, S, s);
if (!epoint_set(PAx, PAy, 0, PA))
{
return ERR_PUBKEY_INIT;
}
if (Test_Range(r))
return ERR_OUTRANGE_R;
if (Test_Range(s))
return ERR_OUTRANGE_S;
M = (char *)malloc(sizeof(char)*(M_len + 1));
memcpy(M, ZA, SM3_len / 8);
memcpy(M + SM3_len / 8, message, len);
SM3_256(M, M_len, hash);
bytes_to_big(SM3_len / 8, hash, e);
add(r, s, t);
divide(t, n, rem);
if (Test_Zero(t))
return ERR_GENERATE_T;
ecurve_mult(s, G, sG);
ecurve_mult(t, PA, tPA);
ecurve_add(sG, tPA);
epoint_get(tPA, x1, y1);
add(e, x1, RR);
divide(RR, n, rem);
free(M);
if (mr_compare(RR, r) == 0)
return 0;
else
return ERR_DATA_MEMCMP;
}
/****************************************************************
Function: SM2_SelfCheck
Description: SM2 self check
Calls: SM2_Init(), SM2_KeyGeneration,SM2_Sign, SM2_Verify,SM3_256()
Called By:
Input:
Output:
Return: 0: sucess
1: paremeter initialization error
2: a point at infinity
5: X or Y coordinate is beyond Fq
3: not a valid point on curve
4: not a point of order n
B: public key error
8: the signed R out of range [1,n-1]
9: the signed S out of range [1,n-1]
A: the intermediate data t equals 0
C: verification fail
Others:
****************************************************************/
int SM2_SelfCheck()
{
unsigned char dA[32] = { 0x39,0x45,0x20,0x8f,0x7b,0x21,0x44,0xb1,0x3f,0x36,0xe3,0x8a,0xc6,0xd3,0x9f,
0x95,0x88,0x93,0x93,0x69,0x28,0x60,0xb5,0x1a,0x42,0xfb,0x81,0xef,0x4d,0xf7,0xc5,0xb8 };
unsigned char rand[32] = { 0x59,0x27,0x6E,0x27,0xD5,0x06,0x86,0x1A,0x16,0x68,0x0F,0x3A,0xD9,0xC0,0x2D,
0xCC,0xEF,0x3C,0xC1,0xFA,0x3C,0xDB,0xE4,0xCE,0x6D,0x54,0xB8,0x0D,0xEA,0xC1,0xBC,0x21 };
/* unsigned char xA[32]={0x09,0xf9,0xdf,0x31,0x1e,0x54,0x21,0xa1,0x50,0xdd,0x7d,0x16,0x1e,0x4b,0xc5,
0xc6,0x72,0x17,0x9f,0xad,0x18,0x33,0xfc,0x07,0x6b,0xb0,0x8f,0xf3,0x56,0xf3,0x50,0x20};
unsigned char yA[32]={0xcc,0xea,0x49,0x0c,0xe2,0x67,0x75,0xa5,0x2d,0xc6,0xea,0x71,0x8c,0xc1,0xaa,
0x60,0x0a,0xed,0x05,0xfb,0xf3,0x5e,0x08,0x4a,0x66,0x32,0xf6,0x07,0x2d,0xa9,0xad,0x13};*/
unsigned char xA[32], yA[32];
unsigned char r[32], s[32];
unsigned char IDA[16] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,
0x34,0x35,0x36,0x37,0x38 }; int IDA_len = 16;
unsigned char ENTLA[2] = { 0x00,0x80 };
unsigned char *message = "message digest";
int len = strlen(message);
unsigned char ZA[SM3_len / 8];
unsigned char Msg[210];
int temp;
miracl *mip = mirsys(10000, 16);
mip->IOBASE = 16;
temp = SM2_KeyGeneration(dA, xA, yA);
if (temp)
return temp;
memcpy(Msg, ENTLA, 2);
memcpy(Msg + 2, IDA, IDA_len);
memcpy(Msg + 2 + IDA_len, SM2_a, SM2_NUMWORD);
memcpy(Msg + 2 + IDA_len + SM2_NUMWORD, SM2_b, SM2_NUMWORD);
memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 2, SM2_Gx, SM2_NUMWORD);
memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 3, SM2_Gy, SM2_NUMWORD);
memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 4, xA, SM2_NUMWORD);
memcpy(Msg + 2 + IDA_len + SM2_NUMWORD * 5, yA, SM2_NUMWORD);
SM3_256(Msg, 210, ZA);
temp = SM2_Sign(message, len, ZA, rand, dA, r, s);
if (temp)
return temp;
temp = SM2_Verify(message, len, ZA, xA, yA, r, s);
if (temp)
return temp;
return 0;
}
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/1$ vim test.cpp
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/1$ g++ -o test test.cpp -m32
ld@DESKTOP-69L72QA:~/shiyan2/2-2/sm3/1$ ./test
SM3 Hash:
66 c7 f0 f4 62 ee ed d9 d1 f2 d4 6b dc 10 e4 e2
41 67 c4 87 5c f2 f7 a2 29 7d a0 2b 8f 4b a8 e0
test.cpp
#include<stdio.h>#include<memory>#include<cstring>#include<cstdint>unsignedchar 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};unsignedlongSL(unsignedlong X,int n){uint64_t x = X;
x = x <<(n %32);unsignedlong l =(unsignedlong)(x >>32);return x | l;}unsignedlongTj(int j){if(j <=15){return0x79cc4519;}else{return0x7a879d8a;}}unsignedlongFFj(int j,unsignedlong X,unsignedlong Y,unsignedlong Z){if(j <=15){return X ^ Y ^ Z;}else{return(X & Y)|(X & Z)|(Y & Z);}}unsignedlongGGj(int j,unsignedlong X,unsignedlong Y,unsignedlong Z){if(j <=15){return X ^ Y ^ Z;}else{return(X & Y)|(~X & Z);}}unsignedlongP0(unsignedlong X){return X ^SL(X,9)^SL(X,17);}unsignedlongP1(unsignedlong X){return X ^SL(X,15)^SL(X,23);}voidEB(unsignedchar Bi[512/8],unsignedlong W[68],unsignedlong W1[64]){for(int i =0; i <16;++i){
W[i]= Bi[i *4]<<24| Bi[i *4+1]<<16| Bi[i *4+2]<<8| Bi[i *4+3];}for(int j =16; j <=67;++j){
W[j]=P1(W[j -16]^ W[j -9]^SL(W[j -3],15))^SL(W[j -13],7)^ W[j -6];}for(int j =0; j <=63;++j){
W1[j]= W[j]^ W[j +4];}}voidCF(unsignedchar Vi[256/8],unsignedchar Bi[512/8],unsignedchar Vi1[256/8]){unsignedlong W[68]={0};unsignedlong W1[64]={0};EB(Bi, W, W1);unsignedlong R[8]={0};for(int i =0; i <8;++i){
R[i]=((unsignedlong)Vi[i *4])<<24|((unsignedlong)Vi[i *4+1])<<16|((unsignedlong)Vi[i *4+2])<<8|((unsignedlong)Vi[i *4+3]);}unsignedlong A = R[0], B = R[1], C = R[2], D = R[3], E = R[4], F = R[5], G = R[6], H = R[7];unsignedlong SS1, SS2, TT1, TT2;for(int j =0; j <=63;++j){
SS1 =SL(SL(A,12)+ E +SL(Tj(j), j),7);
SS2 = SS1 ^SL(A,12);
TT1 =FFj(j, A, B, C)+ D + SS2 + W1[j];
TT2 =GGj(j, E, F, G)+ H + SS1 + W[j];
D = C;
C =SL(B,9);
B = A;
A = TT1;
H = G;
G =SL(F,19);
F = E;
E =P0(TT2);}
R[0]= A, R[1]= B, R[2]= C, R[3]= D, R[4]= E, R[5]= F, R[6]= G, R[7]= H;for(int i =0; i <8;++i){
Vi1[i *4]=(R[i]>>24)&0xFF;
Vi1[i *4+1]=(R[i]>>16)&0xFF;
Vi1[i *4+2]=(R[i]>>8)&0xFF;
Vi1[i *4+3]=(R[i])&0xFF;}for(int i =0; i <256/8;++i){
Vi1[i]^= Vi[i];}}voidSM3Hash(unsignedchar* m,int ml,unsignedchar r[32]){int l = ml *8;int k =448-1- l %512;if(k <=0){
k +=512;}int n =(l + k +65)/512;int m1l = n *512/8;unsignedchar* m1 =newunsignedchar[m1l];memset(m1,0, m1l);memcpy(m1, m, l /8);
m1[l /8]=0x80;unsignedlong l1 = l;for(int i =0; i <64/8&& l1 >0;++i){
m1[m1l -1- i]= l1 &0xFF;
l1 = l1 >>8;}unsignedchar** B =newunsignedchar*[n];for(int i =0; i < n;++i){
B[i]=newunsignedchar[512/8];memcpy(B[i], m1 +(512/8)*i,512/8);}delete[] m1;unsignedchar** V =newunsignedchar*[n +1];for(int i =0; i <= n;++i){
V[i]=newunsignedchar[256/8];memset(V[i],0,256/8);}memcpy(V[0], IV,256/8);for(int i =0; i < n;++i){CF(V[i], B[i], V[i +1]);}for(int i =0; i < n;++i){delete[] B[i];}delete[] B;memcpy(r, V[n],32);for(int i =0; i <= n;++i){delete[] V[i];}delete[] V;}voiddumpbuf(unsignedchar* buf,int len){for(int i =0; i < len;++i){printf("%02x", buf[i]);if((i +1)%16==0)printf("\n");elseprintf(" ");}printf("\n");}intmain(){unsignedchar message[]="abc";int message_len =strlen((char*)message);unsignedchar hash_result[32]={0};SM3Hash(message, message_len, hash_result);printf("SM3 Hash:\n");dumpbuf(hash_result,32);return0;}