当前位置: 首页 > news >正文

SM2国密算法的大数运算原理详解

目录

    • 1. 引言
    • 2. 数据类型与转换机制
      • 2.1 大数数据类型定义
      • 2.2 字节转换宏
      • 2.3 转换函数实现
    • 3. 椭圆曲线参数
      • 3.1 SM2曲线参数
      • 3.2 预计算优化表
    • 4. 大数基础运算
      • 4.1 基本操作
      • 4.2 加法运算
      • 4.3 减法运算
      • 4.4 移位运算
    • 5. 大数乘法运算
      • 5.1 32位乘法
      • 5.2 64位乘法
      • 5.3 256位乘法
    • 6. 模运算
      • 6.1 模加法
      • 6.2 模减法
      • 6.3 模乘法
      • 6.4 模平方
      • 6.5 模逆运算
    • 7. 椭圆曲线点运算
      • 7.1 雅可比坐标转换
      • 7.2 点倍运算
      • 7.3 点加运算
    • 8. 标量乘法优化
      • 8.1 滑动窗口优化
      • 8.2 通用标量乘法
    • 9. 密钥派生函数KDF
    • 10. 性能优化技术
      • 10.1 雅可比坐标优化
      • 10.2 预计算表优化
      • 10.3 Karatsuba乘法优化
    • 11. 安全性考虑
      • 11.1 随机数生成
      • 11.2 椭圆曲线点验证
    • 12. 总结
      • 12.1 核心算法
      • 12.2 性能优化
      • 12.3 安全保证

1. 引言

SM2是中国国家密码管理局发布的椭圆曲线公钥密码算法,基于椭圆曲线密码学(ECC)原理。本文详细解析SM2算法中256位大数运算的实现原理,包括数据类型定义、基础运算、模运算、椭圆曲线运算以及性能优化技术。

2. 数据类型与转换机制

2.1 大数数据类型定义

SM2算法使用256位大整数,在C语言中通过32位整数数组表示:

#define array_len_256  8                    // 256位 = 8个32位整数
#define array_len_double_256 16             // 512位 = 16个32位整数
#define array_len_triple_256 24             // 768位 = 24个32位整数typedef uint32_t bn_256_t[array_len_256];   // 256位大整数
typedef uint32_t eccpoint256_t[array_len_double_256];  // 椭圆曲线点(x,y)
typedef uint32_t eccpoint256J_t[array_len_triple_256]; // 雅可比坐标点(x,y,z)// 64位整数结构,用于乘法运算
typedef struct {uint32_t low;uint32_t high;
} uint64;

2.2 字节转换宏

为了在字节数组和大整数数组之间高效转换,定义了专门的宏:

// 字节数组转32位整数数组(大端序)
#define UC_TO_UL(BN,S,i) \
{ \(BN[i]) = ( (uint32_t) (S)[((i) << 2)    ] << 24 ) \| ( (uint32_t) (S)[((i) << 2) + 1] << 16 ) \| ( (uint32_t) (S)[((i) << 2) + 2] <<  8 ) \| ( (uint32_t) (S)[((i) << 2) + 3]       ); \
}// 32位整数数组转字节数组(大端序)
#define UL_TO_UC(S,BN,i) \
{ \(S)[((i) << 2)    ] = (uint8_t) ( ((BN[i]) & 0xFF000000) >> 24 ); \(S)[((i) << 2) + 1] = (uint8_t) ( ((BN[i]) & 0x00FF0000) >> 16 ); \(S)[((i) << 2) + 2] = (uint8_t) ( ((BN[i]) & 0x0000FF00) >>  8 ); \(S)[((i) << 2) + 3] = (uint8_t) ( ((BN[i]) & 0x000000FF)       ); \
}

转换原理:

  • (i) << 2 等价于 i * 4,计算第i个32位整数对应的字节偏移
  • 使用大端序格式,符合网络字节序标准
  • 通过位运算实现高效的字节重组

2.3 转换函数实现

