在java中使用SM2算法加密时遇到的问题

1.密文组成的顺序

java服务端用的加密库是BouncyCastle,BouncyCastle中的加密数据 由C1,C2,C3组成而国密密文的正确排序是C1,C3,C2,安全芯片SM2加密处理的密文顺序也是 C1,C3,C2。

2.秘钥的标志位

BC库生成的公钥前面包含有04标志位(解密的时候需要有标志位),BC库生成的私钥前面偶尔会多加两个00(也是标志位?),记得去掉00就可以。
注:BC库使用的公钥=64个字节+1个字节(04标志位),BC库使用的私钥=32个字节。

3.验签的公钥使用

对于其他地方(例如加密芯片)传来的公钥,在进行签名验证的时候需要将公钥字符串加上一段变为未压缩状态,再构造成公钥类型进行签名验证。

4.SM2签名长度大于64个字节的原因(国密规范签名64个字节)

https://blog.csdn.net/zmnbehappy/article/details/88715431
https://bbs.csdn.net/topics/392137835
关于SM2签名,这里一定要强调一下!!!这个签名折磨我好几天,一直没有找到为什么验签是false的原因,后来偶然间才看到别人的博客说明,签名是分为硬签名和软签名的!!!硬签名就是通过硬件进行签名(例如加密芯片),软签名就是java加密库提供的签名算法。我在对加密芯片的签名进行验签时一直使用的是java库中的软签名验证算法,因此一直都是错的!!!对于硬签名校验,可以查看该博主的博客https://blog.csdn.net/hwyqb/article/details/106804978,最后通过硬签名校验方式才终于成功了。

5. SM2算法建议依赖坐标

<!-- SM2加密算法包 -->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.57</version>
</dependency>
        
<!-- Base64编码需要  -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.9</version>
</dependency>




注:SM2算法建议参考博客
签名验签:https://blog.csdn.net/q1009020096/article/details/85115698
https://blog.csdn.net/hwyqb/article/details/106804978
加解密:https://blog.csdn.net/Soul_Programmer_Swh/article/details/80375958

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是Java代码实现SM2算法加密: ```java import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.util.PrivateKeyFactory; import org.bouncycastle.crypto.util.PublicKeyFactory; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.util.encoders.Hex; import java.security.SecureRandom; public class SM2Util { // 国密推荐的椭圆曲线参数 private static final String SM2_ECC_PARAM = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; private static final String SM2_ECC_A = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"; private static final String SM2_ECC_B = "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"; private static final String SM2_ECC_GX = "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE171F6241CACD9A2ED"; private static final String SM2_ECC_GY = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"; private static final String SM2_ECC_N = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"; /** * 生成SM2公私钥对 * * @return 公私钥对 */ public static SM2KeyPair generateKeyPair() { ECDomainParameters domainParameters = new ECDomainParameters( SM2Util.getCurve(), SM2Util.getGPoint(), SM2Util.getN()); ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator(); ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(domainParameters, new SecureRandom()); keyPairGenerator.init(keyGenerationParameters); AsymmetricCipherKeyPair keyPair = keyPairGenerator.generateKeyPair(); ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters publicKeyParameters = (ECPublicKeyParameters) keyPair.getPublic(); return new SM2KeyPair(Hex.toHexString(privateKeyParameters.getD().toByteArray()), Hex.toHexString(publicKeyParameters.getQ().getEncoded(true))); } /** * 加密数据 * * @param publicKey 公钥 * @param data 待加密数据 * @return 加密结果 */ public static String encrypt(String publicKey, String data) { ECPublicKeyParameters publicKeyParameters = (ECPublicKeyParameters) PublicKeyFactory.createKey(Hex.decode(publicKey)); SM2Engine engine = new SM2Engine(); engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom())); byte[] input = data.getBytes(); byte[] output = engine.processBlock(input, 0, input.length); return Hex.toHexString(output); } /** * 解密数据 * * @param privateKey 私钥 * @param data 待解密数据 * @return 解密结果 */ public static String decrypt(String privateKey, String data) { ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters) PrivateKeyFactory.createKey(Hex.decode(privateKey)); SM2Engine engine = new SM2Engine(); engine.init(false, privateKeyParameters); byte[] input = Hex.decode(data); byte[] output = engine.processBlock(input, 0, input.length); return new String(output); } /** * 获取SM2曲线参数 */ public static ECDomainParameters getCurve() { return new ECDomainParameters( SM2Util.getCurve(), SM2Util.getGPoint(), SM2Util.getN()); } /** * 获取SM2曲线 */ private static org.bouncycastle.math.ec.ECCurve getCurve() { return new org.bouncycastle.math.ec.ECCurve.Fp( Hex.decode(SM2_ECC_PARAM), Hex.decode(SM2_ECC_A), Hex.decode(SM2_ECC_B)); } /** * 获取SM2曲线生成点G */ private static ECPoint getGPoint() { org.bouncycastle.math.ec.ECCurve curve = SM2Util.getCurve(); return curve.createPoint( new java.math.BigInteger(Hex.toHexString(SM2Util.getGx()), 16), new java.math.BigInteger(Hex.toHexString(SM2Util.getGy()), 16)); } /** * 获取SM2曲线参数N */ private static java.math.BigInteger getN() { return new java.math.BigInteger(Hex.toHexString(SM2_ECC_N), 16); } /** * 获取SM2曲线生成点Gx */ private static byte[] getGx() { return Hex.decode(SM2_ECC_GX); } /** * 获取SM2曲线生成点Gy */ private static byte[] getGy() { return Hex.decode(SM2_ECC_GY); } } ``` 其,`SM2KeyPair`为公私钥对的封装类,`generateKeyPair()`方法用于生成SM2公私钥对;`encrypt(String publicKey, String data)`方法用于加密数据,其`publicKey`为公钥,`data`为待加密数据;`decrypt(String privateKey, String data)`方法用于解密数据,其`privateKey`为私钥,`data`为待解密数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值