mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-25 14:43:40 +08:00
447 lines
16 KiB
C
447 lines
16 KiB
C
/* ====================================================================
|
||
* Copyright (c) 2016 The GmSSL Project. All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions
|
||
* are met:
|
||
*
|
||
* 1. Redistributions of source code must retain the above copyright
|
||
* notice, this list of conditions and the following disclaimer.
|
||
*
|
||
* 2. Redistributions in binary form must reproduce the above copyright
|
||
* notice, this list of conditions and the following disclaimer in
|
||
* the documentation and/or other materials provided with the
|
||
* distribution.
|
||
*
|
||
* 3. All advertising materials mentioning features or use of this
|
||
* software must display the following acknowledgment:
|
||
* "This product includes software developed by the GmSSL Project.
|
||
* (http://gmssl.org/)"
|
||
*
|
||
* 4. The name "GmSSL Project" must not be used to endorse or promote
|
||
* products derived from this software without prior written
|
||
* permission. For written permission, please contact
|
||
* guanzhi1980@gmail.com.
|
||
*
|
||
* 5. Products derived from this software may not be called "GmSSL"
|
||
* nor may "GmSSL" appear in their names without prior written
|
||
* permission of the GmSSL Project.
|
||
*
|
||
* 6. Redistributions of any form whatsoever must retain the following
|
||
* acknowledgment:
|
||
* "This product includes software developed by the GmSSL Project
|
||
* (http://gmssl.org/)"
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
|
||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
|
||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
* ====================================================================
|
||
*/
|
||
|
||
|
||
#include "sm9_standard.h"
|
||
#include "miracl.h"
|
||
#include "mirdef.h"
|
||
#include <math.h>
|
||
|
||
|
||
int SM9_standard_h2(unsigned char Z[], int Zlen, big n, big h2)
|
||
{
|
||
int hlen, ZHlen, i;
|
||
big hh, i256, tmp, n1;
|
||
unsigned char *ZH = NULL, *ha = NULL;
|
||
|
||
hh = mirvar(0);
|
||
i256 = mirvar(0);
|
||
tmp = mirvar(0);
|
||
n1 = mirvar(0);
|
||
convert(1, i256);
|
||
ZHlen = Zlen + 1;
|
||
|
||
hlen = (int)ceil((5.0 * logb2(n)) / 32.0);
|
||
decr(n, 1, n1);
|
||
ZH = (char *)malloc(sizeof(char)*(ZHlen + 1));
|
||
if(ZH == NULL)
|
||
return SM9_ASK_MEMORY_ERR;
|
||
memcpy(ZH + 1, Z, Zlen);
|
||
ZH[0] = 0x02;
|
||
ha = (char *)malloc(sizeof(char)*(hlen + 1));
|
||
if(ha == NULL)
|
||
return SM9_ASK_MEMORY_ERR;
|
||
SM3_kdf(ZH, ZHlen, hlen, ha);
|
||
|
||
for(i = hlen - 1; i >= 0; i--)//key[从大到小]
|
||
{
|
||
premult(i256, ha[i], tmp);
|
||
add(hh, tmp, hh);
|
||
premult(i256, 256, i256);
|
||
divide(i256, n1, tmp);
|
||
divide(hh, n1, tmp);
|
||
}
|
||
incr(hh, 1, h2);
|
||
free(ZH);
|
||
free(ha);
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
int SM9_standard_generatesignkey(unsigned char hid[], unsigned char *ID, int IDlen, big ks, unsigned char Ppubs[], unsigned char dsa[])
|
||
{
|
||
big h1, t1, t2, rem, xdSA, ydSA, tmp;
|
||
unsigned char *Z = NULL;
|
||
int Zlen = IDlen + 1, buf;
|
||
ecn2 Ppub;
|
||
epoint *dSA;
|
||
|
||
h1 = mirvar(0);
|
||
t1 = mirvar(0);
|
||
t2 = mirvar(0);
|
||
rem = mirvar(0);
|
||
tmp = mirvar(0);
|
||
xdSA = mirvar(0);
|
||
ydSA = mirvar(0);
|
||
dSA = epoint_init();
|
||
Ppub.x.a = mirvar(0);
|
||
Ppub.x.b = mirvar(0);
|
||
Ppub.y.a = mirvar(0);
|
||
Ppub.y.b = mirvar(0);
|
||
Ppub.z.a = mirvar(0);
|
||
Ppub.z.b = mirvar(0);
|
||
Ppub.marker = MR_EPOINT_INFINITY;
|
||
|
||
Z = (char *)malloc(sizeof(char)*(Zlen + 1));
|
||
memcpy(Z, ID, IDlen);
|
||
memcpy(Z + IDlen, hid, 1);
|
||
|
||
buf = SM9_standard_h1(Z, Zlen, N, h1);
|
||
if(buf != 0)
|
||
return buf;
|
||
add(h1, ks, t1);//t1=H1(IDA||hid,N)+ks
|
||
xgcd(t1, N, t1, t1, t1);//t1=t1(-1)
|
||
multiply(ks, t1, t2);
|
||
divide(t2, N, rem);//t2=ks*t1(-1)
|
||
|
||
//dSA=[t2]P1
|
||
ecurve_mult(t2, P1, dSA);
|
||
|
||
//Ppub=[ks]P2
|
||
ecn2_copy(&P2, &Ppub);
|
||
ecn2_mul(ks, &Ppub);
|
||
|
||
printf("\n*********************The signed key = (xdA, ydA):*********************\n");
|
||
epoint_get(dSA, xdSA, ydSA);
|
||
cotnum(xdSA, stdout);
|
||
cotnum(ydSA, stdout);
|
||
printf("\n**********************PublicKey Ppubs=[ks]P2:*************************\n");
|
||
ecn2_Bytes128_Print(Ppub);
|
||
|
||
epoint_get(dSA, xdSA, ydSA);
|
||
big_to_bytes(BNLEN, xdSA, dsa, 1);
|
||
big_to_bytes(BNLEN, ydSA, dsa + BNLEN, 1);
|
||
|
||
redc(Ppub.x.b, tmp);
|
||
big_to_bytes(BNLEN, tmp, Ppubs, 1);
|
||
redc(Ppub.x.a, tmp);
|
||
big_to_bytes(BNLEN, tmp, Ppubs + BNLEN, 1);
|
||
redc(Ppub.y.b, tmp);
|
||
big_to_bytes(BNLEN, tmp, Ppubs + BNLEN * 2, 1);
|
||
redc(Ppub.y.a, tmp);
|
||
big_to_bytes(BNLEN, tmp, Ppubs + BNLEN * 3, 1);
|
||
|
||
free(Z);
|
||
return 0;
|
||
}
|
||
|
||
|
||
int SM9_standard_sign(unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char rand[], unsigned char dsa[], unsigned char Ppub[], unsigned char H[], unsigned char S[])
|
||
{
|
||
big h1, r, h, l, xdSA, ydSA;
|
||
big xS, yS, tmp, zero;
|
||
zzn12 g, w;
|
||
epoint *s, *dSA;
|
||
ecn2 Ppubs;
|
||
int Zlen, buf;
|
||
unsigned char *Z = NULL;
|
||
|
||
//initiate
|
||
h1 = mirvar(0);
|
||
r = mirvar(0);
|
||
h = mirvar(0);
|
||
l = mirvar(0);
|
||
tmp = mirvar(0);
|
||
zero = mirvar(0);
|
||
xS = mirvar(0);
|
||
yS = mirvar(0);
|
||
xdSA = mirvar(0);
|
||
ydSA = mirvar(0);
|
||
s = epoint_init();
|
||
dSA = epoint_init();
|
||
Ppubs.x.a = mirvar(0);
|
||
Ppubs.x.b = mirvar(0);
|
||
Ppubs.y.a = mirvar(0);
|
||
Ppubs.y.b = mirvar(0);
|
||
Ppubs.z.a = mirvar(0);
|
||
Ppubs.z.b = mirvar(0);
|
||
Ppubs.marker = MR_EPOINT_INFINITY;
|
||
zzn12_init(&g);
|
||
zzn12_init(&w);
|
||
|
||
bytes_to_big(BNLEN, rand, r);
|
||
bytes_to_big(BNLEN, dsa, xdSA);
|
||
bytes_to_big(BNLEN, dsa + BNLEN, ydSA);
|
||
epoint_set(xdSA, ydSA, 0, dSA);
|
||
bytes128_to_ecn2(Ppub, &Ppubs);
|
||
|
||
//Step1:g = e(P1, Ppub-s)
|
||
if(!ecap(Ppubs, P1, para_t, X, &g))
|
||
return SM9_MY_ECAP_12A_ERR;
|
||
//test if a ZZn12 element is of order q
|
||
if(!member(g, para_t, X))
|
||
return SM9_MEMBER_ERR;
|
||
|
||
printf("\n***********************g=e(P1,Ppubs):****************************\n");
|
||
zzn12_ElementPrint(g);
|
||
|
||
//Step2:calculate w=g(r)
|
||
printf("\n***********************randnum r:********************************\n");
|
||
cotnum(r, stdout);
|
||
w = zzn12_pow(g, r);
|
||
printf("\n***************************w=gr:**********************************\n");
|
||
zzn12_ElementPrint(w);
|
||
|
||
//Step3:calculate h=H2(M||w,N)
|
||
Zlen = len + 32 * 12;
|
||
Z = (char *)malloc(sizeof(char)*(Zlen + 1));
|
||
if(Z == NULL)
|
||
return SM9_ASK_MEMORY_ERR;
|
||
|
||
LinkCharZzn12(message, len, w, Z, Zlen);
|
||
buf = SM9_standard_h2(Z, Zlen, N, h);
|
||
if(buf != 0)
|
||
return buf;
|
||
printf("\n****************************h:*************************************\n");
|
||
cotnum(h, stdout);
|
||
|
||
//Step4:l=(r-h)mod N
|
||
subtract(r, h, l);
|
||
divide(l, N, tmp);
|
||
while(mr_compare(l, zero) < 0)
|
||
add(l, N, l);
|
||
if(mr_compare(l, zero) == 0)
|
||
return SM9_L_error;
|
||
printf("\n**************************l=(r-h)mod N:****************************\n");
|
||
cotnum(l, stdout);
|
||
|
||
//Step5:S=[l]dSA=(xS,yS)
|
||
ecurve_mult(l, dSA, s);
|
||
epoint_get(s, xS, yS);
|
||
printf("\n**************************S=[l]dSA=(xS,yS):*************************\n");
|
||
cotnum(xS, stdout);
|
||
cotnum(yS, stdout);
|
||
|
||
big_to_bytes(32, h, H, 1);
|
||
big_to_bytes(32, xS, S, 1);
|
||
big_to_bytes(32, yS, S + 32, 1);
|
||
|
||
free(Z);
|
||
return 0;
|
||
}
|
||
|
||
|
||
int SM9_standard_verify(unsigned char H[], unsigned char S[], unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char Ppub[])
|
||
{
|
||
big h, xS, yS, h1, h2;
|
||
epoint *S1;
|
||
zzn12 g, t, u, w;
|
||
ecn2 P, Ppubs;
|
||
int Zlen1, Zlen2, buf;
|
||
unsigned char * Z1 = NULL, *Z2 = NULL;
|
||
|
||
h = mirvar(0);
|
||
h1 = mirvar(0);
|
||
h2 = mirvar(0);
|
||
xS = mirvar(0);
|
||
yS = mirvar(0);
|
||
P.x.a = mirvar(0);
|
||
P.x.b = mirvar(0);
|
||
P.y.a = mirvar(0);
|
||
P.y.b = mirvar(0);
|
||
P.z.a = mirvar(0);
|
||
P.z.b = mirvar(0);
|
||
P.marker = MR_EPOINT_INFINITY;
|
||
Ppubs.x.a = mirvar(0);
|
||
Ppubs.x.b = mirvar(0);
|
||
Ppubs.y.a = mirvar(0);
|
||
Ppubs.y.b = mirvar(0);
|
||
Ppubs.z.a = mirvar(0);
|
||
Ppubs.z.b = mirvar(0);
|
||
Ppubs.marker = MR_EPOINT_INFINITY;
|
||
S1 = epoint_init();
|
||
zzn12_init(&g);
|
||
zzn12_init(&t);
|
||
zzn12_init(&u);
|
||
zzn12_init(&w);
|
||
|
||
bytes_to_big(BNLEN, H, h);
|
||
bytes_to_big(BNLEN, S, xS);
|
||
bytes_to_big(BNLEN, S + BNLEN, yS);
|
||
bytes128_to_ecn2(Ppub, &Ppubs);
|
||
|
||
//Step 1:test if h in the rangge [1,N-1]
|
||
if(Test_Range(h))
|
||
return SM9_H_OUTRANGE;
|
||
|
||
//Step 2:test if S is on G1
|
||
epoint_set(xS, yS, 0, S1);
|
||
if(Test_Point(S1))
|
||
return SM9_S_NOT_VALID_G1;
|
||
|
||
//Step3:g = e(P1, Ppub-s)
|
||
if(!ecap(Ppubs, P1, para_t, X, &g))
|
||
return SM9_MY_ECAP_12A_ERR;
|
||
//test if a ZZn12 element is of order q
|
||
if(!member(g, para_t, X))
|
||
return SM9_MEMBER_ERR;
|
||
|
||
printf("\n***********************g=e(P1,Ppubs):****************************\n");
|
||
zzn12_ElementPrint(g);
|
||
|
||
//Step4:calculate t=g(h)
|
||
t = zzn12_pow(g, h);
|
||
printf("\n***************************w=gh:**********************************\n");
|
||
zzn12_ElementPrint(t);
|
||
|
||
//Step5:calculate h1=H1(IDA||hid,N)
|
||
Zlen1 = strlen(IDA) + 1;
|
||
Z1 = (char *)malloc(sizeof(char)*(Zlen1 + 1));
|
||
if(Z1 == NULL)
|
||
return SM9_ASK_MEMORY_ERR;
|
||
|
||
memcpy(Z1, IDA, strlen(IDA));
|
||
memcpy(Z1 + strlen(IDA), hid, 1);
|
||
buf = SM9_standard_h1(Z1, Zlen1, N, h1);
|
||
if(buf != 0)
|
||
return buf;
|
||
printf("\n****************************h1:**********************************\n");
|
||
cotnum(h1, stdout);
|
||
|
||
//Step6:P=[h1]P2+Ppubs
|
||
ecn2_copy(&P2, &P);
|
||
ecn2_mul(h1, &P);
|
||
ecn2_add(&Ppubs, &P);
|
||
|
||
//Step7:u=e(S1,P)
|
||
if(!ecap(P, S1, para_t, X, &u))
|
||
return SM9_MY_ECAP_12A_ERR;
|
||
//test if a ZZn12 element is of order q
|
||
if(!member(u, para_t, X))
|
||
return SM9_MEMBER_ERR;
|
||
printf("\n************************** u=e(S1,P):*****************************\n");
|
||
zzn12_ElementPrint(u);
|
||
|
||
//Step8:w=u*t
|
||
zzn12_mul(u, t, &w);
|
||
printf("\n************************* w=u*t: **********************************\n");
|
||
zzn12_ElementPrint(w);
|
||
|
||
//Step9:h2=H2(M||w,N)
|
||
Zlen2 = len + 32 * 12;
|
||
Z2 = (char *)malloc(sizeof(char)*(Zlen2 + 1));
|
||
if(Z2 == NULL)
|
||
return SM9_ASK_MEMORY_ERR;
|
||
|
||
LinkCharZzn12(message, len, w, Z2, Zlen2);
|
||
buf = SM9_standard_h2(Z2, Zlen2, N, h2);
|
||
if(buf != 0)
|
||
return buf;
|
||
printf("\n**************************** h2:***********************************\n");
|
||
cotnum(h2, stdout);
|
||
|
||
free(Z1);
|
||
free(Z2);
|
||
if(mr_compare(h2, h) != 0)
|
||
return SM9_DATA_MEMCMP_ERR;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
int SM9_standard_sv_selfcheck()
|
||
{
|
||
//the master private key
|
||
unsigned char dA[32] = {0x00, 0x01, 0x30, 0xE7, 0x84, 0x59, 0xD7, 0x85, 0x45, 0xCB, 0x54, 0xC5, 0x87, 0xE0, 0x2C, 0xF4,
|
||
0x80, 0xCE, 0x0B, 0x66, 0x34, 0x0F, 0x31, 0x9F, 0x34, 0x8A, 0x1D, 0x5B, 0x1F, 0x2D, 0xC5, 0xF4};
|
||
unsigned char rand[32] = {0x00, 0x03, 0x3C, 0x86, 0x16, 0xB0, 0x67, 0x04, 0x81, 0x32, 0x03, 0xDF, 0xD0, 0x09, 0x65, 0x02,
|
||
0x2E, 0xD1, 0x59, 0x75, 0xC6, 0x62, 0x33, 0x7A, 0xED, 0x64, 0x88, 0x35, 0xDC, 0x4B, 0x1C, 0xBE};
|
||
|
||
unsigned char h[32], S[64];// Signature
|
||
unsigned char Ppub[128], dSA[64];
|
||
|
||
unsigned char std_h[32] = {0x82, 0x3C, 0x4B, 0x21, 0xE4, 0xBD, 0x2D, 0xFE, 0x1E, 0xD9, 0x2C, 0x60, 0x66, 0x53, 0xE9, 0x96,
|
||
0x66, 0x85, 0x63, 0x15, 0x2F, 0xC3, 0x3F, 0x55, 0xD7, 0xBF, 0xBB, 0x9B, 0xD9, 0x70, 0x5A, 0xDB};
|
||
unsigned char std_S[64] = {0x73, 0xBF, 0x96, 0x92, 0x3C, 0xE5, 0x8B, 0x6A, 0xD0, 0xE1, 0x3E, 0x96, 0x43, 0xA4, 0x06, 0xD8,
|
||
0xEB, 0x98, 0x41, 0x7C, 0x50, 0xEF, 0x1B, 0x29, 0xCE, 0xF9, 0xAD, 0xB4, 0x8B, 0x6D, 0x59, 0x8C,
|
||
0x85, 0x67, 0x12, 0xF1, 0xC2, 0xE0, 0x96, 0x8A, 0xB7, 0x76, 0x9F, 0x42, 0xA9, 0x95, 0x86, 0xAE,
|
||
0xD1, 0x39, 0xD5, 0xB8, 0xB3, 0xE1, 0x58, 0x91, 0x82, 0x7C, 0xC2, 0xAC, 0xED, 0x9B, 0xAA, 0x05};
|
||
unsigned char std_Ppub[128] = {0x9F, 0x64, 0x08, 0x0B, 0x30, 0x84, 0xF7, 0x33, 0xE4, 0x8A, 0xFF, 0x4B, 0x41, 0xB5, 0x65, 0x01,
|
||
0x1C, 0xE0, 0x71, 0x1C, 0x5E, 0x39, 0x2C, 0xFB, 0x0A, 0xB1, 0xB6, 0x79, 0x1B, 0x94, 0xC4, 0x08,
|
||
0x29, 0xDB, 0xA1, 0x16, 0x15, 0x2D, 0x1F, 0x78, 0x6C, 0xE8, 0x43, 0xED, 0x24, 0xA3, 0xB5, 0x73,
|
||
0x41, 0x4D, 0x21, 0x77, 0x38, 0x6A, 0x92, 0xDD, 0x8F, 0x14, 0xD6, 0x56, 0x96, 0xEA, 0x5E, 0x32,
|
||
0x69, 0x85, 0x09, 0x38, 0xAB, 0xEA, 0x01, 0x12, 0xB5, 0x73, 0x29, 0xF4, 0x47, 0xE3, 0xA0, 0xCB,
|
||
0xAD, 0x3E, 0x2F, 0xDB, 0x1A, 0x77, 0xF3, 0x35, 0xE8, 0x9E, 0x14, 0x08, 0xD0, 0xEF, 0x1C, 0x25,
|
||
0x41, 0xE0, 0x0A, 0x53, 0xDD, 0xA5, 0x32, 0xDA, 0x1A, 0x7C, 0xE0, 0x27, 0xB7, 0xA4, 0x6F, 0x74,
|
||
0x10, 0x06, 0xE8,0x5F,0x5C,0xDF,0xF0,0x73,0x0E,0x75,0xC0,0x5F,0xB4,0xE3,0x21, 0x6D};
|
||
unsigned char std_dSA[64] = {0xA5, 0x70, 0x2F, 0x05, 0xCF, 0x13, 0x15, 0x30, 0x5E, 0x2D, 0x6E, 0xB6, 0x4B, 0x0D, 0xEB, 0x92,
|
||
0x3D, 0xB1, 0xA0, 0xBC, 0xF0, 0xCA, 0xFF, 0x90, 0x52, 0x3A, 0xC8, 0x75, 0x4A, 0xA6, 0x98, 0x20,
|
||
0x78, 0x55, 0x9A, 0x84, 0x44, 0x11, 0xF9, 0x82, 0x5C, 0x10, 0x9F, 0x5E, 0xE3, 0xF5, 0x2D, 0x72,
|
||
0x0D, 0xD0, 0x17, 0x85, 0x39, 0x2A, 0x72, 0x7B, 0xB1, 0x55, 0x69, 0x52, 0xB2, 0xB0, 0x13, 0xD3};
|
||
|
||
unsigned char hid[] = {0x01};
|
||
unsigned char *IDA = "Alice";
|
||
unsigned char *message = "Chinese IBS standard";//the message to be signed
|
||
int mlen = strlen(message), tmp;//the length of message
|
||
big ks;
|
||
|
||
tmp = SM9_standard_init();
|
||
|
||
if(tmp != 0)
|
||
return tmp;
|
||
ks = mirvar(0);
|
||
|
||
bytes_to_big(32, dA, ks);
|
||
|
||
printf("\n*********************** SM9 key Generation ***************************\n");
|
||
tmp = SM9_standard_generatesignkey(hid, IDA, strlen(IDA), ks, Ppub, dSA);
|
||
if(tmp != 0)
|
||
return tmp;
|
||
if(memcmp(Ppub, std_Ppub, 128) != 0)
|
||
return SM9_GEPUB_ERR;
|
||
if(memcmp(dSA, std_dSA, 64) != 0)
|
||
return SM9_GEPRI_ERR;
|
||
|
||
printf("\n********************** SM9 signature algorithm***************************\n");
|
||
tmp = SM9_standard_sign(hid, IDA, message, mlen, rand, dSA, Ppub, h, S);
|
||
if(tmp != 0)
|
||
return tmp;
|
||
if(memcmp(h, std_h, 32) != 0)
|
||
return SM9_SIGN_ERR;
|
||
if(memcmp(S, std_S, 64) != 0)
|
||
return SM9_SIGN_ERR;
|
||
printf("\n******************* SM9 verification algorithm *************************\n");
|
||
tmp = SM9_standard_verify(h, S, hid, IDA, message, mlen, Ppub);
|
||
if(tmp != 0)
|
||
return tmp;
|
||
|
||
return 0;
|
||
}
|