Ailaibo.CSharp.SM2 1.0.0

dotnet add package Ailaibo.CSharp.SM2 --version 1.0.0
                    
NuGet\Install-Package Ailaibo.CSharp.SM2 -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ailaibo.CSharp.SM2" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ailaibo.CSharp.SM2" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Ailaibo.CSharp.SM2" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ailaibo.CSharp.SM2 --version 1.0.0
                    
#r "nuget: Ailaibo.CSharp.SM2, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ailaibo.CSharp.SM2@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ailaibo.CSharp.SM2&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Ailaibo.CSharp.SM2&version=1.0.0
                    
Install as a Cake Tool

Ailaibo.CSharp.SM2

国密 SM2 椭圆曲线公钥密码算法的 C# 实现 —— 零依赖、纯托管,支持从 .NET Framework 4.0 到 .NET 8.0 的各类项目直接引用。

  • 作者:Chu Lijia
  • 公司:Beijing iLab mobile Co,.Ltd
  • 版本:1.0.0
  • 标准:GM/T 0003-2012《SM2 椭圆曲线公钥密码算法》、GM/T 0004-2012《SM3 密码杂凑算法》
  • 标签:SM2 / Ailaibo / C# / CSharp

简介

SM2 是国家密码管理局发布的椭圆曲线公钥密码算法标准,包含密钥对生成、数据加密解密、数字签名验签三大功能,广泛用于政务、金融、能源等领域的身份认证、数据保护与电子签章场景。

本包是 SM2 的 C# 实现,具有以下特点:

  • 零第三方依赖:不引用 BouncyCastle 等任何密码库,椭圆曲线点乘、点加、模逆、模运算全部手写实现;
  • 不调用系统内置国密 API:不依赖 OpenSSL / Windows CNG,纯托管代码自带完整算法;
  • 不使用 unsafe 代码:全部安全托管 C#,可在任意平台运行;
  • 不使用版本专属 API:同一份源码编译到 net40 / net452 / netstandard2.0 / netstandard2.1 / net8.0;
  • 两种密文格式:同时支持 C1 ‖ C3 ‖ C2(新标准)与 C1 ‖ C2 ‖ C3(旧格式),可配置切换;
  • 两种公钥格式:同时支持 65 字节未压缩公钥与 33 字节压缩公钥;
  • 内置官方测试向量:可用 Sm2TestVectors.Verify() 在部署现场做一次冒烟自检。

安装

.NET CLI:

dotnet add package Ailaibo.CSharp.SM2 --version 1.0.0

Package Manager:

Install-Package Ailaibo.CSharp.SM2 -Version 1.0.0

或在 .csproj 中:

<PackageReference Include="Ailaibo.CSharp.SM2" Version="1.0.0" />

提示: 若项目需要独立的 SM3 哈希能力(流式计算、分段多次 Update、与 HashAlgorithm 集成等), 请另行引用配套包 Ailaibo.CSharp.SM3。本包不对外提供 SM3 的算法能力,仅供 SM2 内部按标准计算摘要。

支持的目标框架

目标框架 说明
net40 .NET Framework 4.0(旧系统兼容)
net452 .NET Framework 4.5.2 / 4.6.x / 4.7.x / 4.8
netstandard2.0 覆盖 .NET Core 2.0+ / .NET 5+ 等大多数现代项目
netstandard2.1 .NET Core 3.0+ / .NET 5+
net8.0 .NET 8

快速上手

命名空间是 Ailaibo.CSharp,主类 SM2 的完整类型名为 Ailaibo.CSharp.SM2。

using System.Numerics;
using System.Text;
using Ailaibo.CSharp;

// 1) 生成密钥对
SM2KeyPair keyPair = SM2.GenerateKeyPair();

byte[] publicKey  = keyPair.PublicKey;              // 65 字节,04 开头(未压缩)
byte[] publicKeyC = keyPair.PublicKeyCompressed;    // 33 字节,02/03 开头(压缩)
BigInteger privateKey = keyPair.PrivateKey;

// 2) 加密与解密(默认 C1C3C2 新标准格式)
byte[] plainData = Encoding.UTF8.GetBytes("国密 SM2 加密演示");
byte[] cipherText = SM2.Encrypt(plainData, publicKey);              // isNewFormat: true
byte[] decrypted  = SM2.Decrypt(cipherText, privateKey);

// 旧格式 C1C2C3:把 isNewFormat 传 false
byte[] legacyCipher = SM2.Encrypt(plainData, publicKey, false);
byte[] legacyPlain  = SM2.Decrypt(legacyCipher, privateKey, false);