// 大整数转字节数组
static void bn_to_str(uint8_t *s, const bn_t x) {int i;for (i = 0; i < array_len; i++) {UL_TO_UC(s, x, i);  // 使用宏进行转换}
}// 字节数组转大整数
static void str_to_bn(bn_t x, uint8_t *s) {int i;for (i = 0; i < array_len; i++) {UC_TO_UL(x, s, i);  // 使用宏进行转换}
}

3. 椭圆曲线参数

3.1 SM2曲线参数

// SM2椭圆曲线参数
const bn_t curve_p = { 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF };  // 素数p
const bn_t curve_b = { 0x28E9FA9E, 0x9D9F5E34, 0x4D5A9E4B, 0xCF6509A7, 0xF39789F5, 0x15AB8F92, 0xDDBCBD41, 0x4D940E93 };  // 参数b
const bn_t curve_n = { 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7203DF6B, 0x21C6052B, 0x53BBF409, 0x39D54123 };  // 基点阶n// SM2基点G
const eccpoint_t G = {0x32C4AE2C, 0x1F198119, 0x5F990446, 0x6A39C994, 0x8FE30BBF, 0xF2660BE1, 0x715A4589, 0x334C74C7,0xBC3736A2, 0xF4F6779C, 0x59BDCEE3, 0x6B692153, 0xD0A9877C, 0xC62A4740, 0x02DF32E5, 0x2139F0A0
};

参数说明:

  • curve_p: 有限域的素数p,定义椭圆曲线运算的模数
  • curve_b: 椭圆曲线方程 y² = x³ + ax + b 中的参数b(a = -3)
  • curve_n: 基点G的阶,用于私钥范围限制
  • G: 椭圆曲线的基点,用于生成公钥

3.2 预计算优化表

// 预计算curve_p的倍数,用于模运算优化
const bn_t CURVE_P1[11] = {{ 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff },{ 0xfffffffd, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0x00000001, 0xffffffff, 0xfffffffe },// ... 更多预计算值
};// 预计算基点G的倍数,用于滑动窗口优化
const eccpoint_t GPP[16] = {// G, 2G, 3G, ..., 15G 的预计算值
};

4. 大数基础运算

4.1 基本操作

// 清零操作
static void bn_clear(uint32_t *x) {memset(x, 0, array_len * 4);
}// 赋值操作
static void bn_set(uint32_t *x, const uint32_t *y) {memcpy(x, y, array_len * 4);
}// 零值判断
static int bn_is_zero(const bn_t x) {int i = 0;do {if (x[i]) return 0;i++;} while (i < array_len);return 1;
}// 大数比较
static int bn_cmp(const bn_t x, const bn_t y) {int i = 0;do {if (x[i] > y[i]) return 1;else if (x[i] < y[i]) return -1;i++;} while (i < array_len);return 0;
}

4.2 加法运算

static uint32_t bn_add(uint32_t *x, const uint32_t *y, const uint32_t *z) {uint32_t l_carry = 0;int i;for (i = 7; i >= 0; --i) {uint32_t l_sum = y[i] + z[i] + l_carry;if (l_sum != y[i]) {l_carry = (l_sum < y[i]);  // 检测进位}x[i] = l_sum;}return l_carry;  // 返回最高位进位
}

加法原理:

  • 从最低位(数组末尾)开始逐位相加
  • 每次相加考虑前一位的进位
  • 通过比较l_sum < y[i]检测是否发生进位
  • 返回最高位的进位标志

4.3 减法运算

static uint32_t bn_sub(bn_t x, const bn_t y, const bn_t z) {uint32_t l_borrow = 0;int i;for (i = 7; i >= 0; i--) {uint32_t l_diff = y[i] - z[i] - l_borrow;if (l_diff != y[i]) {l_borrow = (l_diff > y[i]);  // 检测借位}x[i] = l_diff;}return l_borrow;
}

4.4 移位运算

// 右移1位
static void bn_rshift1(uint32_t *bn) {bn[7] = bn[7] >> 1 | (bn[6] << 31);bn[6] = bn[6] >> 1 | (bn[5] << 31);bn[5] = bn[5] >> 1 | (bn[4] << 31);bn[4] = bn[4] >> 1 | (bn[3] << 31);bn[3] = bn[3] >> 1 | (bn[2] << 31);bn[2] = bn[2] >> 1 | (bn[1] << 31);bn[1] = bn[1] >> 1 | (bn[0] << 31);bn[0] >>= 1;
}// 右移n位
static void bn_rshiftn(uint32_t *bn, int n) {if (n) {bn[7] = (bn[7] >> (n)) | bn[6] << (32 - (n));bn[6] = (bn[6] >> (n)) | bn[5] << (32 - (n));bn[5] = (bn[5] >> (n)) | bn[4] << (32 - (n));bn[4] = (bn[4] >> (n)) | bn[3] << (32 - (n));bn[3] = (bn[3] >> (n)) | bn[2] << (32 - (n));bn[2] = (bn[2] >> (n)) | bn[1] << (32 - (n));bn[1] = (bn[1] >> (n)) | bn[0] << (32 - (n));bn[0] >>= n;}
}

5. 大数乘法运算

5.1 32位乘法

static uint64 mult_32_32(uint32_t bn_x, uint32_t bn_y) {uint64 l_result;uint32_t a0 = bn_x & 0x0000fffful;  // 低16位uint32_t a1 = bn_x >> 16;           // 高16位uint32_t b0 = bn_y & 0x0000fffful;  // 低16位uint32_t b1 = bn_y >> 16;           // 高16位uint32_t m0 = a0 * b0;  // 低×低uint32_t m1 = a0 * b1;  // 低×高uint32_t m2 = a1 * b0;  // 高×低uint32_t m3 = a1 * b1;  // 高×高m2 += (m0 >> 16);       // 处理进位m2 += m1;if (m2 < m1) {m3 += 0x10000ul;    // 进位处理}l_result.low = bn_x * bn_y;l_result.high = m3 + (m2 >> 16);return l_result;
}

乘法原理:

  • 将32位整数分解为两个16位部分
  • 使用分治思想:(a1*2^16 + a0) * (b1*2^16 + b0) = a1*b1*2^32 + (a1*b0 + a0*b1)*2^16 + a0*b0
  • 通过位运算处理进位

5.2 64位乘法

static void mult_64_64(uint32_t *bn_result, uint64 bn_x, uint64 bn_y) {uint32_t a0 = bn_x.low;uint32_t a1 = bn_x.high;uint32_t b0 = bn_y.low;uint32_t b1 = bn_y.high;uint64 m0 = mult_32_32(a0, b0);  // 低×低uint64 m3 = mult_32_32(a1, b1);  // 高×高// 计算中间项uint32_t m1 = a0 + a1;uint32_t m1_carry = (m1 < a0);uint32_t m2 = b0 + b1;uint32_t m2_carry = (m2 < b0);uint64 m12 = mult_32_32(m1, m2);// 使用Karatsuba算法优化// m12 = (a0+a1)*(b0+b1) - m0 - m3// 结果 = m0 + m12*2^32 + m3*2^64
}

5.3 256位乘法

static void bn_mult(uint32_t *bn_result, const bn_t bn_x, const bn_t bn_y) {// 将256位大数分为两个128位部分uint32_t a0[4], a1[4], b0[4], b1[4];// a0 = bn_x的高128位, a1 = bn_x的低128位// b0 = bn_y的高128位, b1 = bn_y的低128位uint32_t m0[8], m3[8];mult_128_128(m0, a0, b0);  // 高×高mult_128_128(m3, a1, b1);  // 低×低// 计算中间项uint32_t m1[4], m2[4];// m1 = a0 + a1, m2 = b0 + b1bn_t m12;mult_128_128(m12, m1, m2);// 使用Karatsuba算法:m12 = m1*m2 - m0 - m3// 最终结果 = m0*2^256 + m12*2^128 + m3
}

6. 模运算

6.1 模加法

static void bn_modAdd(uint32_t *bn_result, const uint32_t *bn_x, const uint32_t *bn_y) {if (bn_add(bn_result, bn_x, bn_y) || bn_cmp(bn_result, curve_p) >= 0) {bn_sub(bn_result, bn_result, curve_p);  // 如果结果>=p,减去p}
}

6.2 模减法

static void bn_modSub(uint32_t *bn_result, const uint32_t *bn_left, const uint32_t *bn_right) {if (bn_sub(bn_result, bn_left, bn_right)) {bn_add(bn_result, bn_result, curve_p);  // 如果借位,加上p}
}

6.3 模乘法

static inline void bn_modMult(uint32_t *bn_result, const uint32_t *bn_x, const uint32_t *bn_y) {uint32_t l_product[array_len_double];  // 存储乘法结果bn_mult(l_product, bn_x, bn_y);       // 先做完整乘法bn_512mod256(bn_result, l_product);    // 再取模
}

6.4 模平方

static inline void bn_modSquare(uint32_t *bn_result, const uint32_t *bn) {uint32_t l_product[array_len_double];bn_square(l_product, bn);bn_512mod256(bn_result, l_product);
}

6.5 模逆运算

模逆运算使用扩展欧几里得算法的二进制版本:

static void bn_modInv(uint32_t *bn_result, const uint32_t *bn) {bn_t a, b, u, v;uint32_t l_carry;int l_cmpResult;if (bn_is_zero(bn)) {bn_clear(bn_result);return;}bn_set(a, bn);bn_set(b, curve_p);bn_clear(u);u[array_len - 1] = 1;  // u = 1bn_clear(v);           // v = 0while ((l_cmpResult = bn_cmp(a, b)) != 0) {if (EVEN(a)) {// a是偶数,a = a/2, u = u/2 mod pbn_rshift1(a);if (!EVEN(u)) {l_carry = bn_add(u, u, curve_p);}bn_rshift1(u);if (l_carry) {u[0] |= 0x80000000ul;}}else if (EVEN(b)) {// b是偶数,b = b/2, v = v/2 mod pbn_rshift1(b);if (!EVEN(v)) {l_carry = bn_add(v, v, curve_p);}bn_rshift1(v);if (l_carry) {v[0] |= 0x80000000ul;}}else if (l_cmpResult > 0) {// a > b, a = (a-b)/2, u = (u-v)/2 mod pbn_sub(a, a, b);bn_rshift1(a);if (bn_cmp(u, v) < 0) {bn_add(u, u, curve_p);}bn_sub(u, u, v);if (!EVEN(u)) {l_carry = bn_add(u, u, curve_p);}bn_rshift1(u);if (l_carry) {u[0] |= 0x80000000ul;}}else {// b > a, b = (b-a)/2, v = (v-u)/2 mod pbn_sub(b, b, a);bn_rshift1(b);if (bn_cmp(v, u) < 0) {bn_add(v, v, curve_p);}bn_sub(v, v, u);if (!EVEN(v)) {l_carry = bn_add(v, v, curve_p);}bn_rshift1(v);if (l_carry) {v[0] |= 0x80000000ul;}}}bn_set(bn_result, u);
}

模逆算法原理:

  • 使用二进制扩展欧几里得算法
  • 通过连续除以2来减少计算复杂度
  • 维护两个系数u和v,最终u即为模逆

7. 椭圆曲线点运算

7.1 雅可比坐标转换

雅可比坐标可以避免模逆运算,提高椭圆曲线运算效率:

// 从仿射坐标(x,y)转换为雅可比坐标(x,y,z)
static void jacobian_transformation(eccpointJ_t p, const eccpoint_t P) {bn_t t1;uint32_t *pz = p + array_len_double;bn_modSquare(t1, pz);                    // z^2bn_modMult(p, P, t1);                    // x = X*z^2bn_modMult(t1, t1, pz);                  // z^3bn_modMult(p + array_len, P + array_len, t1); // y = Y*z^3
}// 从雅可比坐标(x,y,z)转换为仿射坐标(x,y)
static void jacobian_invtransformation(eccpoint_t P, const eccpointJ_t p) {bn_t t1;bn_t zinv;bn_modInv(zinv, p + array_len_double);   // 1/zbn_modSquare(t1, zinv);                  // 1/(z^2)bn_modMult(P, p, t1);                    // x/(z^2)bn_modMult(t1, t1, zinv);               // 1/(z^3)bn_modMult(P + array_len, p + array_len, t1); // y/(z^3)
}

7.2 点倍运算

static void eccpoint_double(eccpoint_t p_result, const eccpoint_t p) {bn_t kx, prkx;bn_set(kx, p);bn_t s, temp1;bn_modSquare(temp1, kx);                 // x^2bn_modAdd(s, temp1, temp1);              // 2*x^2bn_modAdd(s, s, temp1);                  // 3*x^2bn_clear(temp1);temp1[7] = 3;bn_modSub(s, s, temp1);                  // 3*x^2+a (a=-3)bn_modAdd(temp1, p + array_len, p + array_len); // 2*ybn_modInv(temp1, temp1);                 // 1/(2*y)bn_modMult(s, s, temp1);                 // s = (3*x^2+a)/(2*y)bn_modSquare(prkx, s);                   // s^2bn_modSub(prkx, prkx, kx);               // s^2-xbn_modSub(p_result, prkx, kx);           // s^2-2*xbn_modSub(temp1, kx, p_result);          // x-x3bn_modMult(temp1, temp1, s);             // s*(x-x3)bn_modSub(p_result + array_len, temp1, p + array_len); // s*(x-x3)-y
}

点倍运算原理:

  • 计算椭圆曲线点P的2倍:2P
  • 使用椭圆曲线点倍公式:x₃ = s² - 2x₁, y₃ = s(x₁ - x₃) - y₁
  • 其中s = (3x₁² + a)/(2y₁)

7.3 点加运算

static void eccpoint_add_neq(eccpointJ_t p_result, const eccpointJ_t p1, const eccpoint_t p2) {// 处理特殊情况if (bn_is_zero(p1) == 1 && bn_is_zero(p1 + array_len) == 1) {bn_set(p_result, p2);bn_set(p_result + array_len, p2 + array_len);bn_set(p_result + array_len_double, ONE);return;}if (bn_is_zero(p2) == 1 && bn_is_zero(p2 + array_len) == 1) {bn_set(p_result, p1);bn_set(p_result + array_len, p1 + array_len);bn_set(p_result + array_len_double, p1 + array_len_double);return;}// 计算点加const uint32_t *p1x = p1;const uint32_t *p1y = p1 + array_len;const uint32_t *p1z = p1 + array_len_double;const uint32_t *p2kx = p2;const uint32_t *p2ky = p2 + array_len;bn_t A, B, C, D, temp1, temp2, temp3, temp4;bn_modSquare(temp1, p1z);                // z1^2bn_modMult(A, p2kx, temp1);              // x2*z1^2bn_modMult(B, temp1, p1z);               // z1^3bn_modMult(B, B, p2ky);                  // y2*z1^3bn_modSub(C, A, p1x);                    // A-x1bn_modSub(D, B, p1y);                    // B-y1// 计算结果点坐标bn_modSquare(temp1, C);                   // C^2bn_modMult(temp2, temp1, p1x);           // x1*C^2bn_modAdd(temp3, temp2, temp2);          // 2*(x1*C^2)bn_modMult(temp1, temp1, C);             // C^3bn_modAdd(temp3, temp3, temp1);          // C^3+2*(x1*C^2)bn_modSquare(temp4, D);                   // D^2bn_modSub(p_result, temp4, temp3);       // D^2-(C^3+2*(x1*C^2))bn_modSub(temp3, temp2, p_result);       // x1*C^2-x3bn_modMult(temp4, D, temp3);             // D*(x1*C^2-x3)bn_modMult(temp2, temp1, p1y);           // y1*C^3bn_modSub(p_result + array_len, temp4, temp2); // D*(x1*C^2-x3)-y1*C^3bn_modMult(p_result + array_len_double, p1z, C); // z1*C
}

8. 标量乘法优化

8.1 滑动窗口优化

static void eccpoint_mult_G_jacobian(eccpoint_t P_result, const bn_t P_scalar) {int i;int j = 255;bn_t k;bn_set(k, P_scalar);int t;uint32_t h;bn_t ktemp;eccpointJ_t p = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 };while (j >= 0) {if (!bn_testBit(k, j)) {eccpoint_add_eq_jacobian(p, p);  // 点倍j--;} else {// 找到连续的1位,进行批量点加t = (j > 4) ? j - 4 : 0;while (!bn_testBit(k, t)) {t++;}bn_rshift(ktemp, k, t);h = ktemp[7] & (0xFFFFFFFFul >> (32 - (j - t + 1) % 32));// 批量点倍for (i = 0; i < j - t + 1; i++) {eccpoint_add_eq_jacobian(p, p);}// 加上预计算的点eccpoint_add_neq(p, p, GPP[h >> 1]);j = t - 1;}}jacobian_invtransformation(P_result, p);
}

滑动窗口原理:

  • 将标量k分解为多个窗口
  • 每个窗口处理连续的1位
  • 使用预计算表GPP减少点加运算次数
  • 显著提高标量乘法效率

8.2 通用标量乘法

void eccpoint_mult_jacobian(eccpoint_t P_result, const eccpoint_t P_point, const bn_t P_scalar) {int i;eccpointJ_t p = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 };eccpointJ_t pp[16] = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } };jacobian_transformation(pp[0], P_point);int j = 255;eccpoint_t P2;eccpoint_double(P2, P_point);for (i = 0; i < 15; i++) {eccpoint_add_neq(pp[i + 1], pp[i], P2);}bn_t k;bn_set(k, P_scalar);int t;uint32_t h;bn_t ktemp;while (j >= 0) {if (!bn_testBit(k, j)) {eccpoint_add_eq_jacobian(p, p);j--;} else {t = (j > 4) ? j - 4 : 0;while (!bn_testBit(k, t)) {t++;}bn_rshift(ktemp, k, t);h = ktemp[7] & (0xFFFFFFFFul >> (32 - (j - t + 1) % 32));for (i = 0; i < j - t + 1; i++) {eccpoint_add_eq_jacobian(p, p);}eccpoint_add_neq_jacobian(p, p, pp[h >> 1]);j = t - 1;}}jacobian_invtransformation(P_result, p);
}

9. 密钥派生函数KDF

static int KDF(uint8_t *R, const uint8_t *S, const uint32_t slen, const uint32_t klen) {uint32_t ct = 0x00000001;uint32_t i;uint8_t H[0x10][0x20];uint32_t imax = TopXdivv(klen);for (i = 0; i < imax; i++) {uint8_t ctc[4];ctc[0] = (uint8_t)(ct >> 24);ctc[1] = (uint8_t)(ct >> 16);ctc[2] = (uint8_t)(ct >> 8);ctc[3] = (uint8_t)(ct);uint8_t *Zct = malloc(slen + 4);memcpy(Zct, S, slen);memcpy(Zct + slen, ctc, 4);sm3(Zct, slen + 4, H[i]);  // 使用SM3哈希ct++;free(Zct);}// 组合所有哈希值uint8_t *H_end = H[imax - 1];uint8_t *K = malloc((imax - 1) << 5);for (i = 0; i < imax - 1; i++) {memcpy(K + (i << 5), H[i], 32);}memcpy(R, K, (imax - 1) << 5);memcpy(R + ((imax - 1) << 5), H_end, 32);free(K);return 0;
}

KDF原理:

  • 将输入数据S与计数器ct连接
  • 使用SM3哈希函数生成哈希值
  • 重复此过程直到生成足够长度的密钥
  • 将所有哈希值连接作为最终密钥

10. 性能优化技术

10.1 雅可比坐标优化

雅可比坐标的主要优势:

  • 避免模逆运算:在点加和点倍运算中不需要计算模逆
  • 减少运算次数:特别是在标量乘法中
  • 提高并行性:雅可比坐标运算更容易并行化

10.2 预计算表优化

// 预计算基点G的倍数
const eccpoint_t GPP[16] = {// G, 2G, 3G, ..., 15G 的预计算值
};

预计算优势:

  • 减少重复计算
  • 加速滑动窗口算法
  • 提高标量乘法效率

10.3 Karatsuba乘法优化

// 使用Karatsuba算法优化大数乘法
// (a1*2^n + a0) * (b1*2^n + b0) = a1*b1*2^(2n) + ((a1+a0)*(b1+b0) - a1*b1 - a0*b0)*2^n + a0*b0

Karatsuba算法优势:

  • 将O(n²)的乘法复杂度降低到O(n^1.585)
  • 特别适合大数乘法运算
  • 减少乘法运算次数

11. 安全性考虑

11.1 随机数生成

static void getRandnum(bn_t bn) {int i;do {for(i = 0; i < array_len; i++) {bn[i] = (uint32_t)rand() | ((uint32_t)rand() << 15) | ((uint32_t)rand() << 30);}} while(bn_cmp(bn, curve_p) > 0);
}

安全要求:

  • 使用密码学安全的随机数生成器
  • 确保随机数在有效范围内
  • 避免可预测的随机数

11.2 椭圆曲线点验证

static int is_eccpoint(eccpoint_t p) {bn_t x, y;bn_set(x, p);bn_set(y, p + array_len);bn_t y2_bar, ax, x2, x3, y2;bn_clear(ax);ax[7] = 3;bn_modMult(ax, x, ax);bn_modSquare(x2, x);bn_modMult(x3, x2, x);bn_modSub(y2_bar, x3, ax);bn_modAdd(y2_bar, y2_bar, curve_b);bn_modSquare(y2, y);return !bn_cmp(y2, y2_bar);
}

验证原理:

  • 检查点坐标是否满足椭圆曲线方程
  • 防止无效点导致的安全漏洞
  • 确保运算的正确性

12. 总结

SM2算法的大数运算实现涉及多个层面的优化:

12.1 核心算法

  1. 基础运算:加法、减法、乘法、比较
  2. 模运算:模加、模减、模乘、模逆
  3. 椭圆曲线运算:点加、点倍、标量乘法
  4. 密钥派生:KDF函数实现

12.2 性能优化

  1. 雅可比坐标:避免模逆运算
  2. 滑动窗口:减少点加运算次数
  3. 预计算表:加速标量乘法
  4. Karatsuba乘法:优化大数乘法

12.3 安全保证

  1. 参数验证:确保椭圆曲线点有效性
  2. 随机数安全:使用密码学安全的随机数
  3. 边界检查:防止溢出和越界

这些技术为SM2算法提供了高效、安全的数学基础,确保算法在实际应用中的性能和安全性。通过精心设计的优化策略,SM2算法能够在保证安全性的同时,提供优秀的性能表现。

http://www.lryc.cn/news/608161.html

相关文章:

  • 牛客 - 旋转数组的最小数字
  • 【PCL点云库:下】
  • 详解Python标准库之互联网数据处理
  • 一个物理引擎仿真器(mujoco这种)的计算流程
  • 回溯 79 单词搜索一波三折想和
  • 中科院开源HYPIR图像复原大模型:1.7秒,老照片变8K画质
  • 深入剖析Nacos:云原生架构的基石
  • JVM 02 垃圾回收
  • 【LeetCode 热题 100】(三)滑动窗口
  • file命令libmagic、python的cchardet库使用、自定义magic文件的使用
  • 【Spring Boot 快速入门】五、文件上传
  • Python 入门指南:从零基础到环境搭建
  • Qt 信号和槽正常连接返回true,但发送信号后槽函数无响应问题【已解决】
  • AI原生数据库:告别SQL的新时代来了?
  • 飞书推送工具-自动化测试发送测试报告一种方式
  • Linux 动静态库的制作和使用
  • [硬件电路-121]:模拟电路 - 信号处理电路 - 模拟电路中常见的难题
  • FastAPI--一个快速的 Python Web
  • 网络安全突发事件应急预案方案
  • 2024年网络安全预防
  • 电脑手机热点方式通信(上)
  • 智能手表:小恐龙游戏
  • Linux自主实现shell
  • C#开发入门指南_学习笔记
  • Ubuntu系统VScode实现opencv(c++)图像翻转和旋转
  • Java 注解详解(含底层原理)
  • Vue 3.0 Composition API:重新定义组件逻辑的组织方式
  • 算法训练营DAY46 第九章 动态规划part13
  • 全球化 2.0 | 中国香港教育机构通过云轴科技ZStack实现VMware替代
  • stm32103如果不用32k晶振,那引脚是悬空还是接地