国密SM2密码算法的C语言实现
基于Java语言的国密SM2SM3SM4算法库,包含加密解密、签名验签、摘要计算的实现代码。。。

基于Java语⾔的国密SM2SM3SM4算法库,包含加密解密、签名验签、摘要计算的实现代码。
SM2_SM3_SM4Encrypt项⽬介绍最近有⼀个项⽬需要⽤到国密算法 , 具体是需要对接硬件加密机调⽤加密机的JAVA接⼝实现国密的⼀整套流程 , 但是由于公司测试环境和阿⾥云硬件加密机不通 , 所以只能⾃⼰模拟加密机的接⼝实现⼀套国密的软加密实现。
将有关国密的代码提取并分享出来 , 并且提供了详细的测试代码以供参考。
项⽬中包括SM2算法的加密/解密/签名/验签 , SM3算法的摘要计算 , SM4算法的对称加密/解密 , 以及相应算法的公私钥对的⽣成⽅法。
项⽬测试脚本使⽤在项⽬中的test包下SecurityTestAll.java类中的main⽅法下有SM2/SM3/SM4的按照加解密流程实现的⼀整套测试脚本 , 直接直接执⾏可以输出如下测试结果:--产⽣SM2秘钥--:公钥:04ec7e40b8dfa4b14383f703ec5403b71db0ab505b9fc41f0df45a9910a307dfbd5b3c5afdd4b90d79fa0ab70d53fd88422df77e09b254a53e72b4857f74ab1da4私钥:58967e2beb6fffd3c96545eebd3000b39c10087d48faa0d41f9c7bf3720e0ea4--测试加密开始--原⽂UTF-8转hex:49204c6f766520596f75加密:密⽂:1b40e51d8462d97ac1cc9929039313152b8067eecfcff7ba0348a721d3f4d257e83f924364b84147879906d62a72472403a3c3d36d4cf243055ff77a4c794909673cc0e39954fbc8b01c50a4b708216d4d19c400719734b98bc0a6d7da92a078b6ef8dd971解密:I Love You--测试加密结束----测试SM2签名--原⽂hex:49204c6f766520596f75签名测试开始:软加密签名结果:3046022100d2665f92221efd00aa96d2729475aa05690bd10766641fd169c6e13c1a441b87022100c8ff9f00c7bb0a8308e183629cebef53e4fd65542c7ee6068275a606e3010088加密机签名结果:d2665f92221efd00aa96d2729475aa05690bd10766641fd169c6e13c1a441b87c8ff9f00c7bb0a8308e183629cebef53e4fd65542c7ee6068275a606e3010088验签1,软件加密⽅式:软件加密⽅式验签结果:true验签2,硬件加密⽅式:签名R:d2665f92221efd00aa96d2729475aa05690bd10766641fd169c6e13c1a441b87签名S:c8ff9f00c7bb0a8308e183629cebef53e4fd65542c7ee6068275a606e3010088硬件加密⽅式验签结果:true--签名测试结束----SM3摘要测试--hash:700B1D31B7BF81A3CE2B5AC97057AE783C9C51F56FA4EA14E13CF3EC6E58159A--SM3摘要结束----⽣成SM4秘钥--sm4Key:c8e8e733ac8c4043a1d6464ae82d70e6--⽣成SM4结束----SM4的CBC加密--密⽂:046be2948f89c9f78e9248fc562a9d0cCBC解密解密结果:I Love You--ECB加密--ECB密⽂:851b68592ac1a029976204ef66f62a5dECB解密ECB解密结果:I Love You下⾯将会说明使⽤此加解密包会遇到的问题以及解决⽅案 , 没有发现的问题后续还会做补充。
面向SOC的SM2加解密算法的实现