// 3) 签名与验签(默认用户 ID "1234567812345678")
byte[] message   = Encoding.UTF8.GetBytes("订单号 20260921-0001");
byte[] signature = SM2.Sign(message, privateKey);                   // 64 字节 r ‖ s
bool ok = SM2.Verify(message, signature, publicKey);

// 4) 自定义用户 ID(默认可省略)
byte[] sig2 = SM2.Sign(message, privateKey, "ALICE123@YAHOO.COM");
bool ok2 = SM2.Verify(message, sig2, publicKey, "ALICE123@YAHOO.COM");

// 5) 用密钥对对象调用更省事
byte[] cipher2 = SM2.Encrypt(plainData, keyPair);
byte[] plain2  = SM2.Decrypt(cipher2, keyPair);
byte[] sig3    = SM2.Sign(message, keyPair);
bool ok3       = SM2.Verify(message, sig3, keyPair.PublicKeyCompressed);   // 压缩公钥也可验签

// 6) 从已有私钥恢复密钥对(十六进制 / 字节数组 / BigInteger 三种方式)
SM2KeyPair restored = SM2.GenerateKeyPair(SM2Utils.HexToBigInteger("3945208F...4DF7C5B8"));

API 一览

SM2(静态方法)

成员 说明
GenerateKeyPair() 生成新的 SM2 密钥对
GenerateKeyPair(BigInteger privateKey) 由私钥大整数恢复密钥对
GenerateKeyPair(byte[] privateKeyBytes) 由私钥字节恢复密钥对
Encrypt(byte[] plainData, byte[] publicKey, bool isNewFormat = true) 用公钥加密,返回密文
Encrypt(byte[] plainData, SM2KeyPair keyPair, bool isNewFormat = true) 用密钥对的公钥加密
Decrypt(byte[] cipherData, BigInteger privateKey, bool isNewFormat) 用私钥解密
Decrypt(byte[] cipherData, SM2KeyPair keyPair, bool isNewFormat) 用密钥对的私钥解密
Sign(byte[] data, BigInteger privateKey, string? userId = null) 签名,返回 64 字节 R ‖ S
Sign(byte[] data, SM2KeyPair keyPair, string? userId = null) 用密钥对的私钥签名
SignWithId(byte[] data, BigInteger privateKey, byte[] userId) 签名,用户 ID 以原始字节给出
Verify(byte[] data, byte[] signature, byte[] publicKey, string? userId) 验签,返回 bool
VerifyWithId(byte[] data, byte[] signature, byte[] publicKey, byte[] userId) 验签,用户 ID 以原始字节给出
ComputeZA(byte[] publicKey, string? userId = null) 计算 ZA = SM3(ENTL ‖ ID ‖ a ‖ b ‖ xG ‖ yG ‖ xA ‖ yA)
ComputeDigest(byte[] data, byte[] publicKey, string? userId) 计算待签名摘要 e = SM3(ZA ‖ M),便于与"只签名摘要"的系统对接
Sm3Hash(byte[] data) 便捷方法:计算标准 SM3 杂凑值(不含 ZA)
SM2.DefaultUserId 标准默认用户 ID "1234567812345678"
SM2.SignatureSizeInBytes 签名固定长度 64

SM2KeyPair

成员 说明
PrivateKey 私钥大整数 d,取值 [1, n-2]
PrivateKeyBytes 私钥的固定 32 字节大端表示
PrivateKeyHex 私钥的小写十六进制字符串
PublicKey 未压缩公钥,65 字节 04 ‖ x ‖ y
PublicKeyCompressed 压缩公钥,33 字节 02/03 ‖ x
PublicKeyX / PublicKeyY 公钥坐标
PublicKeyHex 未压缩公钥的十六进制字符串
PublicKeyCompressedHex 压缩公钥的十六进制字符串
GetPublicKey(bool compressed) 按指定格式取得公钥副本
ToString() 便于日志阅读的摘要,私钥已脱敏

SM2Utils(辅助工具)

成员 说明
BigIntegerToBytes(BigInteger) 大整数 → 最短大端无符号字节数组
BigIntegerToBytes(BigInteger, int fixedLength) 大整数 → 固定长度大端字节数组(左侧补零)
BytesToBigInteger(byte[]) 大端字节数组 → 非负大整数
ToHex(byte[]) / ToHex(byte[], bool) 字节数组 → 十六进制(可指定大小写)
FromHex(string) 十六进制 → 字节数组(忽略空格等分隔符)
HexToBigInteger(string) 十六进制 → 大整数
CompressPublicKey(byte[]) 未压缩公钥 → 压缩公钥
DecompressPublicKey(byte[]) 压缩公钥 → 未压缩公钥
IsValidPublicKey(byte[]) 校验公钥格式并确认点确实在曲线上
IsCompressedPublicKey(byte[]) / IsUncompressedPublicKey(byte[]) 格式判断

