mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-07 00:46:17 +08:00
654 lines
13 KiB
JavaScript
654 lines
13 KiB
JavaScript
/*
|
|
* Copyright (c) 2014 - 2020 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.
|
|
*/
|
|
|
|
|
|
const SM2_P = [
|
|
0xffff, 0xffff, 0xffff, 0xffff,
|
|
0x0000, 0x0000, 0xffff, 0xffff,
|
|
0xffff, 0xffff, 0xffff, 0xffff,
|
|
0xffff, 0xffff, 0xfffe, 0xffff,
|
|
];
|
|
|
|
const SM2_B = [
|
|
0x0e93, 0x4d94, 0xbd41, 0xddbc,
|
|
0x8f92, 0x15ab, 0x89f5, 0xf397,
|
|
0x09a7, 0xcf65, 0x9e4b, 0x4d5a,
|
|
0x5e34, 0x9d9f, 0xfa9e, 0x28e9,
|
|
];
|
|
|
|
const SM2_G = {
|
|
X : [
|
|
0x74c7, 0x334c, 0x4589, 0x715a,
|
|
0x0be1, 0xf266, 0x0bbf, 0x8fe3,
|
|
0xc994, 0x6a39, 0x0446, 0x5f99,
|
|
0x8119, 0x1f19, 0xae2c, 0x32c4],
|
|
|
|
Y : [
|
|
0xf0a0, 0x2139, 0x32e5, 0x02df,
|
|
0x4740, 0xc62a, 0x877c, 0xd0a9,
|
|
0x2153, 0x6b69, 0xcee3, 0x59bd,
|
|
0x779c, 0xf4f6, 0x36a2, 0xbc37],
|
|
|
|
Z: [
|
|
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
};
|
|
|
|
const SM2_N = [
|
|
0x4123, 0x39d5, 0xf409, 0x53bb,
|
|
0x052b, 0x21c6, 0xdf6b, 0x7203,
|
|
0xffff, 0xffff, 0xffff, 0xffff,
|
|
0xffff, 0xffff, 0xfffe, 0xffff,
|
|
];
|
|
|
|
function bn_new() {
|
|
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
}
|
|
|
|
function bn_free(a) {
|
|
bn_set_zero(a);
|
|
delete a;
|
|
}
|
|
|
|
function bn_is_zero(a) {
|
|
for (var i = 0; i < 16; i++) {
|
|
if (a[i] != 0)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
function bn_is_one(a) {
|
|
if (a[0] != 1)
|
|
return 0;
|
|
for (var i = 1; i < 16; i++) {
|
|
if (a[i] != 0)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
function bn_to_bytes(a, buf, offset) {
|
|
for (var i = 15; i >= 0; i--) {
|
|
buf[offset++] = Math.floor(a[i]/256);
|
|
buf[offset++] = a[i] % 256;
|
|
}
|
|
}
|
|
|
|
function bn_set_bytes(a, buf, offset) {
|
|
for (var i = 15; i >= 0; i--) {
|
|
a[i] = buf[offset++] * 256;
|
|
a[i] += buf[offset++];
|
|
}
|
|
}
|
|
|
|
function bn_cmp(a, b) {
|
|
for (var i = 15; i >= 0; i--) {
|
|
if (a[i] > b[i])
|
|
return 1;
|
|
if (a[i] < b[i])
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function bn_set_word(a, word) {
|
|
a[0] = word;
|
|
for (var i = 1; i < 16; i++) {
|
|
a[i] = 0;
|
|
}
|
|
}
|
|
|
|
function bn_set_zero(a) {
|
|
bn_set_word(a, 0);
|
|
}
|
|
|
|
function bn_set_one(a) {
|
|
bn_set_word(a, 1);
|
|
}
|
|
|
|
function bn_copy(r, a) {
|
|
for (var i = 0; i < 16; i++) {
|
|
r[i] = a[i];
|
|
}
|
|
}
|
|
|
|
function bn_to_bits(a) {
|
|
var bits = new Array(256);
|
|
for (var i = 0; i < 16; i++) {
|
|
var w = a[i];
|
|
for (var j = 0; j < 16; j++) {
|
|
bits[i*16 + j] = w % 2;
|
|
w = Math.floor(w/2);
|
|
}
|
|
}
|
|
return bits.reverse();
|
|
}
|
|
|
|
function bn_add(r, a, b) {
|
|
r[0] = a[0] + b[0];
|
|
for (var i = 1; i < 16; i++) {
|
|
r[i] = a[i] + b[i] + Math.floor(r[i-1] / 65536);
|
|
}
|
|
for (var i = 0; i < 15; i++) {
|
|
r[i] %= 65536;
|
|
}
|
|
}
|
|
|
|
function bn_sub(r, a, b) {
|
|
var borrow = 0;
|
|
for (var i = 0; i < 16; i++) {
|
|
r[i] = a[i] - b[i] - borrow;
|
|
borrow = 0;
|
|
if (r[i] < 0) {
|
|
r[i] += 65536;
|
|
borrow = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function fp_add(r, a, b) {
|
|
bn_add(r, a, b);
|
|
if (bn_cmp(r, SM2_P) >= 0) {
|
|
return bn_sub(r, r, SM2_P);
|
|
}
|
|
}
|
|
|
|
function fp_sub(r, a, b) {
|
|
if (bn_cmp(a, b) >= 0) {
|
|
bn_sub(r, a, b);
|
|
} else {
|
|
// FIXME: remove t,
|
|
// it need there is no fp_sub(b, a, b)
|
|
// which is used in point_double()
|
|
var t = bn_new();
|
|
bn_add(t, a, SM2_P);
|
|
bn_sub(r, t, b);
|
|
}
|
|
}
|
|
|
|
function fp_dbl(r, a) {
|
|
return fp_add(r, a, a);
|
|
}
|
|
|
|
function fp_tri(r, a) {
|
|
var t = bn_new();
|
|
fp_dbl(t, a);
|
|
fp_add(r, t, a);
|
|
}
|
|
|
|
function fp_div2(r, a) {
|
|
bn_copy(r, a);
|
|
if (r[0] % 2) {
|
|
bn_add(r, r, SM2_P);
|
|
}
|
|
|
|
var i;
|
|
for (i = 0; i < 15; i++) {
|
|
r[i] = Math.floor(r[i] / 2);
|
|
r[i] += (r[i + 1] % 2) * 32768;
|
|
}
|
|
r[i] = Math.floor(r[i] / 2);
|
|
}
|
|
|
|
function fp_neg(r, a) {
|
|
if (bn_is_zero(a)) {
|
|
bn_set_zero(r);
|
|
} else {
|
|
bn_sub(r, SM2_P, a);
|
|
}
|
|
}
|
|
|
|
function fp_mul(r, a, b) {
|
|
var ab = [
|
|
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,
|
|
]
|
|
for (var i = 0; i < 16; i++) {
|
|
for (var j = 0; j < 16; j++) {
|
|
ab[i + j] += a[i] * b[j];
|
|
}
|
|
}
|
|
for (var i = 0; i < 31; i++) {
|
|
ab[i + 1] += Math.floor(ab[i] / 65536);
|
|
ab[i] = ab[i] % 65536;
|
|
}
|
|
s = ab.slice(16, 32);
|
|
|
|
r[ 0] = ab[ 0] + s[0] + s[ 2] + s[ 4] + s[ 6] + s[ 8] + 2 * (s[10] + s[12] + s[14]);
|
|
r[ 1] = ab[ 1] + s[1] + s[ 3] + s[ 5] + s[ 7] + s[ 9] + 2 * (s[11] + s[13] + s[15]);
|
|
r[ 2] = ab[ 2] + s[2] + s[ 4] + s[ 6] + s[ 8] + s[10] + 2 * (s[12] + s[14]);
|
|
r[ 3] = ab[ 3] + s[3] + s[ 5] + s[ 7] + s[ 9] + s[11] + 2 * (s[13] + s[15]);
|
|
r[ 4] = ab[ 4];
|
|
r[ 5] = ab[ 5];
|
|
r[ 6] = ab[ 6] + s[0] + s[ 6] + s[ 8] + s[12] + s[14] + 2 * s[10];
|
|
r[ 7] = ab[ 7] + s[1] + s[ 7] + s[ 9] + s[13] + s[15] + 2 * s[11];
|
|
r[ 8] = ab[ 8] + s[2] + s[ 8] + s[10] + s[14] + 2 * s[12];
|
|
r[ 9] = ab[ 9] + s[3] + s[ 9] + s[11] + s[15] + 2 * s[13];
|
|
r[10] = ab[10] + s[4] + s[10] + s[12] + 2 * s[14];
|
|
r[11] = ab[11] + s[5] + s[11] + s[13] + 2 * s[15];
|
|
r[12] = ab[12] + s[6] + s[12] + s[14];
|
|
r[13] = ab[13] + s[7] + s[13] + s[15];
|
|
r[14] = ab[14] + s[0] + s[ 2] + s[ 4] + s[ 6] + s[14] + 2 * (s[8] + s[10] + s[12] + s[14]);
|
|
r[15] = ab[15] + s[1] + s[ 3] + s[ 5] + s[ 7] + s[15] + 2 * (s[9] + s[11] + s[13] + s[15]);
|
|
|
|
for (var i = 0; i < 15; i++) {
|
|
r[i + 1] += Math.floor(r[i] / 65536);
|
|
r[i] %= 65536
|
|
}
|
|
|
|
var d = [0,0,0,0,s[0]+s[2]+s[10]+s[12],s[1]+s[3]+s[11]+s[13],0,0,0,0,0,0,0,0,0,0];
|
|
for (var i = 0; i < 15; i++) {
|
|
d[i + 1] += Math.floor(d[i] / 65536);
|
|
d[i] %= 65536
|
|
}
|
|
|
|
bn_sub(r, r, d);
|
|
|
|
while (bn_cmp(r, SM2_P) >= 0) {
|
|
bn_sub(r, r, SM2_P);
|
|
}
|
|
}
|
|
|
|
function fp_sqr(r, a) {
|
|
fp_mul(r, a, a);
|
|
}
|
|
|
|
function fp_inv(r, a) {
|
|
var a1 = bn_new();
|
|
var a2 = bn_new();
|
|
var a3 = bn_new();
|
|
var a4 = bn_new();
|
|
var a5 = bn_new();
|
|
|
|
fp_sqr(a1, a);
|
|
fp_mul(a2, a1, a);
|
|
fp_sqr(a3, a2);
|
|
fp_sqr(a3, a3);
|
|
fp_mul(a3, a3, a2);
|
|
fp_sqr(a4, a3);
|
|
fp_sqr(a4, a4);
|
|
fp_sqr(a4, a4);
|
|
fp_sqr(a4, a4);
|
|
fp_mul(a4, a4, a3);
|
|
fp_sqr(a5, a4);
|
|
for (i = 1; i < 8; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a5, a5, a4);
|
|
for (i = 0; i < 8; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a5, a5, a4);
|
|
for (i = 0; i < 4; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a5, a5, a3);
|
|
fp_sqr(a5, a5);
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a5, a5, a2);
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a5, a5, a);
|
|
fp_sqr(a4, a5);
|
|
fp_mul(a3, a4, a1);
|
|
fp_sqr(a5, a4);
|
|
for (i = 1; i< 31; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a4, a5, a4);
|
|
fp_sqr(a4, a4);
|
|
fp_mul(a4, a4, a);
|
|
fp_mul(a3, a4, a2);
|
|
for (i = 0; i < 33; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a2, a5, a3);
|
|
fp_mul(a3, a2, a3);
|
|
for (i = 0; i < 32; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a2, a5, a3);
|
|
fp_mul(a3, a2, a3);
|
|
fp_mul(a4, a2, a4);
|
|
for (i = 0; i < 32; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a2, a5, a3);
|
|
fp_mul(a3, a2, a3);
|
|
fp_mul(a4, a2, a4);
|
|
for (i = 0; i < 32; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a2, a5, a3);
|
|
fp_mul(a3, a2, a3);
|
|
fp_mul(a4, a2, a4);
|
|
for (i = 0; i < 32; i++)
|
|
fp_sqr(a5, a5);
|
|
fp_mul(a2, a5, a3);
|
|
fp_mul(a3, a2, a3);
|
|
fp_mul(a4, a2, a4);
|
|
for (i = 0; i < 32; i++)
|
|
fp_sqr(a5, a5)
|
|
fp_mul(r, a4, a5);
|
|
|
|
bn_free(a1);
|
|
bn_free(a2);
|
|
bn_free(a3);
|
|
bn_free(a4);
|
|
bn_free(a5);
|
|
}
|
|
|
|
function sm2_point_new() {
|
|
var point = {
|
|
X : [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
Y : [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
Z : [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
}
|
|
return point;
|
|
}
|
|
|
|
function sm2_point_free(P) {
|
|
bn_set_zero(P.X);
|
|
bn_set_zero(P.Y);
|
|
bn_set_zero(P.Z);
|
|
delete P;
|
|
}
|
|
|
|
function sm2_point_copy(R, P) {
|
|
bn_copy(R.X, P.X);
|
|
bn_copy(R.Y, P.Y);
|
|
bn_copy(R.Z, P.Z);
|
|
}
|
|
|
|
function sm2_point_is_at_infinity(P) {
|
|
return bn_is_zero(P.Z);
|
|
}
|
|
|
|
function sm2_point_set_infinity(R) {
|
|
bn_set_one(R.X);
|
|
bn_set_one(R.Y);
|
|
bn_set_zero(R.Z);
|
|
}
|
|
|
|
function sm2_point_get_affine(R, P) {
|
|
sm2_point_copy(R, P);
|
|
if (bn_is_zero(R.Z) || bn_is_one(R.Z))
|
|
return;
|
|
fp_inv(R.Z, R.Z);
|
|
fp_mul(R.Y, R.Y, R.Z);
|
|
fp_sqr(R.Z, R.Z);
|
|
fp_mul(R.X, R.X, R.Z);
|
|
fp_mul(R.Y, R.Y, R.Z);
|
|
bn_set_one(R.Z);
|
|
}
|
|
|
|
function sm2_point_set_bytes(P, buf, offset) {
|
|
bn_set_bytes(P.X, buf, offset);
|
|
bn_set_bytes(P.Y, buf, offset + 32);
|
|
bn_set_one(P.Z);
|
|
}
|
|
|
|
function sm2_point_to_bytes(P, buf, offset) {
|
|
var A = sm2_point_new();
|
|
sm2_point_get_affine(A, P);
|
|
bn_to_bytes(A.X, buf, offset);
|
|
bn_to_bytes(A.Y, buf, offset + 32);
|
|
}
|
|
|
|
function sm2_point_is_on_curve(P) {
|
|
var t0 = bn_new();
|
|
var t1 = bn_new();
|
|
var t2 = bn_new();
|
|
|
|
if (bn_is_one(P.Z)) {
|
|
fp_sqr(t0, P.Y);
|
|
fp_add(t0, t0, P.X);
|
|
fp_add(t0, t0, P.X);
|
|
fp_add(t0, t0, P.X);
|
|
fp_sqr(t1, P.X);
|
|
fp_mul(t1, t1, P.X);
|
|
fp_add(t1, t1, SM2_B);
|
|
} else {
|
|
fp_sqr(t0, P.Y);
|
|
fp_sqr(t1, P.Z);
|
|
fp_sqr(t2, t1);
|
|
fp_mul(t1, t1, t2);
|
|
fp_mul(t1, t1, SM2_B);
|
|
fp_mul(t2, t2, P.X);
|
|
fp_add(t0, t0, t2);
|
|
fp_add(t0, t0, t2);
|
|
fp_add(t0, t0, t2);
|
|
fp_sqr(t2, P.X);
|
|
fp_mul(t2, t2, P.X);
|
|
fp_add(t1, t1, t2);
|
|
}
|
|
|
|
return (bn_cmp(t0, t1) == 0);
|
|
}
|
|
|
|
function sm2_point_neg(R, P) {
|
|
bn_copy(R.X, P.X);
|
|
fp_neg(R.Y, P.Y);
|
|
bn_copy(R.Z, P.Z);
|
|
}
|
|
|
|
function sm2_point_double(R, P) {
|
|
if (sm2_point_is_at_infinity(P)) {
|
|
return sm2_point_copy(R, P);
|
|
}
|
|
var X1 = P.X;
|
|
var Y1 = P.Y;
|
|
var Z1 = P.Z;
|
|
var T1 = bn_new();
|
|
var T2 = bn_new();
|
|
var T3 = bn_new();
|
|
var X3 = bn_new();
|
|
var Y3 = bn_new();
|
|
var Z3 = bn_new();
|
|
|
|
fp_sqr(T1, Z1);
|
|
fp_sub(T2, X1, T1);
|
|
fp_add(T1, X1, T1);
|
|
fp_mul(T2, T2, T1);
|
|
fp_tri(T2, T2);
|
|
fp_dbl(Y3, Y1);
|
|
fp_mul(Z3, Y3, Z1);
|
|
fp_sqr(Y3, Y3);
|
|
fp_mul(T3, Y3, X1);
|
|
fp_sqr(Y3, Y3);
|
|
fp_div2(Y3, Y3);
|
|
fp_sqr(X3, T2);
|
|
fp_dbl(T1, T3);
|
|
fp_sub(X3, X3, T1);
|
|
fp_sub(T1, T3, X3);
|
|
fp_mul(T1, T1, T2);
|
|
fp_sub(Y3, T1, Y3);
|
|
|
|
bn_copy(R.X, X3);
|
|
bn_copy(R.Y, Y3);
|
|
bn_copy(R.Z, Z3);
|
|
}
|
|
|
|
function sm2_point_add(R, P, Q) {
|
|
if (sm2_point_is_at_infinity(Q)) {
|
|
sm2_point_copy(R, P);
|
|
return;
|
|
}
|
|
if (sm2_point_is_at_infinity(P)) {
|
|
sm2_point_copy(R, Q);
|
|
return;
|
|
}
|
|
|
|
var X1 = P.X;
|
|
var Y1 = P.Y;
|
|
var Z1 = P.Z;
|
|
var x2 = Q.X;
|
|
var y2 = Q.Y;
|
|
var T1 = bn_new();
|
|
var T2 = bn_new();
|
|
var T3 = bn_new();
|
|
var T4 = bn_new();
|
|
var X3 = bn_new();
|
|
var Y3 = bn_new();
|
|
var Z3 = bn_new();
|
|
|
|
fp_sqr(T1, Z1);
|
|
fp_mul(T2, T1, Z1);
|
|
fp_mul(T1, T1, x2);
|
|
fp_mul(T2, T2, y2);
|
|
fp_sub(T1, T1, X1);
|
|
fp_sub(T2, T2, Y1);
|
|
if (bn_is_zero(T1)) {
|
|
if (bn_is_zero(T2)) {
|
|
return sm2_point_double(R, Q);
|
|
} else {
|
|
return sm2_point_set_infinity(R);
|
|
}
|
|
}
|
|
fp_mul(Z3, Z1, T1);
|
|
fp_sqr(T3, T1);
|
|
fp_mul(T4, T3, T1);
|
|
fp_mul(T3, T3, X1);
|
|
fp_dbl(T1, T3);
|
|
fp_sqr(X3, T2);
|
|
fp_sub(X3, X3, T1);
|
|
fp_sub(X3, X3, T4);
|
|
fp_sub(T3, T3, X3);
|
|
fp_mul(T3, T3, T2);
|
|
fp_mul(T4, T4, Y1);
|
|
fp_sub(Y3, T3, T4);
|
|
|
|
bn_copy(R.X, X3);
|
|
bn_copy(R.Y, Y3);
|
|
bn_copy(R.Z, Z3);
|
|
}
|
|
|
|
function sm2_point_mul(R, k, P) {
|
|
var bits = bn_to_bits(k);
|
|
var Q = sm2_point_new();
|
|
|
|
for (var i = 0; i < bits.length; i++) {
|
|
sm2_point_double(Q, Q);
|
|
|
|
if (bits[i] == 1) {
|
|
sm2_point_add(Q, Q, P);
|
|
}
|
|
}
|
|
sm2_point_copy(R, Q);
|
|
}
|
|
|
|
function sm2_point_mul_G(R, k) {
|
|
return sm2_point_mul(R, k, SM2_G);
|
|
}
|
|
|
|
|
|
function sm2_sig_new() {
|
|
var sig = {
|
|
r: bn_new(),
|
|
s: bn_new(),
|
|
};
|
|
return sig;
|
|
}
|
|
|
|
function sm2_do_verify(dgst, sig, P) {
|
|
|
|
if (dgst.length < 32
|
|
|| bn_is_zero(sig.r)
|
|
|| bn_cmp(sig.r, SM2_N) >= 0
|
|
|| bn_is_zero(sig.s)
|
|
|| bn_cmp(sig.s, SM2_N) >= 0) {
|
|
return false;
|
|
}
|
|
|
|
var e = bn_new();
|
|
|
|
bn_set_bytes(e, dgst, 0);
|
|
if (bn_cmp(e, SM2_N) >= 0) {
|
|
bn_sub(e, e, SM2_N);
|
|
}
|
|
|
|
var t = bn_new();
|
|
bn_add(t, sig.r, sig.s);
|
|
if (bn_cmp(t, SM2_N) == 0) {
|
|
return false;
|
|
}
|
|
|
|
var Q1 = sm2_point_new();
|
|
var Q2 = sm2_point_new();
|
|
|
|
sm2_point_mul_G(Q1, s1);
|
|
sm2_point_mul(Q2, t, P);
|
|
sm2_point_add(Q1, Q1, Q2);
|
|
sm2_point_get_affine(Q1, Q1);
|
|
|
|
bn_add(e, e, Q1.X);
|
|
if (bn_cmp(e, SM2_N)) {
|
|
bn_sub(e, e, SM2_N);
|
|
}
|
|
if (bn_cmp(e, SM2_N)) {
|
|
bn_sub(e, e, SM2_N);
|
|
}
|
|
|
|
return bn_cmp(e, sig.r) == 0;
|
|
}
|
|
|
|
function sm2_point_test() {
|
|
|
|
var P = sm2_point_new();
|
|
|
|
/*
|
|
sm2_point_double(P, SM2_G);
|
|
sm2_point_double(P, P);
|
|
sm2_point_add(P, P, SM2_G);
|
|
sm2_point_get_affine(P, P);
|
|
console.log(P);
|
|
*/
|
|
|
|
var k = bn_new();
|
|
bn_set_word(k, 11);
|
|
|
|
console.log("mul");
|
|
sm2_point_mul(P, SM2_B, SM2_G);
|
|
sm2_point_get_affine(P, P);
|
|
|
|
console.log(P.X);
|
|
console.log(P.Y);
|
|
console.log(P.Z);
|
|
}
|