面向SOC的SM2加解密算法的实现随着信息技术的高速发展,网络安全成为了一个日益重要的话题,加密算法也成为了保证网络安全的重要手段之一。
在众多的加密算法中,SM2被广泛应用于数字证书、电子邮件、电子签名等领域。
SM2加解密算法是一种基于椭圆曲线密码学的公开密钥算法,它采用了国密标准体系,适用于中国特有的政府、金融、电信、物联网等领域。
实现面向SOC的SM2加解密算法,则需要对SM2算法进行一定程度的优化,并将其应用于SOC芯片等具有特定用途的计算平台上。
为了展示SM2加解密算法的优秀性能和广泛应用,以下列举了三个面向SOC的SM2加解密算法的实现案例。
1. 基于ARM处理器的SM2算法实现该案例使用ARM Cortex-M系列处理器实现了SM2算法的加解密和签名验签功能。
通过对SM2算法中的模幂、模乘等运算进行优化,使其在ARM芯片上运行效率更高。
同时,该实现还采用了硬件加速模块,进一步提升了SM2算法的加解密速度,使其适用于低功耗、高效率的物联网设备。
2. 基于Xilinx FPGA的SM2算法实现该案例使用Xilinx FPGA芯片实现了SM2算法的加解密和签名验签功能。
利用FPGA芯片的可编程性,将SM2算法中的运算模块进行并行化,进一步提高了算法的性能。
同时,该实现还采用了FPGA芯片的硬核模块,将SM2算法中的乘法运算转化为硬件实现,使其运行效率更高。
3. 基于高通骁龙处理器的SM2算法实现该案例使用高通骁龙处理器实现了SM2算法的加解密和签名验签功能。
通过对SM2算法中的运算模块进行SIMD优化,使其能够更好地利用处理器中的多核心,提高算法的运行速度。
同时,该实现还采用了高通骁龙处理器上的硬件安全保护模块,加强了SM2算法在处理器上的安全性。
总之,面向SOC的SM2加解密算法的实现具有高效、安全、广泛应用等特点,可应用于物联网、金融、政府等多个领域,有效保障了信息的安全性。
同时,随着物联网和5G技术的发展,对SM2算法的要求也越来越高,需要在保证安全性的同时,考虑到处理器的低功耗、高效率等需求。
bouncycastle(BC)实现SM2国密加解密、签名、验签