Sm2TestVectors(官方测试向量与自检)

成员 说明
Verify() 自检,失败抛 InvalidOperationException
TryVerify(out string? failedName) 自检,通过返回值报告结果
CurvePHex / CurveAHex / … GM/T 0003.5-2012 推荐曲线参数
Encryption*Hex 官方加密样例的私钥、公钥、k、C1、C2、C3
Signature*Hex 官方签名样例的示例曲线参数、ID、ZA、e 等
Sm3Sample1HashHex / Sm3Sample2HashHex SM3 官方测试向量

密文与公钥格式说明

密文结构

格式 结构 何时使用
C1C3C2 C1(65) ‖ C3(32) ‖ C2(klen) 默认,isNewFormat = true
C1C2C3 C1(65) ‖ C2(klen) ‖ C3(32) 旧格式,isNewFormat = false
  • C1 是椭圆曲线点 [k]G,按国密标准编码为未压缩点 04 ‖ x ‖ y,共 65 字节;
  • C2 是密文主体,长度与明文相同;
  • C3 是 32 字节 SM3 完整性校验码,解密时会校验,不通过则抛 CryptographicException。

对接提醒: 与外部系统对接时必须先确认对方的 C1 是否带 0x04 前缀、C2/C3 的先后顺序。 本包加密时始终输出标准的 65 字节带前缀 C1;解密时会自动兼容省略 0x04 的 64 字节 C1 形式。

公钥结构

格式 长度 结构 说明
未压缩 65 04 ‖ x(32) ‖ y(32) 需求中所述的"04 开头原始公钥"
压缩 33 02/03 ‖ x(32) 前缀 02 表示 y 为偶数、03 为奇数

两种格式可无损互转,本包的所有接口(加密、验签)都同时接受两种格式。

注意事项

  • 命名空间:本包命名空间为 Ailaibo.CSharp,主类 SM2 的完整类型名为 Ailaibo.CSharp.SM2。 该命名空间与配套的 Ailaibo.CSharp.SM3 包共用,两个包同时引用不会冲突(类名不重叠)。
  • 明文不能为空:Encrypt / Sign / Verify / ComputeDigest 对空字节数组会抛 ArgumentException; null 参数抛 ArgumentNullException。
  • 私钥取值范围:必须是 [1, n-2] 内的大整数。上限取 n-2 而非 n-1,是因为签名需要计算 (1+d) 的模逆, 而 d = n-1 时 1+d ≡ 0,逆元不存在。
  • 文本一律 UTF-8:userId 字符串按 UTF-8 编码。若约定的是其它编码或二进制 ID, 请改用 SignWithId / VerifyWithId 直接传入原始字节。
  • 签名是随机化的:同一数据两次签名结果不同,这是正常行为;验签只关心是否通过。
  • 加密是概率加密:同一明文两次加密得到的密文不同,切勿通过比较密文判断明文是否相同。
  • 用户 ID 必须双方一致:ZA 把用户 ID 与公钥绑定进签名,验签方使用不同的 ID 必然失败。 未指定时双方都使用标准默认值 "1234567812345678"。
  • 侧信道限制:本实现基于 BigInteger,运算时间与操作数取值相关,属于非恒定时间实现, 不具备抗计时 / 功耗等侧信道攻击能力。适用于业务系统加解密与签名验签; 若用于智能卡、金融 IC 卡等攻击者能精确测量运算耗时的环境,请改用经国密认证的硬件密码模块。
  • 已废弃用法:国密算法存在多种"盐值/ID"约定与 ASN.1 DER 编码签名格式(SM2Signature ::= SEQUENCE { R, S })。 本包输出的是 64 字节裸 R ‖ S,不包含 ASN.1 包装;若对接方要求 DER 编码,请自行封装。

版本历史

版本 说明
1.0.0 首个发布版本:SM2 纯托管实现,含密钥对生成、C1C3C2 / C1C2C3 双格式加解密、SM3 摘要签名验签、自定义用户 ID、公钥压缩解压缩,内置 GM/T 0003.5-2012 官方测试向量。

许可与支持

MIT 许可。如需商业授权或技术支持,请联系作者 Chu Lijia(Beijing iLab mobile Co,.Ltd)。

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net40 is compatible.  net403 was computed.  net45 was computed.  net451 was computed.  net452 is compatible.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.0

    • No dependencies.
  • .NETFramework 4.5.2

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 134 9/21/2026