mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-07 00:46:17 +08:00
Update SM2
This commit is contained in:
@@ -539,10 +539,17 @@ int sm2_fp_sqrt(SM2_Fp r, const SM2_Fp a)
|
||||
SM2_BN u;
|
||||
SM2_BN y; // temp result, prevent call sm2_fp_sqrt(a, a)
|
||||
|
||||
printf("sm2_fp_sqrt\n");
|
||||
sm2_bn_print(stderr, 0, 4, "a", a);
|
||||
|
||||
// r = a^((p + 1)/4) when p = 3 (mod 4)
|
||||
sm2_bn_add(u, SM2_P, SM2_ONE);
|
||||
sm2_bn_rshift(u, u, 2);
|
||||
|
||||
sm2_bn_print(stderr, 0, 4, "u", u);
|
||||
|
||||
sm2_fp_exp(y, a, u);
|
||||
sm2_bn_print(stderr, 0, 4, "y", y);
|
||||
|
||||
// check r^2 == a
|
||||
sm2_fp_sqr(u, y);
|
||||
@@ -1087,6 +1094,7 @@ int sm2_point_is_at_infinity(const SM2_POINT *P)
|
||||
return mem_is_zero((uint8_t *)P, sizeof(SM2_POINT));
|
||||
}
|
||||
|
||||
// 这个函数和 sm2_z256_point_from_x_bytes 不一样
|
||||
int sm2_point_from_x(SM2_POINT *P, const uint8_t x[32], int y)
|
||||
{
|
||||
SM2_BN _x, _y, _g, _z;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm2_z256.h>
|
||||
#include <gmssl/sm3.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
@@ -22,11 +23,19 @@
|
||||
|
||||
int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!ctx || !key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->key = *key;
|
||||
|
||||
// d' = (d + 1)^-1 (mod n)
|
||||
sm2_z256_from_bytes(ctx->sign_key, key->private_key);
|
||||
sm2_z256_modn_add(ctx->sign_key, ctx->sign_key, sm2_z256_one());
|
||||
sm2_z256_modn_inv(ctx->sign_key, ctx->sign_key);
|
||||
|
||||
sm3_init(&ctx->sm3_ctx);
|
||||
|
||||
if (id) {
|
||||
@@ -38,6 +47,24 @@ int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t
|
||||
sm2_compute_z(z, &key->public_key, id, idlen);
|
||||
sm3_update(&ctx->sm3_ctx, z, sizeof(z));
|
||||
}
|
||||
|
||||
ctx->inited_sm3_ctx = ctx->sm3_ctx;
|
||||
|
||||
// pre compute (k, x = [k]G.x)
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (sm2_do_sign_pre_compute(ctx->pre_comp[i].k, ctx->pre_comp[i].x1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->num_pre_comp = 32;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_sign_ctx_reset(SM2_SIGN_CTX *ctx)
|
||||
{
|
||||
ctx->sm3_ctx = ctx->inited_sm3_ctx;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -56,16 +83,39 @@ int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
||||
{
|
||||
uint8_t dgst[SM3_DIGEST_SIZE];
|
||||
SM2_SIGNATURE signature;
|
||||
|
||||
if (!ctx || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm3_finish(&ctx->sm3_ctx, dgst);
|
||||
if (sm2_sign(&ctx->key, dgst, sig, siglen) != 1) {
|
||||
|
||||
if (ctx->num_pre_comp == 0) {
|
||||
size_t i;
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (sm2_do_sign_pre_compute(ctx->pre_comp[i].k, ctx->pre_comp[i].x1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->num_pre_comp = 32;
|
||||
}
|
||||
|
||||
ctx->num_pre_comp--;
|
||||
if (sm2_do_sign_fast_ex(ctx->sign_key,
|
||||
ctx->pre_comp[ctx->num_pre_comp].k, ctx->pre_comp[ctx->num_pre_comp].x1,
|
||||
dgst, &signature) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
*siglen = 0;
|
||||
if (sm2_signature_to_der(&signature, &sig, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -93,6 +143,9 @@ int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->key.public_key = key->public_key;
|
||||
|
||||
sm2_z256_point_from_bytes(&ctx->public_key, (const uint8_t *)&key->public_key);
|
||||
|
||||
sm3_init(&ctx->sm3_ctx);
|
||||
|
||||
if (id) {
|
||||
@@ -104,6 +157,9 @@ int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_
|
||||
sm2_compute_z(z, &key->public_key, id, idlen);
|
||||
sm3_update(&ctx->sm3_ctx, z, sizeof(z));
|
||||
}
|
||||
|
||||
ctx->inited_sm3_ctx = ctx->sm3_ctx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -135,9 +191,6 @@ int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int sm2_encrypt_init(SM2_ENC_CTX *ctx, const SM2_KEY *sm2_key)
|
||||
{
|
||||
if (!ctx || !sm2_key) {
|
||||
|
||||
282
src/sm2_point.c
Normal file
282
src/sm2_point.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm2_z256.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
int sm2_point_is_on_curve(const SM2_POINT *P)
|
||||
{
|
||||
SM2_Z256_POINT T;
|
||||
sm2_z256_point_from_bytes(&T, (const uint8_t *)P);
|
||||
|
||||
if (sm2_z256_point_is_on_curve(&T) == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int sm2_point_is_at_infinity(const SM2_POINT *P)
|
||||
{
|
||||
return mem_is_zero((uint8_t *)P, sizeof(SM2_POINT));
|
||||
}
|
||||
|
||||
int sm2_point_from_x(SM2_POINT *P, const uint8_t x[32], int y_is_odd)
|
||||
{
|
||||
|
||||
SM2_Z256_POINT T;
|
||||
|
||||
if (sm2_z256_point_from_x_bytes(&T, x, y_is_odd) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_z256_point_to_bytes(&T, (uint8_t *)P);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_from_xy(SM2_POINT *P, const uint8_t x[32], const uint8_t y[32])
|
||||
{
|
||||
memcpy(P->x, x, 32);
|
||||
memcpy(P->y, y, 32);
|
||||
return sm2_point_is_on_curve(P);
|
||||
}
|
||||
|
||||
int sm2_point_add(SM2_POINT *R, const SM2_POINT *P, const SM2_POINT *Q)
|
||||
{
|
||||
SM2_Z256_POINT P_;
|
||||
SM2_Z256_POINT Q_;
|
||||
|
||||
sm2_z256_point_from_bytes(&P_, (uint8_t *)P);
|
||||
sm2_z256_point_from_bytes(&Q_, (uint8_t *)Q);
|
||||
sm2_z256_point_add(&P_, &P_, &Q_);
|
||||
sm2_z256_point_to_bytes(&P_, (uint8_t *)R);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_sub(SM2_POINT *R, const SM2_POINT *P, const SM2_POINT *Q)
|
||||
{
|
||||
SM2_Z256_POINT P_;
|
||||
SM2_Z256_POINT Q_;
|
||||
|
||||
sm2_z256_point_from_bytes(&P_, (uint8_t *)P);
|
||||
sm2_z256_point_from_bytes(&Q_, (uint8_t *)Q);
|
||||
sm2_z256_point_sub(&P_, &P_, &Q_);
|
||||
sm2_z256_point_to_bytes(&P_, (uint8_t *)R);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_neg(SM2_POINT *R, const SM2_POINT *P)
|
||||
{
|
||||
SM2_Z256_POINT P_;
|
||||
|
||||
sm2_z256_point_from_bytes(&P_, (uint8_t *)P);
|
||||
sm2_z256_point_neg(&P_, &P_);
|
||||
sm2_z256_point_to_bytes(&P_, (uint8_t *)R);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_dbl(SM2_POINT *R, const SM2_POINT *P)
|
||||
{
|
||||
SM2_Z256_POINT P_;
|
||||
|
||||
sm2_z256_point_from_bytes(&P_, (uint8_t *)P);
|
||||
sm2_z256_point_dbl(&P_, &P_);
|
||||
sm2_z256_point_to_bytes(&P_, (uint8_t *)R);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_mul(SM2_POINT *R, const uint8_t k[32], const SM2_POINT *P)
|
||||
{
|
||||
uint64_t _k[4];
|
||||
SM2_Z256_POINT _P;
|
||||
|
||||
sm2_z256_from_bytes(_k, k);
|
||||
sm2_z256_point_from_bytes(&_P, (uint8_t *)P);
|
||||
sm2_z256_point_mul(&_P, _k, &_P);
|
||||
sm2_z256_point_to_bytes(&_P, (uint8_t *)R);
|
||||
|
||||
memset(_k, 0, sizeof(_k));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_mul_generator(SM2_POINT *R, const uint8_t k[32])
|
||||
{
|
||||
uint64_t _k[4];
|
||||
SM2_Z256_POINT _R;
|
||||
|
||||
sm2_z256_from_bytes(_k, k);
|
||||
sm2_z256_point_mul_generator(&_R, _k);
|
||||
sm2_z256_point_to_bytes(&_R, (uint8_t *)R);
|
||||
|
||||
memset(_k, 0, sizeof(_k));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_mul_sum(SM2_POINT *R, const uint8_t k[32], const SM2_POINT *P, const uint8_t s[32])
|
||||
{
|
||||
uint64_t _k[4];
|
||||
SM2_Z256_POINT _P;
|
||||
uint64_t _s[4];
|
||||
|
||||
sm2_z256_from_bytes(_k, k);
|
||||
sm2_z256_point_from_bytes(&_P, (uint8_t *)P);
|
||||
sm2_z256_from_bytes(_s, s);
|
||||
sm2_z256_point_mul_sum(&_P, _k, &_P, _s);
|
||||
sm2_z256_point_to_bytes(&_P, (uint8_t *)R);
|
||||
|
||||
memset(_k, 0, sizeof(_k));
|
||||
memset(_s, 0, sizeof(_s));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_print(FILE *fp, int fmt, int ind, const char *label, const SM2_POINT *P)
|
||||
{
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
format_bytes(fp, fmt, ind, "x", P->x, 32);
|
||||
format_bytes(fp, fmt, ind, "y", P->y, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33])
|
||||
{
|
||||
*out++ = (P->y[31] & 0x01) ? 0x03 : 0x02;
|
||||
memcpy(out, P->x, 32);
|
||||
}
|
||||
|
||||
void sm2_point_to_uncompressed_octets(const SM2_POINT *P, uint8_t out[65])
|
||||
{
|
||||
*out++ = 0x04;
|
||||
memcpy(out, P, 64);
|
||||
}
|
||||
|
||||
int sm2_z256_point_from_octets(SM2_Z256_POINT *P, const uint8_t *in, size_t inlen)
|
||||
{
|
||||
switch (*in) {
|
||||
case SM2_point_at_infinity:
|
||||
if (inlen != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_z256_point_set_infinity(P);
|
||||
break;
|
||||
case SM2_point_compressed_y_even:
|
||||
if (inlen != 33) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_z256_point_from_x_bytes(P, in + 1, 0) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case SM2_point_compressed_y_odd:
|
||||
if (inlen != 33) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_z256_point_from_x_bytes(P, in + 1, 1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case SM2_point_uncompressed:
|
||||
if (inlen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_z256_point_from_bytes(P, in + 1);
|
||||
if (sm2_z256_point_is_on_curve(P) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_from_octets(SM2_POINT *P, const uint8_t *in, size_t inlen)
|
||||
{
|
||||
if ((*in == 0x02 || *in == 0x03) && inlen == 33) {
|
||||
if (sm2_point_from_x(P, in + 1, *in) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (*in == 0x04 && inlen == 65) {
|
||||
if (sm2_point_from_xy(P, in + 1, in + 33) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_to_der(const SM2_POINT *P, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t octets[65];
|
||||
if (!P) {
|
||||
return 0;
|
||||
}
|
||||
sm2_point_to_uncompressed_octets(P, octets);
|
||||
if (asn1_octet_string_to_der(octets, sizeof(octets), out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_from_der(SM2_POINT *P, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if ((ret = asn1_octet_string_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (dlen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_point_from_octets(P, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_point_from_hash(SM2_POINT *R, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
437
src/sm2_z256.c
437
src/sm2_z256.c
@@ -52,6 +52,8 @@
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/endian.h>
|
||||
#include <gmssl/sm2_z256.h>
|
||||
#include <gmssl/sm3.h>
|
||||
|
||||
|
||||
/*
|
||||
SM2 parameters
|
||||
@@ -71,7 +73,10 @@ const uint64_t *sm2_z256_one(void) {
|
||||
return &SM2_Z256_ONE[0];
|
||||
}
|
||||
|
||||
|
||||
void sm2_z256_set_zero(uint64_t a[4])
|
||||
{
|
||||
a[0] = a[1] = a[2] = a[3] = 0;
|
||||
}
|
||||
|
||||
int sm2_z256_rand_range(uint64_t r[4], const uint64_t range[4])
|
||||
{
|
||||
@@ -161,6 +166,23 @@ uint64_t sm2_z256_is_zero(const uint64_t a[4])
|
||||
is_zero(a[3]);
|
||||
}
|
||||
|
||||
void sm2_z256_rshift(uint64_t r[4], const uint64_t a[4], unsigned int nbits)
|
||||
{
|
||||
nbits &= 0x3f;
|
||||
|
||||
if (nbits) {
|
||||
r[0] = a[0] >> nbits;
|
||||
r[0] |= a[1] << (64 - nbits);
|
||||
r[1] = a[1] >> nbits;
|
||||
r[1] |= a[2] << (64 - nbits);
|
||||
r[2] = a[2] >> nbits;
|
||||
r[2] |= a[3] << (64 - nbits);
|
||||
r[3] = a[3] >> nbits;
|
||||
} else {
|
||||
sm2_z256_copy(r, a);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t sm2_z256_add(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
uint64_t t, c = 0;
|
||||
@@ -351,6 +373,9 @@ int sm2_z512_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t
|
||||
const uint64_t SM2_Z256_P[4] = {
|
||||
0xffffffffffffffff, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
// 注意这里 SM2_Z256_P[0] 和 SM2_Z256_P[2] 是特殊值,在汇编中可以根据这个特殊值做特定的实现
|
||||
|
||||
|
||||
|
||||
const uint64_t *sm2_z256_prime(void) {
|
||||
return &SM2_Z256_P[0];
|
||||
@@ -362,6 +387,7 @@ const uint64_t SM2_Z256_NEG_P[4] = {
|
||||
1, ((uint64_t)1 << 32) - 1, 0, ((uint64_t)1 << 32),
|
||||
};
|
||||
|
||||
#ifndef ENABLE_SM2_Z256_ARMV8
|
||||
void sm2_z256_modp_add(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
uint64_t c;
|
||||
@@ -404,6 +430,11 @@ void sm2_z256_modp_mul_by_3(uint64_t r[4], const uint64_t a[4])
|
||||
sm2_z256_modp_add(r, t, a);
|
||||
}
|
||||
|
||||
void sm2_z256_modp_neg(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
(void)sm2_z256_sub(r, SM2_Z256_P, a);
|
||||
}
|
||||
|
||||
void sm2_z256_modp_div_by_2(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
uint64_t c = 0;
|
||||
@@ -422,11 +453,9 @@ void sm2_z256_modp_div_by_2(uint64_t r[4], const uint64_t a[4])
|
||||
r[2] = (r[2] >> 1) | ((r[3] & 1) << 63);
|
||||
r[3] = (r[3] >> 1) | ((c & 1) << 63);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sm2_z256_modp_neg(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
(void)sm2_z256_sub(r, SM2_Z256_P, a);
|
||||
}
|
||||
// p' * p = -1 mod 2^256
|
||||
|
||||
// p' = -p^(-1) mod 2^256
|
||||
// = fffffffc00000001fffffffe00000000ffffffff000000010000000000000001
|
||||
@@ -435,10 +464,12 @@ const uint64_t SM2_Z256_P_PRIME[4] = {
|
||||
0x0000000000000001, 0xffffffff00000001, 0xfffffffe00000000, 0xfffffffc00000001,
|
||||
};
|
||||
|
||||
|
||||
// mont(1) (mod p) = 2^256 mod p = 2^256 - p
|
||||
const uint64_t *SM2_Z256_MODP_MONT_ONE = SM2_Z256_NEG_P;
|
||||
|
||||
// z = xy
|
||||
#ifndef ENABLE_SM2_Z256_ARMV8
|
||||
// z = a*b
|
||||
// c = (z + (z * p' mod 2^256) * p)/2^256
|
||||
void sm2_z256_modp_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
@@ -484,6 +515,24 @@ void sm2_z256_modp_mont_sqr(uint64_t r[4], const uint64_t a[4])
|
||||
sm2_z256_modp_mont_mul(r, a, a);
|
||||
}
|
||||
|
||||
// mont(mont(a), 1) = aR * 1 * R^-1 (mod p) = a (mod p)
|
||||
void sm2_z256_modp_from_mont(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modp_mont_mul(r, a, SM2_Z256_ONE);
|
||||
}
|
||||
|
||||
// 2^512 (mod p)
|
||||
const uint64_t SM2_Z256_2e512modp[4] = {
|
||||
0x0000000200000003, 0x00000002ffffffff, 0x0000000100000001, 0x0000000400000002
|
||||
};
|
||||
|
||||
// mont(a) = a * 2^256 (mod p) = mont_mul(a, 2^512 mod p)
|
||||
void sm2_z256_modp_to_mont(const uint64_t a[4], uint64_t r[4])
|
||||
{
|
||||
sm2_z256_modp_mont_mul(r, a, SM2_Z256_2e512modp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sm2_z256_modp_mont_exp(uint64_t r[4], const uint64_t a[4], const uint64_t e[4])
|
||||
{
|
||||
uint64_t t[4];
|
||||
@@ -589,21 +638,30 @@ void sm2_z256_modp_mont_inv(uint64_t r[4], const uint64_t a[4])
|
||||
sm2_z256_modp_mont_mul(r, a4, a5);
|
||||
}
|
||||
|
||||
// mont(mont(a), 1) = aR * 1 * R^-1 (mod p) = a (mod p)
|
||||
void sm2_z256_modp_from_mont(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modp_mont_mul(r, a, SM2_Z256_ONE);
|
||||
}
|
||||
|
||||
// 2^512 (mod p)
|
||||
const uint64_t SM2_Z256_2e512modp[4] = {
|
||||
0x0000000200000003, 0x00000002ffffffff, 0x0000000100000001, 0x0000000400000002
|
||||
// (p+1)/4 = 3fffffffbfffffffffffffffffffffffffffffffc00000004000000000000000
|
||||
const uint64_t SM2_Z256_SQRT_EXP[4] = {
|
||||
0x4000000000000000, 0xffffffffc0000000, 0xffffffffffffffff, 0x3fffffffbfffffff,
|
||||
};
|
||||
|
||||
// mont(a) = a * 2^256 (mod p) = mont_mul(a, 2^512 mod p)
|
||||
void sm2_z256_modp_to_mont(const uint64_t a[4], uint64_t r[4])
|
||||
// -r (mod p), i.e. (p - r) is also a square root of a
|
||||
int sm2_z256_modp_mont_sqrt(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modp_mont_mul(r, a, SM2_Z256_2e512modp);
|
||||
uint64_t a_[4];
|
||||
uint64_t r_[4]; // temp result, prevent call sm2_fp_sqrt(a, a)
|
||||
|
||||
// r = a^((p + 1)/4) when p = 3 (mod 4)
|
||||
sm2_z256_modp_mont_exp(r_, a, SM2_Z256_SQRT_EXP);
|
||||
|
||||
// check r^2 == a
|
||||
sm2_z256_modp_mont_sqr(a_, r_);
|
||||
if (sm2_z256_cmp(a_, a) != 0) {
|
||||
// not every number has a square root, so it is not an error
|
||||
// `sm2_z256_point_from_hash` need a non-negative return value
|
||||
return 0;
|
||||
}
|
||||
|
||||
sm2_z256_copy(r, r_);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_z256_modp_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4])
|
||||
@@ -621,6 +679,11 @@ const uint64_t SM2_Z256_N[4] = {
|
||||
0x53bbf40939d54123, 0x7203df6b21c6052b, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
|
||||
const uint64_t SM2_Z256_N_MINUS_ONE[4] = {
|
||||
0x53bbf40939d54122, 0x7203df6b21c6052b, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
|
||||
|
||||
// 2^256 - n = 0x10000000000000000000000008dfc2094de39fad4ac440bf6c62abedd
|
||||
const uint64_t SM2_Z256_NEG_N[4] = {
|
||||
0xac440bf6c62abedd, 0x8dfc2094de39fad4, 0x0000000000000000, 0x0000000100000000,
|
||||
@@ -680,6 +743,10 @@ const uint64_t *sm2_z256_order(void) {
|
||||
return &SM2_Z256_N[0];
|
||||
}
|
||||
|
||||
const uint64_t *sm2_z256_order_minus_one(void) {
|
||||
return &SM2_Z256_N_MINUS_ONE[0];
|
||||
}
|
||||
|
||||
|
||||
// mont(1) (mod n) = 2^256 - n
|
||||
const uint64_t *SM2_Z256_MODN_MONT_ONE = SM2_Z256_NEG_N;
|
||||
@@ -784,10 +851,45 @@ void sm2_z256_modn_exp(uint64_t r[4], const uint64_t a[4], const uint64_t e[4])
|
||||
const uint64_t SM2_Z256_N_MINUS_TWO[4] = {
|
||||
0x53bbf40939d54121, 0x7203df6b21c6052b, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
// exp都是从高位开始的,如果都是1的话,那么就是都要平方和乘
|
||||
|
||||
void sm2_z256_modn_mont_inv(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modn_mont_exp(r, a, SM2_Z256_N_MINUS_TWO);
|
||||
// expand sm2_z256_modn_mont_exp(r, a, SM2_Z256_N_MINUS_TWO)
|
||||
uint64_t t[4];
|
||||
uint64_t w;
|
||||
int i;
|
||||
int k = 0;
|
||||
|
||||
sm2_z256_copy(t, a);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
sm2_z256_modn_mont_sqr(t, t);
|
||||
sm2_z256_modn_mont_mul(t, t, a);
|
||||
}
|
||||
sm2_z256_modn_mont_sqr(t, t);
|
||||
for (i = 0; i < 96; i++) {
|
||||
sm2_z256_modn_mont_sqr(t, t);
|
||||
sm2_z256_modn_mont_mul(t, t, a);
|
||||
}
|
||||
w = SM2_Z256_N_MINUS_TWO[1];
|
||||
for (i = 0; i < 64; i++) {
|
||||
sm2_z256_modn_mont_sqr(t, t);
|
||||
if (w & 0x8000000000000000) {
|
||||
sm2_z256_modn_mont_mul(t, t, a);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
w = SM2_Z256_N_MINUS_TWO[0];
|
||||
for (i = 0; i < 64; i++) {
|
||||
sm2_z256_modn_mont_sqr(t, t);
|
||||
if (w & 0x8000000000000000) {
|
||||
sm2_z256_modn_mont_mul(t, t, a);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
|
||||
sm2_z256_copy(r, t);
|
||||
}
|
||||
|
||||
void sm2_z256_modn_inv(uint64_t r[4], const uint64_t a[4])
|
||||
@@ -805,7 +907,6 @@ void sm2_z256_modn_from_mont(uint64_t r[4], const uint64_t a[4])
|
||||
sm2_z256_modn_mont_mul(r, a, SM2_Z256_ONE);
|
||||
}
|
||||
|
||||
|
||||
// 2^512 (mod n) = 0x1eb5e412a22b3d3b620fc84c3affe0d43464504ade6fa2fa901192af7c114f20
|
||||
const uint64_t SM2_Z256_2e512modn[4] = {
|
||||
0x901192af7c114f20, 0x3464504ade6fa2fa, 0x620fc84c3affe0d4, 0x1eb5e412a22b3d3b,
|
||||
@@ -828,11 +929,29 @@ int sm2_z256_modn_mont_print(FILE *fp, int ind, int fmt, const char *label, cons
|
||||
|
||||
// Jacobian Point with Montgomery coordinates
|
||||
|
||||
void sm2_z256_point_set_infinity(SM2_Z256_POINT *P)
|
||||
{
|
||||
sm2_z256_copy(P->X, SM2_Z256_MODP_MONT_ONE);
|
||||
sm2_z256_copy(P->Y, SM2_Z256_MODP_MONT_ONE);
|
||||
sm2_z256_set_zero(P->Z);
|
||||
}
|
||||
|
||||
// 这里还应该检查X == Y == mont(1)
|
||||
// point at infinity should be like (k^2 : k^3 : 0), k in [0, p-1]
|
||||
int sm2_z256_point_is_at_infinity(const SM2_Z256_POINT *P)
|
||||
{
|
||||
if (sm2_z256_is_zero(P->Z)) {
|
||||
uint64_t X_cub[4];
|
||||
uint64_t Y_sqr[4];
|
||||
|
||||
sm2_z256_modp_mont_sqr(X_cub, P->X);
|
||||
sm2_z256_modp_mont_mul(X_cub, X_cub, P->X);
|
||||
sm2_z256_modp_mont_sqr(Y_sqr, P->Y);
|
||||
|
||||
if (sm2_z256_cmp(X_cub, Y_sqr) != 0) {
|
||||
error_print();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -907,6 +1026,34 @@ void sm2_z256_point_get_xy(const SM2_Z256_POINT *P, uint64_t x[4], uint64_t y[4]
|
||||
}
|
||||
}
|
||||
|
||||
// impl with modified jacobian coordinates
|
||||
void sm2_z256_point_dbl_x5(SM2_Z256_POINT *R, const SM2_Z256_POINT *A)
|
||||
|
||||
{
|
||||
sm2_z256_point_dbl(R, A);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
}
|
||||
|
||||
void sm2_z256_point_multi_dbl(SM2_Z256_POINT *R, const SM2_Z256_POINT *P, unsigned int i)
|
||||
{
|
||||
const uint64_t *X1 = P->X;
|
||||
const uint64_t *Y1 = P->Y;
|
||||
const uint64_t *Z1 = P->Z;
|
||||
uint64_t *X3 = R->X;
|
||||
uint64_t *Y3 = R->Y;
|
||||
uint64_t *Z3 = R->Z;
|
||||
uint64_t A[4];
|
||||
uint64_t B[4];
|
||||
uint64_t C[4];
|
||||
uint64_t D[4];
|
||||
uint64_t E[4];
|
||||
|
||||
// A = Z1^2
|
||||
}
|
||||
|
||||
void sm2_z256_point_dbl(SM2_Z256_POINT *R, const SM2_Z256_POINT *A)
|
||||
{
|
||||
const uint64_t *X1 = A->X;
|
||||
@@ -922,77 +1069,75 @@ void sm2_z256_point_dbl(SM2_Z256_POINT *R, const SM2_Z256_POINT *A)
|
||||
|
||||
// S = 2*Y1
|
||||
sm2_z256_modp_mul_by_2(S, Y1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "1", S);
|
||||
|
||||
|
||||
// Zsqr = Z1^2
|
||||
sm2_z256_modp_mont_sqr(Zsqr, Z1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "2", Zsqr);
|
||||
|
||||
// S = S^2 = 4*Y1^2
|
||||
sm2_z256_modp_mont_sqr(S, S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "3", S);
|
||||
|
||||
// Z3 = Z1 * Y1
|
||||
sm2_z256_modp_mont_mul(Z3, Z1, Y1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "4", Z3);
|
||||
|
||||
// Z3 = 2 * Z3 = 2*Y1*Z1
|
||||
sm2_z256_modp_mul_by_2(Z3, Z3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "5", Z3);
|
||||
|
||||
// M = X1 + Zsqr = X1 + Z1^2
|
||||
sm2_z256_modp_add(M, X1, Zsqr);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "6", M);
|
||||
|
||||
// Zsqr = X1 - Zsqr = X1 - Z1^2
|
||||
sm2_z256_modp_sub(Zsqr, X1, Zsqr);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "7", Zsqr);
|
||||
|
||||
// Y3 = S^2 = 16 * Y1^4
|
||||
sm2_z256_modp_mont_sqr(Y3, S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "8", Y3);
|
||||
|
||||
// Y3 = Y3/2 = 8 * Y1^4
|
||||
sm2_z256_modp_div_by_2(Y3, Y3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "9", Y3);
|
||||
|
||||
// M = M * Zsqr = (X1 + Z1^2)(X1 - Z1^2)
|
||||
sm2_z256_modp_mont_mul(M, M, Zsqr);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "10", M);
|
||||
|
||||
// M = 3*M = 3(X1 + Z1^2)(X1 - Z1^2)
|
||||
sm2_z256_modp_mul_by_3(M, M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "11", M);
|
||||
|
||||
// S = S * X1 = 4 * X1 * Y1^2
|
||||
sm2_z256_modp_mont_mul(S, S, X1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "12", S);
|
||||
|
||||
// tmp0 = 2 * S = 8 * X1 * Y1^2
|
||||
sm2_z256_modp_mul_by_2(tmp0, S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "13", tmp0);
|
||||
|
||||
// X3 = M^2 = (3(X1 + Z1^2)(X1 - Z1^2))^2
|
||||
sm2_z256_modp_mont_sqr(X3, M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "14", X3);
|
||||
|
||||
// X3 = X3 - tmp0 = (3(X1 + Z1^2)(X1 - Z1^2))^2 - 8 * X1 * Y1^2
|
||||
sm2_z256_modp_sub(X3, X3, tmp0);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "15", X3);
|
||||
|
||||
// S = S - X3 = 4 * X1 * Y1^2 - X3
|
||||
sm2_z256_modp_sub(S, S, X3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "16", S);
|
||||
|
||||
// S = S * M = 3(X1 + Z1^2)(X1 - Z1^2)(4 * X1 * Y1^2 - X3)
|
||||
sm2_z256_modp_mont_mul(S, S, M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "17", S);
|
||||
|
||||
// Y3 = S - Y3 = 3(X1 + Z1^2)(X1 - Z1^2)(4 * X1 * Y1^2 - X3) - 8 * Y1^4
|
||||
sm2_z256_modp_sub(Y3, S, Y3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "18", Y3);
|
||||
}
|
||||
|
||||
/*
|
||||
(X1:Y1:Z1) + (X2:Y2:Z2) => (X3:Y3:Z3)
|
||||
|
||||
A = Y2 * Z1^3 - Y1 * Z2^3
|
||||
B = X2 * Z1^2 - X1 * Z2^2
|
||||
|
||||
X3 = A^2 - B^2 * (X2 * Z1^2 + X1 * Z2^2)
|
||||
= A^2 - B^3 - 2 * B^2 * X1 * Z2^2
|
||||
Y3 = A * (X1 * B^2 * Z2^2 - X3) - Y1 * B^3 * Z2^3
|
||||
Z3 = B * Z1 * Z2
|
||||
|
||||
P + (-P) = (X:Y:Z) + (k^2*X : k^3*Y : k*Z) => (0:0:0)
|
||||
|
||||
感觉点加也有很好的并行性
|
||||
*/
|
||||
void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z256_POINT *b)
|
||||
{
|
||||
uint64_t U2[4], S2[4];
|
||||
@@ -1028,6 +1173,7 @@ void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z2
|
||||
in1infty = is_zero(in1infty);
|
||||
in2infty = is_zero(in2infty);
|
||||
|
||||
// 这里很明显有极好的并行性
|
||||
sm2_z256_modp_mont_sqr(Z2sqr, in2_z); /* Z2^2 */
|
||||
sm2_z256_modp_mont_sqr(Z1sqr, in1_z); /* Z1^2 */
|
||||
|
||||
@@ -1057,11 +1203,13 @@ void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z2
|
||||
|
||||
sm2_z256_modp_mont_sqr(Rsqr, R); /* R^2 */
|
||||
sm2_z256_modp_mont_mul(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
|
||||
|
||||
sm2_z256_modp_mont_sqr(Hsqr, H); /* H^2 */
|
||||
sm2_z256_modp_mont_mul(res_z, res_z, in2_z); /* Z3 = H*Z1*Z2 */
|
||||
sm2_z256_modp_mont_mul(Hcub, Hsqr, H); /* H^3 */
|
||||
|
||||
sm2_z256_modp_mont_mul(Hcub, Hsqr, H); /* H^3 */
|
||||
sm2_z256_modp_mont_mul(U2, U1, Hsqr); /* U1*H^2 */
|
||||
|
||||
sm2_z256_modp_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */
|
||||
|
||||
sm2_z256_modp_sub(res_x, Rsqr, Hsqr);
|
||||
@@ -1071,6 +1219,7 @@ void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z2
|
||||
|
||||
sm2_z256_modp_mont_mul(S2, S1, Hcub);
|
||||
sm2_z256_modp_mont_mul(res_y, R, res_y);
|
||||
|
||||
sm2_z256_modp_sub(res_y, res_y, S2);
|
||||
|
||||
sm2_z256_copy_conditional(res_x, in2_x, in1infty);
|
||||
@@ -1093,7 +1242,6 @@ void sm2_z256_point_neg(SM2_Z256_POINT *R, const SM2_Z256_POINT *P)
|
||||
sm2_z256_copy(R->Z, P->Z);
|
||||
}
|
||||
|
||||
// point_mul 中用到
|
||||
void sm2_z256_point_sub(SM2_Z256_POINT *R, const SM2_Z256_POINT *A, const SM2_Z256_POINT *B)
|
||||
{
|
||||
SM2_Z256_POINT neg_B;
|
||||
@@ -1109,8 +1257,28 @@ void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_P
|
||||
int n = (256 + window_size - 1)/window_size;
|
||||
int i;
|
||||
|
||||
// 这相当于做了一个预计算表
|
||||
/*
|
||||
P 2P 4P 8P // 这实际上是一个连续的dbl
|
||||
|
||||
3P 6P, 12P
|
||||
|
||||
5P, 10P,
|
||||
|
||||
7P, 14P
|
||||
|
||||
15P
|
||||
...
|
||||
|
||||
// 如果一次能并行计算4组点加法,那么这部分与计算表的计算量可以降低
|
||||
// 这个连续计算中,dbl的数量越多,计算量越低
|
||||
*/
|
||||
|
||||
// T[i] = (i + 1) * P
|
||||
memcpy(&T[0], P, sizeof(SM2_Z256_POINT));
|
||||
|
||||
// 这个计算大概是有并行能力的!
|
||||
/*
|
||||
sm2_z256_point_dbl(&T[ 1], &T[ 0]);
|
||||
sm2_z256_point_add(&T[ 2], &T[ 1], P);
|
||||
sm2_z256_point_dbl(&T[ 3], &T[ 1]);
|
||||
@@ -1126,6 +1294,24 @@ void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_P
|
||||
sm2_z256_point_dbl(&T[13], &T[ 6]);
|
||||
sm2_z256_point_add(&T[14], &T[13], P);
|
||||
sm2_z256_point_dbl(&T[15], &T[ 7]);
|
||||
*/
|
||||
|
||||
sm2_z256_point_dbl(&T[2-1], &T[1-1]);
|
||||
sm2_z256_point_dbl(&T[4-1], &T[2-1]);
|
||||
sm2_z256_point_dbl(&T[8-1], &T[4-1]);
|
||||
sm2_z256_point_dbl(&T[16-1], &T[8-1]);
|
||||
sm2_z256_point_add(&T[3-1], &T[2-1], P);
|
||||
sm2_z256_point_dbl(&T[6-1], &T[3-1]);
|
||||
sm2_z256_point_dbl(&T[12-1], &T[6-1]);
|
||||
sm2_z256_point_add(&T[5-1], &T[3-1], &T[2-1]);
|
||||
sm2_z256_point_dbl(&T[10-1], &T[5-1]);
|
||||
sm2_z256_point_add(&T[7-1], &T[4-1], &T[3-1]);
|
||||
sm2_z256_point_dbl(&T[14-1], &T[7-1]);
|
||||
sm2_z256_point_add(&T[9-1], &T[4-1], &T[5-1]);
|
||||
sm2_z256_point_add(&T[11-1], &T[6-1], &T[5-1]);
|
||||
sm2_z256_point_add(&T[13-1], &T[7-1], &T[6-1]);
|
||||
sm2_z256_point_add(&T[15-1], &T[8-1], &T[7-1]);
|
||||
|
||||
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
int booth = sm2_z256_get_booth(k, window_size, i);
|
||||
@@ -1136,11 +1322,9 @@ void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_P
|
||||
R_infinity = 0;
|
||||
}
|
||||
} else {
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
sm2_z256_point_dbl(R, R);
|
||||
// 这个重复dbl的计算可以适当降低吗?
|
||||
// 这说明对dbl的优化还是很有意义的,因为这里面dbl的数量最多
|
||||
sm2_z256_point_dbl_x5(R, R);
|
||||
|
||||
if (booth > 0) {
|
||||
sm2_z256_point_add(R, R, &T[booth - 1]);
|
||||
@@ -1177,6 +1361,8 @@ void sm2_z256_point_copy_affine(SM2_Z256_POINT *R, const SM2_Z256_POINT_AFFINE *
|
||||
sm2_z256_copy(R->Z, SM2_Z256_MODP_MONT_ONE);
|
||||
}
|
||||
|
||||
// 这是一个比较容易并行的算法
|
||||
// r, a, b 都转换为实际输入的值
|
||||
void sm2_z256_point_add_affine(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z256_POINT_AFFINE *b)
|
||||
{
|
||||
uint64_t U2[4], S2[4];
|
||||
@@ -1287,44 +1473,60 @@ int sm2_z256_point_affine_print(FILE *fp, int fmt, int ind, const char *label, c
|
||||
extern const uint64_t sm2_z256_pre_comp[37][64 * 4 * 2];
|
||||
static SM2_Z256_POINT_AFFINE (*g_pre_comp)[64] = (SM2_Z256_POINT_AFFINE (*)[64])sm2_z256_pre_comp;
|
||||
|
||||
|
||||
/*
|
||||
这个函数的粗粒度并行算法
|
||||
|
||||
输出的R应该有多个,输入的k也有多个
|
||||
|
||||
轮数是一样的
|
||||
|
||||
需要用一个数组表示这个值是否还是无穷远点
|
||||
|
||||
在签名、加密的时候,参与计算的k都是秘密值,因此需要考虑cache攻击的问题
|
||||
|
||||
但是在验签的时候,其中s*G计算,其中s是公开值,因此不需要考虑cache攻击
|
||||
|
||||
应该提供一个专用的常量时间的gather函数
|
||||
|
||||
*/
|
||||
void sm2_z256_point_mul_generator(SM2_Z256_POINT *R, const uint64_t k[4])
|
||||
{
|
||||
size_t window_size = 7;
|
||||
int R_infinity = 1;
|
||||
int R_infinity = 1; // 开始的时候点
|
||||
int n = (256 + window_size - 1)/window_size;
|
||||
int i;
|
||||
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
int booth = sm2_z256_get_booth(k, window_size, i);
|
||||
|
||||
// 下面的计算应该改为并行化
|
||||
if (R_infinity) {
|
||||
if (booth != 0) {
|
||||
sm2_z256_point_copy_affine(R, &g_pre_comp[i][booth - 1]);
|
||||
R_infinity = 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
// 可以先把那个点从内存复制到当前空间中
|
||||
// 如果booth < 0,则把这个点改为 -P
|
||||
// 然后再加上这个点,得到一个新的结果
|
||||
if (booth > 0) {
|
||||
sm2_z256_point_add_affine(R, R, &g_pre_comp[i][booth - 1]);
|
||||
} else if (booth < 0) {
|
||||
sm2_z256_point_sub_affine(R, R, &g_pre_comp[i][-booth - 1]);
|
||||
}
|
||||
|
||||
// booth == 0的时候意味应该加入的affine是一个无穷远点
|
||||
// 如果是无穷远点,读入的值,以及计算结果就没有用了。
|
||||
}
|
||||
}
|
||||
|
||||
if (R_infinity) {
|
||||
memset(R, 0, sizeof(*R));
|
||||
sm2_z256_point_set_infinity(R);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// R = t*P + s*G
|
||||
void sm2_z256_point_mul_sum(SM2_Z256_POINT *R, const uint64_t t[4], const SM2_Z256_POINT *P, const uint64_t s[4])
|
||||
{
|
||||
@@ -1334,8 +1536,6 @@ void sm2_z256_point_mul_sum(SM2_Z256_POINT *R, const uint64_t t[4], const SM2_Z2
|
||||
sm2_z256_point_add(R, R, &Q);
|
||||
}
|
||||
|
||||
|
||||
// 这个是否要检查点是否在曲线上?
|
||||
void sm2_z256_point_from_bytes(SM2_Z256_POINT *P, const uint8_t in[64])
|
||||
{
|
||||
sm2_z256_from_bytes(P->X, in);
|
||||
@@ -1364,6 +1564,35 @@ void sm2_z256_point_to_bytes(const SM2_Z256_POINT *P, uint8_t out[64])
|
||||
sm2_z256_to_bytes(y, out + 32);
|
||||
}
|
||||
|
||||
int sm2_z256_point_equ(const SM2_Z256_POINT *P, const SM2_Z256_POINT *Q)
|
||||
{
|
||||
uint64_t Z1[4] = {0};
|
||||
uint64_t Z2[4] = {0};
|
||||
uint64_t V1[4] = {0};
|
||||
uint64_t V2[4] = {0};
|
||||
|
||||
// X1 * Z2^2 == X2 * Z1^2
|
||||
sm2_z256_modp_mont_sqr(Z1, P->Z);
|
||||
sm2_z256_modp_mont_sqr(Z2, Q->Z);
|
||||
sm2_z256_modp_mont_mul(V1, P->X, Z2);
|
||||
sm2_z256_modp_mont_mul(V2, Q->X, Z1);
|
||||
if (sm2_z256_cmp(V1, V2) != 0) {
|
||||
error_print();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Y1 * Z2^3 == Y2 * Z1^3
|
||||
sm2_z256_modp_mont_mul(Z1, Z1, P->Z);
|
||||
sm2_z256_modp_mont_mul(Z2, Z2, Q->Z);
|
||||
sm2_z256_modp_mont_mul(V1, P->Y, Z2);
|
||||
sm2_z256_modp_mont_mul(V2, Q->Y, Z1);
|
||||
if (sm2_z256_cmp(V1, V2) != 0) {
|
||||
error_print();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_z256_point_equ_hex(const SM2_Z256_POINT *P, const char *hex)
|
||||
{
|
||||
@@ -1379,8 +1608,96 @@ int sm2_z256_point_equ_hex(const SM2_Z256_POINT *P, const char *hex)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int sm2_z256_is_odd(const uint64_t a[4])
|
||||
{
|
||||
return a[0] & 0x01;
|
||||
}
|
||||
|
||||
int sm2_z256_point_from_x_bytes(SM2_Z256_POINT *P, const uint8_t x_bytes[32], int y_is_odd)
|
||||
{
|
||||
uint64_t x[4];
|
||||
uint64_t y_sqr[4];
|
||||
uint64_t y[4];
|
||||
int ret;
|
||||
|
||||
uint64_t SM2_Z256_MODP_MONT_THREE[4] = { 3,0,0,0 };
|
||||
|
||||
sm2_z256_modp_to_mont(SM2_Z256_MODP_MONT_THREE, SM2_Z256_MODP_MONT_THREE);
|
||||
|
||||
sm2_z256_from_bytes(x, x_bytes);
|
||||
if (sm2_z256_cmp(x, SM2_Z256_P) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_z256_modp_to_mont(x, x);
|
||||
|
||||
sm2_z256_copy(P->X, x);
|
||||
|
||||
// y^2 = x^3 - 3x + b = (x^2 - 3)*x + b
|
||||
sm2_z256_modp_mont_sqr(y_sqr, x);
|
||||
sm2_z256_modp_sub(y_sqr, y_sqr, SM2_Z256_MODP_MONT_THREE);
|
||||
sm2_z256_modp_mont_mul(y_sqr, y_sqr, x);
|
||||
sm2_z256_modp_add(y_sqr, y_sqr, SM2_Z256_MODP_MONT_B);
|
||||
|
||||
// y = sqrt(y^2)
|
||||
if ((ret = sm2_z256_modp_mont_sqrt(y, y_sqr)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
|
||||
sm2_z256_copy(P->Y , y); // mont(y)
|
||||
|
||||
sm2_z256_modp_from_mont(y, y);
|
||||
if (y_is_odd) {
|
||||
if (!sm2_z256_is_odd(y)) {
|
||||
sm2_z256_modp_neg(P->Y, P->Y);
|
||||
}
|
||||
} else {
|
||||
if (sm2_z256_is_odd(y)) {
|
||||
sm2_z256_modp_neg(P->Y, P->Y);
|
||||
}
|
||||
}
|
||||
|
||||
sm2_z256_copy(P->Z, SM2_Z256_MODP_MONT_ONE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_z256_point_from_hash(SM2_Z256_POINT *R, const uint8_t *data, size_t datalen, int y_is_odd)
|
||||
{
|
||||
uint64_t x[4];
|
||||
uint8_t x_bytes[32];
|
||||
uint8_t dgst[32];
|
||||
int ret;
|
||||
|
||||
do {
|
||||
// x = sm3(data) mod p
|
||||
sm3_digest(data, datalen, dgst);
|
||||
|
||||
sm2_z256_from_bytes(x, dgst);
|
||||
if (sm2_z256_cmp(x, SM2_Z256_P) >= 0) {
|
||||
sm2_z256_sub(x, x, SM2_Z256_P);
|
||||
}
|
||||
sm2_z256_to_bytes(x, x_bytes);
|
||||
|
||||
// compute y
|
||||
if ((ret = sm2_z256_point_from_x_bytes(R, x_bytes, y_is_odd)) == 1) {
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// data = sm3(data), try again
|
||||
data = dgst;
|
||||
datalen = sizeof(dgst);
|
||||
|
||||
} while (1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
706
src/sm2_z256_key.c
Normal file
706
src/sm2_z256_key.c
Normal file
@@ -0,0 +1,706 @@
|
||||
/*
|
||||
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <gmssl/sm2_z256.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/pem.h>
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/pbkdf2.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
|
||||
|
||||
int sm2_key_generate(SM2_KEY *key)
|
||||
{
|
||||
uint64_t d[4];
|
||||
SM2_Z256_POINT P;
|
||||
|
||||
if (!key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (sm2_z256_rand_range(d, sm2_z256_order_minus_one()) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_z256_is_zero(d));
|
||||
|
||||
sm2_z256_point_mul_generator(&P, d);
|
||||
|
||||
sm2_z256_to_bytes(d, key->private_key);
|
||||
sm2_z256_point_to_bytes(&P, (uint8_t *)&key->public_key);
|
||||
|
||||
gmssl_secure_clear(d, sizeof(d));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_key_set_private_key(SM2_KEY *key, const uint8_t private_key[32])
|
||||
{
|
||||
uint64_t d[4];
|
||||
SM2_Z256_POINT P;
|
||||
int ret = -1;
|
||||
|
||||
if (!key || !private_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_z256_from_bytes(d, private_key);
|
||||
|
||||
if (sm2_z256_is_zero(d)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (sm2_z256_cmp(d, sm2_z256_order_minus_one()) >= 0) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
sm2_z256_point_mul_generator(&P, d);
|
||||
|
||||
sm2_z256_to_bytes(d, key->private_key);
|
||||
sm2_z256_point_to_bytes(&P, (uint8_t *)&key->public_key);
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(d, sizeof(d));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key)
|
||||
{
|
||||
uint64_t d[4] = {0};
|
||||
SM2_Z256_POINT P;
|
||||
|
||||
if (!key || !public_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_z256_point_from_bytes(&P, (uint8_t *)public_key);
|
||||
if (sm2_z256_point_is_on_curve(&P) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_z256_to_bytes(d, key->private_key);
|
||||
sm2_z256_point_to_bytes(&P, (uint8_t *)&key->public_key);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *key)
|
||||
{
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
sm2_public_key_print(fp, fmt, ind, "publicKey", key);
|
||||
format_bytes(fp, fmt, ind, "privateKey", key->private_key, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int sm2_public_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t buf[65];
|
||||
size_t len = 0;
|
||||
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
sm2_point_to_uncompressed_octets(&key->public_key, buf);
|
||||
if (asn1_bit_octets_to_der(buf, sizeof(buf), out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
SM2_POINT P;
|
||||
|
||||
if ((ret = asn1_bit_octets_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (dlen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 这里不太对,SM2_POINT 被反复检查了
|
||||
if (sm2_point_from_octets(&P, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_set_public_key(key, &P) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *pub_key)
|
||||
{
|
||||
return sm2_point_print(fp, fmt, ind, label, &pub_key->public_key);
|
||||
}
|
||||
|
||||
int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if (x509_public_key_algor_to_der(OID_ec_public_key, OID_sm2, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
int oid;
|
||||
int curve;
|
||||
|
||||
if ((ret = x509_public_key_algor_from_der(&oid, &curve, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (oid != OID_ec_public_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (curve != OID_sm2) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SM2_PRIVATE_KEY_DER_SIZE 121
|
||||
int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t params[64];
|
||||
uint8_t pubkey[128];
|
||||
uint8_t *params_ptr = params;
|
||||
uint8_t *pubkey_ptr = pubkey;
|
||||
size_t params_len = 0;
|
||||
size_t pubkey_len = 0;
|
||||
|
||||
if (!key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ec_named_curve_to_der(OID_sm2, ¶ms_ptr, ¶ms_len) != 1
|
||||
|| sm2_public_key_to_der(key, &pubkey_ptr, &pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_int_to_der(EC_private_key_version, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(key->private_key, 32, NULL, &len) != 1
|
||||
|| asn1_explicit_to_der(0, params, params_len, NULL, &len) != 1
|
||||
|| asn1_explicit_to_der(1, pubkey, pubkey_len, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_int_to_der(EC_private_key_version, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(key->private_key, 32, out, outlen) != 1
|
||||
|| asn1_explicit_to_der(0, params, params_len, out, outlen) != 1
|
||||
|| asn1_explicit_to_der(1, pubkey, pubkey_len, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int ver;
|
||||
const uint8_t *prikey;
|
||||
const uint8_t *params;
|
||||
const uint8_t *pubkey;
|
||||
size_t prikey_len, params_len, pubkey_len;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&ver, &d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1
|
||||
|| asn1_explicit_from_der(0, ¶ms, ¶ms_len, &d, &dlen) != 1
|
||||
|| asn1_explicit_from_der(1, &pubkey, &pubkey_len, &d, &dlen) != 1
|
||||
|| asn1_check(ver == EC_private_key_version) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (params) {
|
||||
int curve;
|
||||
if (ec_named_curve_from_der(&curve, ¶ms, ¶ms_len) != 1
|
||||
|| asn1_check(curve == OID_sm2) != 1
|
||||
|| asn1_length_is_zero(params_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (asn1_check(prikey_len == 32) != 1
|
||||
|| sm2_key_set_private_key(key, prikey) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if the public key is correct
|
||||
if (pubkey) {
|
||||
SM2_KEY tmp_key;
|
||||
if (sm2_public_key_from_der(&tmp_key, &pubkey, &pubkey_len) != 1
|
||||
|| asn1_length_is_zero(pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_public_key_equ(key, &tmp_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
return ec_private_key_print(fp, fmt, ind, label, d, dlen);
|
||||
}
|
||||
|
||||
#define SM2_PRIVATE_KEY_INFO_DER_SIZE 150
|
||||
|
||||
int sm2_private_key_info_to_der(const SM2_KEY *sm2_key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t prikey[SM2_PRIVATE_KEY_DER_SIZE];
|
||||
uint8_t *p = prikey;
|
||||
size_t prikey_len = 0;
|
||||
|
||||
if (sm2_private_key_to_der(sm2_key, &p, &prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1
|
||||
|| sm2_public_key_algor_to_der(NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1
|
||||
|| sm2_public_key_algor_to_der(out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) {
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_from_der(SM2_KEY *sm2_key, const uint8_t **attrs, size_t *attrslen,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int version;
|
||||
const uint8_t *prikey;
|
||||
size_t prikey_len;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&version, &d, &dlen) != 1
|
||||
|| sm2_public_key_algor_from_der(&d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1
|
||||
|| asn1_implicit_set_from_der(0, attrs, attrslen, &d, &dlen) < 0
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_check(version == PKCS8_private_key_info_version) != 1
|
||||
|| sm2_private_key_from_der(sm2_key, &prikey, &prikey_len) != 1
|
||||
|| asn1_length_is_zero(prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
int val;
|
||||
const uint8_t *prikey;
|
||||
size_t prikey_len;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "version: %d\n", val);
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
x509_public_key_algor_print(fp, fmt, ind, "privateKeyAlgorithm", p, len);
|
||||
if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
if (asn1_sequence_from_der(&prikey, &prikey_len, &p, &len) != 1) goto err;
|
||||
ec_private_key_print(fp, fmt, ind + 4, "privateKey", prikey, prikey_len);
|
||||
if (asn1_length_is_zero(len) != 1) goto err;
|
||||
if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
else if (ret) format_bytes(fp, fmt, ind, "attributes", p, len);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SM2_PRIVATE_KEY_EXPORT
|
||||
int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp)
|
||||
{
|
||||
int ret = -1;
|
||||
uint8_t buf[SM2_PRIVATE_KEY_INFO_DER_SIZE];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (!key || !fp) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_info_to_der(key, &p, &len) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (len != sizeof(buf)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (pem_write(fp, "PRIVATE KEY", buf, len) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(buf, sizeof(buf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_from_pem(SM2_KEY *sm2_key, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
const uint8_t *cp = buf;
|
||||
size_t len;
|
||||
const uint8_t *attrs;
|
||||
size_t attrs_len;
|
||||
|
||||
if (pem_read(fp, "PRIVATE KEY", buf, &len, sizeof(buf)) != 1
|
||||
|| sm2_private_key_info_from_der(sm2_key, &attrs, &attrs_len, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (attrs_len) {
|
||||
error_print();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sm2_public_key_info_to_der(const SM2_KEY *pub_key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (sm2_public_key_algor_to_der(NULL, &len) != 1
|
||||
|| sm2_public_key_to_der(pub_key, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| sm2_public_key_algor_to_der(out, outlen) != 1
|
||||
|| sm2_public_key_to_der(pub_key, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_info_from_der(SM2_KEY *pub_key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (sm2_public_key_algor_from_der(&d, &dlen) != 1
|
||||
|| sm2_public_key_from_der(pub_key, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SM2_PRIVATE_KEY_EXPORT
|
||||
|
||||
// FIXME: side-channel of Base64
|
||||
int sm2_private_key_to_pem(const SM2_KEY *a, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (sm2_private_key_to_der(a, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pem_write(fp, "EC PRIVATE KEY", buf, len) <= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_from_pem(SM2_KEY *a, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
const uint8_t *cp = buf;
|
||||
size_t len;
|
||||
|
||||
if (pem_read(fp, "EC PRIVATE KEY", buf, &len, sizeof(buf)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_from_der(a, &cp, &len) != 1
|
||||
|| len > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sm2_public_key_info_to_pem(const SM2_KEY *a, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (sm2_public_key_info_to_der(a, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pem_write(fp, "PUBLIC KEY", buf, len) <= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
const uint8_t *cp = buf;
|
||||
size_t len;
|
||||
|
||||
if (pem_read(fp, "PUBLIC KEY", buf, &len, sizeof(buf)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_public_key_info_from_der(a, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_equ(const SM2_KEY *sm2_key, const SM2_KEY *pub_key)
|
||||
{
|
||||
if (memcmp(sm2_key, pub_key, sizeof(SM2_POINT)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key)
|
||||
{
|
||||
return sm2_key_set_public_key(sm2_key, &pub_key->public_key);
|
||||
}
|
||||
|
||||
int sm2_public_key_digest(const SM2_KEY *sm2_key, uint8_t dgst[32])
|
||||
{
|
||||
uint8_t bits[65];
|
||||
sm2_point_to_uncompressed_octets(&sm2_key->public_key, bits);
|
||||
sm3_digest(bits, sizeof(bits), dgst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_encrypt_to_der(const SM2_KEY *sm2_key, const char *pass,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int ret = -1;
|
||||
uint8_t pkey_info[SM2_PRIVATE_KEY_INFO_DER_SIZE];
|
||||
uint8_t *p = pkey_info;
|
||||
size_t pkey_info_len = 0;
|
||||
uint8_t salt[16];
|
||||
int iter = 65536;
|
||||
uint8_t iv[16];
|
||||
uint8_t key[16];
|
||||
SM4_KEY sm4_key;
|
||||
uint8_t enced_pkey_info[sizeof(pkey_info) + 32];
|
||||
size_t enced_pkey_info_len;
|
||||
|
||||
if (!sm2_key || !pass || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_info_to_der(sm2_key, &p, &pkey_info_len) != 1
|
||||
|| rand_bytes(salt, sizeof(salt)) != 1
|
||||
|| rand_bytes(iv, sizeof(iv)) != 1
|
||||
|| pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass),
|
||||
salt, sizeof(salt), iter, sizeof(key), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
if (pkey_info_len != sizeof(pkey_info)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
*/
|
||||
sm4_set_encrypt_key(&sm4_key, key);
|
||||
if (sm4_cbc_padding_encrypt(
|
||||
&sm4_key, iv, pkey_info, pkey_info_len,
|
||||
enced_pkey_info, &enced_pkey_info_len) != 1
|
||||
|| pkcs8_enced_private_key_info_to_der(
|
||||
salt, sizeof(salt), iter, sizeof(key), OID_hmac_sm3,
|
||||
OID_sm4_cbc, iv, sizeof(iv),
|
||||
enced_pkey_info, enced_pkey_info_len, out, outlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(pkey_info, sizeof(pkey_info));
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_decrypt_from_der(SM2_KEY *sm2,
|
||||
const uint8_t **attrs, size_t *attrs_len,
|
||||
const char *pass, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret = -1;
|
||||
const uint8_t *salt;
|
||||
size_t saltlen;
|
||||
int iter;
|
||||
int keylen;
|
||||
int prf;
|
||||
int cipher;
|
||||
const uint8_t *iv;
|
||||
size_t ivlen;
|
||||
uint8_t key[16];
|
||||
SM4_KEY sm4_key;
|
||||
const uint8_t *enced_pkey_info;
|
||||
size_t enced_pkey_info_len;
|
||||
uint8_t pkey_info[256];
|
||||
const uint8_t *cp = pkey_info;
|
||||
size_t pkey_info_len;
|
||||
|
||||
if (!sm2 || !attrs || !attrs_len || !pass || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &keylen, &prf,
|
||||
&cipher, &iv, &ivlen, &enced_pkey_info, &enced_pkey_info_len, in, inlen) != 1
|
||||
|| asn1_check(keylen == -1 || keylen == 16) != 1
|
||||
|| asn1_check(prf == - 1 || prf == OID_hmac_sm3) != 1
|
||||
|| asn1_check(cipher == OID_sm4_cbc) != 1
|
||||
|| asn1_check(ivlen == 16) != 1
|
||||
|| asn1_length_le(enced_pkey_info_len, sizeof(pkey_info)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
sm4_set_decrypt_key(&sm4_key, key);
|
||||
if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_pkey_info, enced_pkey_info_len,
|
||||
pkey_info, &pkey_info_len) != 1
|
||||
|| sm2_private_key_info_from_der(sm2, attrs, attrs_len, &cp, &pkey_info_len) != 1
|
||||
|| asn1_length_is_zero(pkey_info_len) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(pkey_info, sizeof(pkey_info));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_encrypt_to_pem(const SM2_KEY *sm2_key, const char *pass, FILE *fp)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (!fp) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_info_encrypt_to_der(sm2_key, pass, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pem_write(fp, "ENCRYPTED PRIVATE KEY", buf, len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_decrypt_from_pem(SM2_KEY *key, const char *pass, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
const uint8_t *cp = buf;
|
||||
size_t len;
|
||||
const uint8_t *attrs;
|
||||
size_t attrs_len;
|
||||
|
||||
if (!key || !pass || !fp) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf)) != 1
|
||||
|| sm2_private_key_info_decrypt_from_der(key, &attrs, &attrs_len, pass, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
|
||||
typedef SM2_Z256 SM2_U256;
|
||||
|
||||
#define sm2_u256_one() sm2_z256_one()
|
||||
@@ -52,7 +51,6 @@ typedef SM2_Z256_POINT SM2_U256_POINT;
|
||||
#define sm2_u256_point_get_xy(P,x,y) sm2_z256_point_get_xy((P),(x),(y))
|
||||
|
||||
|
||||
|
||||
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_U256_POINT _P, *P = &_P;
|
||||
@@ -82,6 +80,10 @@ int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
sm2_u256_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e", e);
|
||||
|
||||
retry:
|
||||
|
||||
// >>>>>>>>>> BEGIN PRECOMP
|
||||
|
||||
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_u256_modn_rand(k) != 1) {
|
||||
@@ -96,6 +98,11 @@ retry:
|
||||
//sm2_bn_print(stderr, 0, 4, "x", x);
|
||||
|
||||
|
||||
// 如果我们提前计算了 (k, x) 那么我们在真正做签名的时候就可以利用到这个与计算的表了,直接从表中读取 (k, x)
|
||||
// 当然这些计算都可以放在sign_fast里面
|
||||
|
||||
// >>>>>>>>>>> END PRECOMP
|
||||
|
||||
// r = e + x (mod n)
|
||||
if (sm2_u256_cmp(e, order) >= 0) {
|
||||
sm2_u256_sub(e, e, order);
|
||||
@@ -132,13 +139,65 @@ retry:
|
||||
return 1;
|
||||
}
|
||||
|
||||
// k 和 x1 都是要参与计算的,因此我们返回的是内部格式
|
||||
int sm2_do_sign_pre_compute(uint64_t k[4], uint64_t x1[4])
|
||||
{
|
||||
SM2_Z256_POINT P;
|
||||
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_z256_modn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_z256_is_zero(k));
|
||||
|
||||
// (x1, y1) = kG
|
||||
sm2_u256_point_mul_generator(&P, k); // 这个函数要粗力度并行,这要怎么做?
|
||||
sm2_u256_point_get_xy(&P, x1, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 实际上这里只有一次mod n的乘法,用barret就可以了
|
||||
int sm2_do_sign_fast_ex(const uint64_t d[4], const uint64_t k[4], const uint64_t x1[4], const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_Z256_POINT R;
|
||||
uint64_t e[4];
|
||||
uint64_t r[4];
|
||||
uint64_t s[4];
|
||||
|
||||
const uint64_t *order = sm2_z256_order();
|
||||
|
||||
// e = H(M)
|
||||
sm2_z256_from_bytes(e, dgst);
|
||||
if (sm2_z256_cmp(e, order) >= 0) {
|
||||
sm2_z256_sub(e, e, order);
|
||||
}
|
||||
|
||||
// r = e + x1 (mod n)
|
||||
sm2_z256_modn_add(r, e, x1);
|
||||
|
||||
// s = (k + r) * d' - r
|
||||
sm2_z256_modn_add(s, k, r);
|
||||
sm2_z256_modn_mul(s, s, d);
|
||||
sm2_z256_modn_sub(s, s, r);
|
||||
|
||||
sm2_u256_to_bytes(r, sig->r);
|
||||
sm2_u256_to_bytes(s, sig->s);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// (x1, y1) = k * G
|
||||
// r = e + x1
|
||||
// s = (k - r * d)/(1 + d) = (k +r - r * d - r)/(1 + d) = (k + r - r(1 +d))/(1 + d) = (k + r)/(1 + d) - r
|
||||
// = -r + (k + r)*(1 + d)^-1
|
||||
// = -r + (k + r) * d'
|
||||
|
||||
int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
// 这个函数是我们真正要调用的,甚至可以替代原来的函数
|
||||
int sm2_do_sign_fast(const uint64_t d[4], const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_U256_POINT R;
|
||||
SM2_U256 e;
|
||||
@@ -155,6 +214,8 @@ int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
sm2_u256_sub(e, e, order);
|
||||
}
|
||||
|
||||
/// <<<<<<<<<<< 这里的 (k, x1) 应该是从外部输入的!!,这样才是最快的。
|
||||
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_u256_modn_rand(k) != 1) {
|
||||
@@ -164,16 +225,22 @@ int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
} while (sm2_u256_is_zero(k));
|
||||
|
||||
// (x1, y1) = kG
|
||||
sm2_u256_point_mul_generator(&R, k);
|
||||
sm2_u256_point_mul_generator(&R, k); // 这个函数要粗力度并行,这要怎么做?
|
||||
sm2_u256_point_get_xy(&R, x1, NULL);
|
||||
|
||||
/// >>>>>>>>>>>>>>>>>>
|
||||
|
||||
// r = e + x1 (mod n)
|
||||
sm2_u256_modn_add(r, e, x1);
|
||||
|
||||
// 对于快速实现来说,只需要一次乘法
|
||||
|
||||
// 如果 (k, x) 是预计算的,这意味着我们可以并行这个操作
|
||||
// 也就是随机产生一些k,然后执行粗力度并行的点乘
|
||||
|
||||
|
||||
// s = (k + r) * d' - r
|
||||
sm2_u256_add(s, k, r);
|
||||
sm2_u256_modn_add(s, k, r);
|
||||
sm2_u256_modn_mul(s, s, d);
|
||||
sm2_u256_modn_sub(s, s, r);
|
||||
|
||||
@@ -182,6 +249,72 @@ int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 这个其实并没有更快,无非就是降低了解析公钥椭圆曲线点的计算量,这个点要转换为内部的Mont格式
|
||||
// 这里根本没有modn的乘法
|
||||
int sm2_do_verify_fast(const SM2_Z256_POINT *P, const uint8_t dgst[32], const SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_U256_POINT R;
|
||||
SM2_U256 r;
|
||||
SM2_U256 s;
|
||||
SM2_U256 e;
|
||||
SM2_U256 x;
|
||||
SM2_U256 t;
|
||||
|
||||
const uint64_t *order = sm2_u256_order();
|
||||
|
||||
sm2_u256_from_bytes(r, sig->r);
|
||||
// check r in [1, n-1]
|
||||
if (sm2_u256_is_zero(r) == 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_u256_cmp(r, order) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_u256_from_bytes(s, sig->s);
|
||||
// check s in [1, n-1]
|
||||
if (sm2_u256_is_zero(s) == 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_u256_cmp(s, order) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// e = H(M)
|
||||
sm2_u256_from_bytes(e, dgst);
|
||||
|
||||
// t = r + s (mod n), check t != 0
|
||||
sm2_u256_modn_add(t, r, s);
|
||||
if (sm2_u256_is_zero(t)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Q = s * G + t * P
|
||||
sm2_u256_point_mul_sum(&R, t, P, s);
|
||||
sm2_u256_point_get_xy(&R, x, NULL);
|
||||
|
||||
// r' = e + x (mod n)
|
||||
if (sm2_u256_cmp(e, order) >= 0) {
|
||||
sm2_u256_sub(e, e, order);
|
||||
}
|
||||
if (sm2_u256_cmp(x, order) >= 0) {
|
||||
sm2_u256_sub(x, x, order);
|
||||
}
|
||||
sm2_u256_modn_add(e, e, x);
|
||||
|
||||
// check if r == r'
|
||||
if (sm2_u256_cmp(e, r) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_U256_POINT _P, *P = &_P;
|
||||
@@ -277,6 +410,27 @@ static int all_zero(const uint8_t *buf, size_t len)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_encrypt_pre_compute(uint64_t k[4], uint8_t C1[64])
|
||||
{
|
||||
SM2_Z256_POINT P;
|
||||
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_z256_modn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_z256_is_zero(k));
|
||||
|
||||
// output C1 = k * G = (x1, y1)
|
||||
sm2_z256_point_mul_generator(&P, k);
|
||||
sm2_z256_point_to_bytes(&P, C1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 和签名不一样,加密的时候要生成 (k, (x1, y1)) ,也就是y坐标也是需要的
|
||||
// 其中k是要参与计算的,但是 (x1, y1) 不参与计算,输出为 bytes 就可以了
|
||||
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out)
|
||||
{
|
||||
SM2_U256 k;
|
||||
|
||||
Reference in New Issue
Block a user