bouncycastle(BC)实现SM2国密加解密、签名、验签SM2国密加解密⼀个类就够了<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.65</version></dependency>版本库经测试适⽤(1.61-1.68) 如有问题请留⾔纠正本⽂参考博主「RisenMyth」:https:///RisenMyth/article/details/107212156若要使⽤⽼版本的写法可以参考 https:///fenglongmiao/article/details/79501757import org.bouncycastle.asn1.gm.GMNamedCurves;import org.bouncycastle.asn1.gm.GMObjectIdentifiers;import org.bouncycastle.asn1.x9.X9ECParameters;import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.bouncycastle.jce.spec.ECParameterSpec;import org.bouncycastle.jce.spec.ECPrivateKeySpec;import org.bouncycastle.jce.spec.ECPublicKeySpec;import org.bouncycastle.math.ec.ECPoint;import org.bouncycastle.util.encoders.Hex;import ponent;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import java.io.ByteArrayInputStream;import java.math.BigInteger;import java.security.*;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.security.spec.ECGenParameterSpec;import java.security.spec.InvalidKeySpecException;import java.util.Base64;/*** bcprov-jdk15on 版本适⽤(1.61-1.68)* @author dashou* @date 2021-4-13*/@Componentpublic class SM2Util {private BouncyCastleProvider provider;// 获取SM2相关参数private X9ECParameters parameters;// 椭圆曲线参数规格private ECParameterSpec ecParameterSpec;// 获取椭圆曲线KEY⽣成器private KeyFactory keyFactory;private SM2Util(){try {provider = new BouncyCastleProvider();parameters = GMNamedCurves.getByName("sm2p256v1");ecParameterSpec = new ECParameterSpec(parameters.getCurve(),parameters.getG(), parameters.getN(), parameters.getH());keyFactory = KeyFactory.getInstance("EC", provider);} catch (Exception e) {e.printStackTrace();}}/*** SM2算法⽣成密钥对** @return密钥对信息*/public KeyPair generateSm2KeyPair() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");// 获取⼀个椭圆曲线类型的密钥对⽣成器final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", provider);SecureRandom random = new SecureRandom();// 使⽤SM2的算法区域初始化密钥⽣成器kpg.initialize(sm2Spec, random);// 获取密钥对KeyPair keyPair = kpg.generateKeyPair();return keyPair;}/*** 加密** @param input 待加密⽂本* @param pubKey 公钥* @return*/public String encode(String input, String pubKey)throws NoSuchPaddingException, NoSuchAlgorithmException,BadPaddingException, IllegalBlockSizeException,InvalidKeySpecException, InvalidKeyException {// 获取SM2相关参数X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");// 椭圆曲线参数规格ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());// 将公钥HEX字符串转换为椭圆曲线对应的点ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(pubKey));// 获取椭圆曲线KEY⽣成器KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);BCECPublicKey key = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));// 获取SM2加密器Cipher cipher = Cipher.getInstance("SM2", provider);// 初始化为加密模式cipher.init(Cipher.ENCRYPT_MODE, key);// 加密并编码为base64格式return Base64.getEncoder().encodeToString(cipher.doFinal(input.getBytes()));}/*** 解密** @param input 待解密⽂本* @param prvKey 私钥* @return*/public byte[] decoder(String input, String prvKey) throws NoSuchPaddingException, NoSuchAlgorithmException,InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {// 获取SM2加密器Cipher cipher = Cipher.getInstance("SM2", provider);// 将私钥HEX字符串转换为X值BigInteger bigInteger = new BigInteger(prvKey, 16);BCECPrivateKey privateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger,ecParameterSpec));// 初始化为解密模式cipher.init(Cipher.DECRYPT_MODE, privateKey);// 解密return cipher.doFinal(Base64.getDecoder().decode(input));}/*** 签名** @param plainText 待签名⽂本* @param prvKey 私钥* @return* @throws NoSuchAlgorithmException* @throws InvalidKeySpecException* @throws InvalidKeyException* @throws SignatureException*/public String sign(String plainText, String prvKey) throws NoSuchAlgorithmException, InvalidKeySpecException,InvalidKeyException, SignatureException {// 创建签名对象Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), provider);// 将私钥HEX字符串转换为X值BigInteger bigInteger = new BigInteger(prvKey, 16);BCECPrivateKey privateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger,ecParameterSpec));// 初始化为签名状态signature.initSign(privateKey);// 传⼊签名字节signature.update(plainText.getBytes());// 签名return Base64.getEncoder().encodeToString(signature.sign());}public boolean verify(String plainText, String signatureValue, String pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {// 创建签名对象Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), provider);// 将公钥HEX字符串转换为椭圆曲线对应的点ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(pubKey));BCECPublicKey key = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));// 初始化为验签状态signature.initVerify(key);signature.update(plainText.getBytes());return signature.verify(Base64.getDecoder().decode(signatureValue));}/*** 证书验签** @param certStr 证书串* @param plaintext 签名原⽂* @param signValueStr 签名产⽣签名值此处的签名值实际上就是 R和S的sequence* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws SignatureException*/public boolean certVerify(String certStr, String plaintext, String signValueStr)throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, CertificateException {byte[] signValue = Base64.getDecoder().decode(signValueStr);/** 解析证书*/CertificateFactory factory = new CertificateFactory();X509Certificate certificate = (X509Certificate) factory.engineGenerateCertificate(new ByteArrayInputStream(Base64.getDecoder().decode(certStr)));// 验证签名Signature signature = Signature.getInstance(certificate.getSigAlgName(), provider);signature.initVerify(certificate);signature.update(plaintext.getBytes());return signature.verify(signValue);}public static void main(String[] args) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {String str = "看看能不能⼀次通过";SM2Util sm2 = new SM2Util();KeyPair keyPair = sm2.generateSm2KeyPair();BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate();BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic();// 拿到密钥String pubKey = new String(Hex.encode(publicKey.getQ().getEncoded(true)));String prvKey = privateKey.getD().toString(16);System.out.println("Private Key: " + prvKey);System.out.println("Public Key: " + pubKey);// 加解密测试try {System.out.println("加密前:" + str);String encode = sm2.encode(str, pubKey);System.out.println("加密后:" + encode);String decoder = new String(sm2.decoder(encode, prvKey));System.out.println("解密后:" + decoder);} catch (Exception e) {System.out.println("加解密测试错误");}// 签名和验签测试try {System.out.println("签名源数据:" + str);String signStr = sm2.sign(str, prvKey);System.out.println("签名后数据:" + signStr);boolean verify = sm2.verify(str, signStr, pubKey);System.out.println("签名验证结果:" + verify);} catch (Exception e) {System.out.println("签名和验签测试错误");}}}。
国密SM2加密算法的RCCA安全设计

