国密SM2非对称算法与实现

国密SM2非对称算法与实现


介绍

国密SM2是非对称密码算法,是基于ECC算法的非对称算法。SM2算法标准已公布,有兴趣的可下载文档学习。
国密SM2算法标准包括4个部分,
-第1部分为总则,主要介绍了ECC基本的算法描述,包括素数域和二元扩域两种算法描述
-第2部分为数字签名算法,这个算法不同于ECDSA算法,其计算量大,也比ECDSA复杂些,也许这样会更安全吧
-第3部分为密钥交换协议,与ECDH功能相同,但复杂性高,计算量加大
-第4部分为公钥加密算法,使用ECC公钥进行加密和ECC私钥进行加密算法,其实现上是在ECDH上分散出流密钥,之后与明文或者是密文进行异或运算,并没有采用第3部分的密钥交换协议产生的密钥。
对于SM2算法的总体感觉,应该是国家发明,其计算上比国际上公布的ECC算法复杂,相对来说算法速度可能慢,但可能是更安全一点。

SM2标准还公布了一条建议的256位的ECC曲线,但没有在国际上被公认。SM2算法是好,但要使用,又有很多障碍,就是统一的国际标识与互认,如算法没有OID标识,曲线也没有公认OID标识,这在通用上就大打折扣了,这一点需要考虑的。


调研实现

网上可以查到一些SM2算法的实现代码,有C#的、有Java的,还有C的,但想找到一个完整的C语言代码还是很难,人家做了不公开,算法标准都公开的,代码不开源啊,但比较有意义的是这些代码都是使用Openssl或bouncycastle这些开源的算法库实现的。但至少给你个信息,使用开源密码算法可以实现SM2算法。

要实现SM2算法,首先要实现ECC曲线基本描述,这个要独立去写还是需要很多计算算法能力的,不是搞数学的,还是有许多难度的。Openssl的ECC算法是SUN公司奉献的,大家就是大家,写的就是好。Bouncycastle也是一个比较好的算法,有Java版和C#版,网上可以得到C#的SM2算法,但是使用c语言的代码能够下载的SM2都有一点骗人感情啊,只给了代码测试运行包,没有公开源码。

笔者按着这些信息,细细分析了Openssl的ECC、ECDSA、ECDH算法,可以作为基础用来实现SM2是豪无问题的,待代码进一步完善后可以与大家分享。

最后说一下,RSA与ECC。这两位都是目前主流的非对称加密算法,也代表了2大加密算法难题,一个是大素数分解,一个离散对数难题。RSA的模长在不断的加大,1024不可用了,要用2048,这计算量啊要求也大,就需要使用计算量小的ECC算法,但RSA已大行其道这么多年,还不会马上被ECC所替换,ECC使用也很复杂,要定义多种曲线,要管理这些参数曲线,否则很难互通,还有专利的限制等等。ECC的加密算法也不同于RSA,有公钥加密和私钥解密,而RSA加解密都有啊。不论是RSA还是ECC都是计算上的复杂,随着时间,密钥长度都将加长,这就需要有更好的密码算法来替代了。也许不需要等到那一天,人类社会发展会非常完善,不需要密码了,是个完全透明的、可信任的社会了。


实现

使用Openssl实现的SM2算法代码如下: [ 算法实现演示 ],也可请参考ecc资料


参考

在计算点是否满足方程时,openssl存在依据x查找y时的参数设置,可以参考说明,补充一点个人理解,y存在正负,但是在有限域表示时均为两个整数,在点的分布图上观察可以清晰看出这一点。


  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
C# 是一种通用的编程语言,可以用来开发各种类型的应用程序,包括使用国密SM2非对称算法进行加密和解密操作。 要在C#中使用国密SM2算法,你可以使用BouncyCastle库。BouncyCastle是一个流行的密码学库,提供了各种加密算法实现,包括SM2。 首先,你需要将BouncyCastle库添加到你的项目中。你可以通过NuGet包管理器或手动下载并添加引用。 下面是一个使用C#和BouncyCastle库实现SM2加密和解密的示例代码: ```csharp using System; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; public class SM2Example { public static void Main() { // 生成SM2密钥对 AsymmetricCipherKeyPair keyPair = GenerateKeyPair(); // 获取公钥和私钥 ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters)keyPair.Private; ECPublicKeyParameters publicKey = (ECPublicKeyParameters)keyPair.Public; // 要加密的明文 string plaintext = "Hello, SM2!"; // 使用公钥进行加密 byte[] ciphertext = Encrypt(publicKey, plaintext); // 使用私钥进行解密 string decryptedText = Decrypt(privateKey, ciphertext); Console.WriteLine("Plaintext: " + plaintext); Console.WriteLine("Ciphertext: " + Convert.ToBase64String(ciphertext)); Console.WriteLine("Decrypted text: " + decryptedText); } // 生成SM2密钥对 public static AsymmetricCipherKeyPair GenerateKeyPair() { ECKeyPairGenerator keyPairGenerator = GeneratorUtilities.GetKeyPairGenerator("SM2"); keyPairGenerator.Init(new ECKeyGenerationParameters(SM2NamedCurves.GetByName("sm2p256v1"), new SecureRandom())); return keyPairGenerator.GenerateKeyPair(); } // 使用公钥进行加密 public static byte[] Encrypt(ECPublicKeyParameters publicKey, string plaintext) { IBasicAgreement agreement = AgreementUtilities.GetBasicAgreement("SM2"); agreement.Init(publicKey); byte[] input = System.Text.Encoding.UTF8.GetBytes(plaintext); byte[] output = agreement.CalculateAgreement(publicKey.Q).ToByteArrayUnsigned(); return output; } // 使用私钥进行解密 public static string Decrypt(ECPrivateKeyParameters privateKey, byte[] ciphertext) { IBasicAgreement agreement = AgreementUtilities.GetBasicAgreement("SM2"); agreement.Init(privateKey); byte[] input = new byte[ciphertext.Length]; Array.Copy(ciphertext, input, ciphertext.Length); BigInteger sharedSecret = new BigInteger(1, input); byte[] output = agreement.CalculateAgreement(privateKey.D, sharedSecret).ToByteArrayUnsigned(); return System.Text.Encoding.UTF8.GetString(output); } } ``` 这个示例代码演示了如何生成SM2密钥对,并使用公钥进行加密,私钥进行解密。注意,在实际应用中,你需要妥善保管私钥,确保安全性。 希望这可以帮助到你!如果有任何问题,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值