使用 openssl 进行椭圆曲线加解密(SM2)
在之前一篇博客 ECC(Elliptic Curves Cryptography) 椭圆曲线加密原理 简单地阐述了 ECC 加解密的原理。这本篇博客中接着来聊一聊如何使用 OPENSSL 来进行 ECC 加解密。
首先需要明确一点的是:ECC 本身并没有定义一套加解密的方法,它主要作用于密钥交换(ECDHE),与签名认证(ECDSA). 不过后来中国工程师设计定义了一套加密方法,并于近年得到了世界的认可,这就是中国商用(国家标准) SM2 椭圆曲线公钥密码算法 。
一. 基本概念
其实在 openssl 中,椭圆曲线分两种形式,一种是之前讲到的质数域上的椭圆曲线 ,将其称为 其方程为:
另一种是二进制域,称为 , 其方程为:
在这里只讨论 相关的内容。
椭圆曲线上的点
椭圆曲线上的点使用 EC_POINT 来表示, 它定义在 ec_locl.h :
1 | struct ec_point_st { |
EC_POINT 的操作定义在 ec.h 中,有以下操作:
1 | //r = a + b |
椭圆曲线参数
由曲线方程可知,要确定一条曲线,需要知道三个参数 a, b, p。在 openssl 中用结构体 EC_GROUP 来表示。其结构定义在 ec_locl.h 中:
1 | struct ec_group_st { |
-
generator基点 G -
field质数 p -
a, b常量参数
一般来说,除非有特殊的需求会让你自定义一条曲线,否则直接使用 OPENSSL 内置的曲线,这些曲线是经过密码学专家或组织精心设计的:
1 | EC_GROUP *EC_GROUP_new_by_curve_name(int nid); |
openssl 内置的曲线非常之多,可以使用 EC_get_builtin_curves来获取:
1 | void print_all_build_cures(){ |
这些曲线被定义在 ec_curve.c 中,如 NID_sm2 (也叫做 NID_sm2p256v1) 的定义如下:
1 | static const struct { |
二. 加解密
由 ECC 原理我们知道,椭圆曲线利用的是 在有限域上的椭圆曲线,已知曲线上的一个点 xG, 无法有效地求得 x 这样一个离散对数问题。 xG 可以做为公钥, x 做为私钥。
生成密钥对
API EC_KEY_generate_key(EC_KEY) 用于生成密钥对。 EC_KEY 的结构如下:
1 | struct ec_key_st { |
包含一条曲线和一对密钥。当只有 pub_key 时,EC_KEY 做为公钥,当只有 priv_key 时,EC_KEY 做为私钥。
生成一对密钥的示例代码如下:
1 | EC_KEY* key = EC_KEY_new(); |
SM2 加解密
SM2 的 API 定义在 sm2.h 中。加解密用到的有:
1 | int sm2_encrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *msg,size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len); |
加密用到的是公钥, 解密用到的是私钥。
1 |
|