国密SM2加密算法的RCCA安全设计国密SM2加密算法的RCCA安全设计摘要:随着互联网的快速发展,信息安全成为了重要的关注领域。
作为一种新兴的密码算法,国密SM2被广泛应用于加密通信领域。
然而,随着计算机技术的不断发展,攻击者的攻击手段也越来越复杂。
为了提高SM2算法的安全性,本文提出了一种RCCA安全设计策略,旨在进一步保护SM2算法免受不同类型的攻击。
1. 引言SM2算法是我国自主设计的一种椭圆曲线公钥密码算法,具有高效、安全等特点,在我国加密通信中被广泛应用。
然而,随着计算机技术和密码分析的发展,SM2算法的安全性也面临着新的威胁。
2. SM2算法简介SM2算法基于椭圆曲线离散对数问题,主要包括密钥生成、加密和解密三个过程。
其中,密钥生成过程中使用了随机数生成算法;加密过程使用了随机数生成算法和点压缩算法;解密过程使用了椭圆曲线点恢复算法。
3. RCCA安全设计策略为了进一步提高SM2算法的安全性,本文提出了RCCA (Random Oracle ConvIncability against Chosen-Ciphertext Attacks)安全设计策略。
该策略主要包括以下几个方面的设计:3.1 随机数的生成与保密在SM2算法的密钥生成、加密和解密过程中,随机数的生成非常重要。
为了保证随机数的安全性,可以采用硬件随机数生成器和伪随机数生成器相结合的方式。
同时,需要确保生成的随机数在传输和存储过程中的保密性,可以采用加密传输和存储等措施。
3.2 密钥的保护与管理密钥是SM2算法安全性的关键因素,因此密钥的保护与管理非常重要。
可以采用密钥集中存储和密钥分散存储相结合的方式,将密钥分散存储在多个地方,以提高密钥的安全性。
同时,还可以使用密码学方法对密钥进行加密和保护。
3.3 对抗选择密文攻击选择密文攻击是一种常见的密码攻击方法,为了对抗这种攻击方式,可以采用密文检验和验证机制。
密文检验可以通过对密文的合法性和完整性进行验证,以识别篡改的密文。
sm2 C语言实现加密算法详解教程

SM2算法1、公钥密码算法介绍消息鉴别:是一个证实收到的消息来自可信的源点并且未被篡改的过程。
它的目的是信源识别,保证信息完整性。
数字签名:是一种确保数据完整性和非否认的手段,通过给消息附加一段数据来实现。
公钥密码学与其他密码学完全不同, 使用这种方法的加密系统,不仅公开加密算法本身,也公开了加密用的密钥。
公钥密码系统与只使用一个密钥的对称传统密码不同,算法是基于数学函数而不是基于替换和置换。
公钥密码学是非对称的,它使用两个独立的密钥,即密钥分为公钥和私钥,因此称双密钥体制。
双钥体制的公钥可以公开,因此称为公钥算法。
公钥算法的出现,给密码的发展开辟了新的方向。
公钥算法虽然已经历了20多年的发展,但仍具有强劲的发展势头,在鉴别系统和密钥交换等安全技术领域起着关键的作用公钥算法的加密与解密由不同的密钥完成,并且从加密密钥得到解密密钥在计算上是不可行的。
通常,公钥算法的两个密钥中任何一个都可以作为加密而另一个用作解密,但不是所有的公钥算法都是如此。
2. SM2椭圆曲线公钥密码算法SM2算法就是ECC椭圆曲线密码机制,但在签名、密钥交换方面不同于ECDSA、ECDH等国际标准,而是采取了更为安全的机制。
另外,SM2推荐了一条256位的曲线作为标准曲线。
SM2标准包括总则,数字签名算法,密钥交换协议,公钥加密算法四个部分,并在每个部分的附录详细说明了实现的相关细节及示例。
SM2算法主要考虑素域Fp和F2m上的椭圆曲线,分别介绍了这两类域的表示,运算,以及域上的椭圆曲线的点的表示,运算和多倍点计算算法。
然后介绍了编程语言中的数据转换,包括整数和字节串,字节串和比特串,域元素和比特串,域元素和整数,点和字节串之间的数据转换规则。
详细说明了有限域上椭圆曲线的参数生成以及验证,椭圆曲线的参数包括有限域的选取,椭圆曲线方程参数,椭圆曲线群基点的选取等,并给出了选取的标准以便于验证。
最后给椭圆曲线上密钥对的生成以及公钥的验证,用户的密钥对为(s,sP),其中s为用户的私钥,sP为用户的公钥,由于离散对数问题从sP难以得到s,并针对素域和二元扩域给出了密钥对生成细节和验证方式。
国密算法SM2证书制作

