# openssl 版本必须是 1.1 以上,才包含国密 SM2 算法
require 'openssl'
require 'base64'
# 生成 PEM 格式的私钥
key = OpenSSL::PKey::EC.generate('SM2')
private_key = key.export
# 基于私钥生成 PEM 格式的公钥
pkey = OpenSSL::PKey::EC.new(key.public_key.group)
pkey.public_key = key.public_key
public_key = pkey.export
# 待签名的数据
data = "hello"
# 通过私钥生成签名
ec1 = OpenSSL::PKey::EC.new(private_key)
sn = Base64.encode64(ec.dsa_sign_asn1(data)).gsub("\n", "")
# 通过公钥验证签名
ec2 = OpenSSL::PKey::EC.new(public_key)
ec2.dsa_verify_asn1(data, Base64.decode64(sn))
# => true
SM2 采用的是 ECC 椭圆曲线加密算法,它的几个曲线点位值为:
https://github.com/openssl/openssl/blob/master/crypto/ec/ec_curve.c#L2781
#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODULE)
static const struct {
EC_CURVE_DATA h;
unsigned char data[0 + 32 * 6];
} _EC_sm2p256v1 = {
{
NID_X9_62_prime_field, 0, 32, 1
},
{
/* no seed */
/* p */
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* a */
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
/* b */
0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b,
0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92,
0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93,
/* x */
0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46,
0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1,
0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7,
/* y */
0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3,
0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40,
0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0,
/* order */
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b,
0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23,
}
};
#endif /* OPENSSL_NO_SM2 */