国密算法SM2证书制作原⽂:前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备⼤都同时⽀持RSA和SM2算法,只是应⽤系统的加解密签名验证需要修改,这个更改底层调⽤的加密动态库来,原来RSA⽤的对称加密算法DES(AES)和摘要MD5(SHA1)也相应改变,分别对应SM1、SM3算法,SM1算法基于硬件实现,SM2、SM3算法已公开。
SM2签名验证算法SM2签名同样也是需要先摘要原⽂数据,即先使⽤SM3密码杂凑算法计算出32byte摘要。
SM3需要摘要签名⽅ID(默认1234567812345678)、曲线参数a,b,Gx,Gy、共钥坐标(x,y)计算出Z值,然后再杂凑原⽂得出摘要数据。
这个地⽅要注意曲线参数和坐标点都是32byte,在转换为BigInteger⼤数计算转成字节流时要去掉空补位,否则可能会出现摘要计算不正确的问题。
SM2签名实现如下:[java]1. public static BigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair)2. {3. SM3Digest sm3 = new SM3Digest();4.5. ECPublicKeyParameters ecpub = (ECPublicKeyParameters)keypair.Public;6.7. byte[] z = SM2CryptoServiceProvider.Sm2GetZ(Encoding.Default.GetBytes(erId), ecpub.Q);8. sm3.BlockUpdate(z, 0, z.Length);9.10. byte[] p = md;11. sm3.BlockUpdate(p, 0, p.Length);12.13. byte[] hashData = new byte[32];14. sm3.DoFinal(hashData, 0);15.16. // e17. BigInteger e = new BigInteger(1, hashData);18. // k19. BigInteger k = null;20. ECPoint kp = null;21. BigInteger r = null;22. BigInteger s = null;23. BigInteger userD = null;24.25. do26. {27. do28. {29.30. ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)keypair.Private;31. k = ecpriv.D;32. kp = ecpub.Q;33.34. userD = ecpriv.D;35.36. // r37. r = e.Add(kp.X.ToBigInteger());38. r = r.Mod(ecc_n);39. }40. while (r.Equals(BigInteger.Zero) || r.Add(k).Equals(ecc_n));41.42. // (1 + dA)~-143. BigInteger da_1 = userD.Add(BigInteger.One);44. da_1 = da_1.ModInverse(ecc_n);45. // s46. s = r.Multiply(userD);47. s = k.Subtract(s).Mod(ecc_n);48. s = da_1.Multiply(s).Mod(ecc_n);49. }50. while (s.Equals(BigInteger.Zero));51.52. byte[] btRS = new byte[64];53. byte[] btR = r.ToByteArray();54. byte[] btS = s.ToByteArray();55. Array.Copy(btR, btR.Length - 32, btRS, 0, 32);56. Array.Copy(btS, btS.Length - 32, btRS, 32, 32);57.58. return new BigInteger[] { r, s };59. }SM2算法是基于ECC算法的,签名同样返回2个⼤数,共64byte。
[转]国密SM2非对称算法与实现
![[转]国密SM2非对称算法与实现](https://img.taocdn.com/s3/m/cb58f179a88271fe910ef12d2af90242a895ab35.png)
[转]国密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是豪⽆问题的,待代码进⼀步完善后可以与⼤家分享。
SM2加解密代码示例

SM2加解密代码⽰例pom.xml<!--国密--><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version></dependency>1、Cipherimport org.bouncycastle.crypto.AsymmetricCipherKeyPair;import org.bouncycastle.crypto.digests.SM3Digest;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.math.ec.ECPoint;import java.math.BigInteger;public class Cipher {private int ct;private ECPoint p2;private SM3Digest sm3keybase;private SM3Digest sm3c3;private byte key[];private byte keyOff;public Cipher(){this.ct = 1;this.key = new byte[32];this.keyOff = 0;}private void Reset(){this.sm3keybase = new SM3Digest();this.sm3c3 = new SM3Digest();byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());this.sm3keybase.update(p, 0, p.length);this.sm3c3.update(p, 0, p.length);p = Util.byteConvert32Bytes(p2.getY().toBigInteger());this.sm3keybase.update(p, 0, p.length);this.ct = 1;NextKey();}private void NextKey(){SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);sm3keycur.update((byte) (ct >> 24 & 0xff));sm3keycur.update((byte) (ct >> 16 & 0xff));sm3keycur.update((byte) (ct >> 8 & 0xff));sm3keycur.update((byte) (ct & 0xff));sm3keycur.doFinal(key, 0);this.keyOff = 0;this.ct++;}public ECPoint Init_enc(SM2 sm2, ECPoint userKey){AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();BigInteger k = ecpriv.getD();ECPoint c1 = ecpub.getQ();this.p2 = userKey.multiply(k);Reset();return c1;}public void Encrypt(byte data[]){this.sm3c3.update(data, 0, data.length);for (int i = 0; i < data.length; i++)if (keyOff == key.length){NextKey();}data[i] ^= key[keyOff++];}}public void Init_dec(BigInteger userD, ECPoint c1){this.p2 = c1.multiply(userD);Reset();}public void Decrypt(byte data[]){for (int i = 0; i < data.length; i++){if (keyOff == key.length){NextKey();}data[i] ^= key[keyOff++];}this.sm3c3.update(data, 0, data.length);}public void Dofinal(byte c3[]){byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());this.sm3c3.update(p, 0, p.length);this.sm3c3.doFinal(c3, 0);Reset();}}2、SM2import org.bouncycastle.crypto.generators.ECKeyPairGenerator;import org.bouncycastle.crypto.params.ECDomainParameters;import org.bouncycastle.crypto.params.ECKeyGenerationParameters;import org.bouncycastle.math.ec.ECCurve;import org.bouncycastle.math.ec.ECFieldElement;import org.bouncycastle.math.ec.ECFieldElement.Fp;import org.bouncycastle.math.ec.ECPoint;import java.math.BigInteger;import java.security.SecureRandom;public class SM2 {//国密参数public static String[] ecc_param = {"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7","BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"};public static SM2 Instance() {return new SM2();}/** 素数p */public final BigInteger ecc_p;/** 系数a */public final BigInteger ecc_a;/** 系数b */public final BigInteger ecc_b;/** 基点G, G=(xg,yg),其介记为n */public final BigInteger ecc_n;/** 坐标x */public final BigInteger ecc_gx;/** 坐标y */public final BigInteger ecc_gy;public final ECCurve ecc_curve;public final ECPoint ecc_point_g;public final ECDomainParameters ecc_bc_spec;public final ECKeyPairGenerator ecc_key_pair_generator;public final ECFieldElement ecc_gx_fieldelement;public final ECFieldElement ecc_gy_fieldelement;this.ecc_a = new BigInteger(ecc_param[1], 16);this.ecc_b = new BigInteger(ecc_param[2], 16);this.ecc_n = new BigInteger(ecc_param[3], 16);this.ecc_gx = new BigInteger(ecc_param[4], 16);this.ecc_gy = new BigInteger(ecc_param[5], 16);this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);ECKeyGenerationParameters ecc_ecgenparam;ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());this.ecc_key_pair_generator = new ECKeyPairGenerator();this.ecc_key_pair_generator.init(ecc_ecgenparam);}}3、SM2EncDecUtilsimport org.bouncycastle.crypto.AsymmetricCipherKeyPair;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.math.ec.ECPoint;import java.io.IOException;import java.math.BigInteger;import java.util.HashMap;import java.util.Map;public class SM2EncDecUtils {public static final String public_key = "public_key";public static final String private_key = "private_key";public static void main(String[] args) throws Exception {singleThreadTest();//mutiThreadTest();}// ⽣成随机秘钥对public static Map<String, String> generateKeyPair() {SM2 sm2 = SM2.Instance();AsymmetricCipherKeyPair key = null;while (true) {key = sm2.ecc_key_pair_generator.generateKeyPair();if (((ECPrivateKeyParameters) key.getPrivate()).getD().toByteArray().length == 32) {break;}}ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();BigInteger privateKey = ecpriv.getD();ECPoint publicKey = ecpub.getQ();String pubk = Util.byteToHex(publicKey.getEncoded());String prik = Util.byteToHex(privateKey.toByteArray());System.out.println("公钥: " + pubk);System.out.println("公钥长度: " + pubk.length());System.out.println("私钥: " + prik);System.out.println("私钥长度: " + prik.length());Map<String, String> result = new HashMap<>();result.put(public_key, pubk);result.put(private_key, prik);return result;}// 数据加密public static String encrypt(byte[] publicKey, byte[] data) throws IOException {if (publicKey == null || publicKey.length == 0) {return null;}if (data == null || data.length == 0) {return null;}System.arraycopy(data, 0, source, 0, data.length);Cipher cipher = new Cipher();SM2 sm2 = SM2.Instance();ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);ECPoint c1 = cipher.Init_enc(sm2, userKey);cipher.Encrypt(source);byte[] c3 = new byte[32];cipher.Dofinal(c3);return new StringBuffer(Util.byteToHex(c1.getEncoded())).append(Util.byteToHex(c3)).append(Util.byteToHex(source)).toString();}// 数据解密public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {if (privateKey == null || privateKey.length == 0) {return null;}if (encryptedData == null || encryptedData.length == 0) {return null;}// 加密字节数组转换为⼗六进制的字符串长度变为encryptedData.length * 2String data = Util.byteToHex(encryptedData);byte[] c1Bytes = Util.hexToByte(data.substring(0, 130));int c2Len = encryptedData.length - 97;byte[] c3 = Util.hexToByte(data.substring(130, 130 + 64));byte[] c2 = Util.hexToByte(data.substring(194, 194 + 2 * c2Len));SM2 sm2 = SM2.Instance();BigInteger userD = new BigInteger(1, privateKey);// 通过C1实体字节来⽣成ECPointECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);Cipher cipher = new Cipher();cipher.Init_dec(userD, c1);cipher.Decrypt(c2);cipher.Dofinal(c3);// 返回解密结果return c2;}/*** 单线程* @throws Exception*/private static void singleThreadTest() throws Exception {String plainText = "张三123zhangsan";//获取⽂本内容的字节数byte[] sourceData = plainText.getBytes();// ⽣成随机秘钥对Map<String, String> keymap = generateKeyPair();//获取当前系统时间long start = System.currentTimeMillis();int counts = 100000;for (int j = 0; j < counts; j++) {//数据加密+⼗六进制串转化为byte数组//本本转字节--⽣成随机密钥对--得到公钥---⼗六进制串转化为byte数组--数据加密String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(keymap.get(public_key)), sourceData);System.out.println("加密前长度: " + plainText.length() + " ;加密后长度: " + cipherText.length());System.out.println("加密前原⽂本内容:" + plainText );System.out.println("加密后⽂本内容:" + cipherText);String plainTextEncripted = new String(SM2EncDecUtils.decrypt(Util.hexToByte(keymap.get(private_key)), Util.hexToByte(cipherText))); System.out.println("解密后⽂本内容: " + plainTextEncripted);if (plainText.equals(plainTextEncripted)) {System.out.println("------解密后同原⽂是否⼀致: " + plainText.equals(plainTextEncripted) + "----------------------");}}long end = System.currentTimeMillis();System.out.println("平均耗时:" + (end - start) / counts + "ms。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
国密SM2密码算法的C语言实现
作者:邢维哲
来源:《中国新通信》2017年第18期
【摘要】 N.Koblitz和ler在1985年各自独立地提出将椭圆曲线应用于公钥密码系统。
SM2椭圆曲线密码算法是国家密码管理局批准的一组算法,在电力自动化通讯中得到了广泛应用。
本文介绍了SM2椭圆曲线公钥密码算法和加密解密算法中一部分过程的C语言实现。
【关键词】椭圆曲线 SM2 密码算法公钥加密解密
Implementation of Public Key Cryptographic Algorithm SM2 based on C language XINGWEIZHE (1. XINGWEIZHE COLLEGE OF ENGINEERING, PEKING UNIVERSITY,BEIJING,100871)
Abstract: Applying elliptic curves on public key cryptosystem was put forward independently by Koblitz and ler in 1985. Public Key Cryptographic Algorithm SM2 is Public Key Cryptographic Algorithm SM2, as the Chinese national cryptographic standard, is widely used in communications of automation system. This paper introduces elliptic curve cryptosystem and gives an implementation based on C language.
Key word: elliptic curve cryptosystem; Public Key Cryptographic Algorithm SM2; elliptic curve。