赞
踩
随着信息安全意识的提升,国密算法在保障数据安全方面发挥着至关重要的作用。当前趋势下,国内大部分加密机厂商均已国产算法代替了国际算法,这些厂商包括江南科友、网御星云、天融信、三未信安、山东得安、卫士通、山东渔翁、无锡江南、江南天安、江南博仁、兴唐通信、中安网脉、君众甲匠、立思辰、江南信安、山东确信、信安世纪等等。此前博主已经写了很多关于国密算法SM2、SM3、SM4的代码实现,涵盖了多种开发语言之前的互通,有兴趣的可以点击主页查看置顶博客。
再次声明,博主没有加密机的任何源码,均以伪代码代替,本篇博客主要演示讲解java代码如何实现与加密机的交互,基于1.64版本的bc算法包(其他版本可以参考博主另外一篇博客做升级降级处理,传送门java bcprov 国密 依赖 jar包 版本 升级 降级 教程),包含加密机主要功能接口,其他开发语言可以参考我之前的博客进行调整。
调用加密机的生成非对称密钥对接口,不同厂商的接口ID不一样,此处不列举接口ID。该功能接口需要指定一个密钥名称,然后返回明文hex格式公钥(不同加密机厂商可能返回编码格式有区别),密文hex格式私钥(安全性),类似于java中bcprov算法包中ECKeyPairGenerator类的generateKeyPair方法,该方法得到的AsymmetricCipherKeyPair对象,从中可以获取ECPublicKeyParameters公钥值和ECPrivateKeyParameters私钥值,再转换成hex模式。
生成密钥的代码博主在之前的代码中演示过,传送门java国密 C#国密 golang国密 NodeJS国密汇总(一),需要注意的是加密机的接口返回的明文公钥前面的标志位04大概率是去掉了的。
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.util.encoders.Hex; import java.security.SecureRandom; public class Sm2KeyPair { public static void main(String[] args) { // 初始化 ECKeyPairGenerator keyGen = new ECKeyPairGenerator(); keyGen.init(new ECKeyGenerationParameters(Sm2Params.SM2_DOMAIN_PARAMETERS, new SecureRandom())); // 生成 AsymmetricCipherKeyPair tempPair = keyGen.generateKeyPair(); // 获取对象 ECPublicKeyParameters pubParameters = (ECPublicKeyParameters) tempPair.getPublic(); ECPrivateKeyParameters pvkParameters = (ECPrivateKeyParameters) tempPair.getPrivate(); // 获取值 byte[] privateKeyBytes = pvkParameters.getD().toByteArray(); ECPoint q = pubParameters.getQ(); byte[] publicKeyBytes = q.getEncoded(false); // 转换格式 String privateKeyHex = Hex.toHexString(privateKeyBytes); System.out.println("java privateKeyHex -->" + privateKeyHex); String publicKeyHex = Hex.toHexString(publicKeyBytes); System.out.println("java publicKeyHex -->" + publicKeyHex); // 生成结果 // java privateKeyHex -->00cc5ed0948826adb773cafd4b7514f5ff35ef05bd6374f07007049fec62bca144 // java publicKeyHex -->04b5ce6fb3a4cb301b4d06f4d53a0995caf8cbdb269af30f38868a39390139daba8f1c0daab5d73c7a0de9ed02986bb404196d035005958203abd1dc9eab7c345e // 加密机接口伪代码,根据具体情况自行调整 // String keyName = "test"; // String response = 加密机.生成非对称密钥(keyName); } }
这个接口主要功能是把第三方的公钥灌入加密机,也就是上一章节中生成出来的公钥导入加密机,私钥自己留存,然后根据后续业务场景再调用签名接口或者数字信封接口(下面章节会依次讲解)。请求报文中主要上送密钥名称和hex格式公钥值,响应成功或失败相关信息。
// 加密机接口伪代码,根据具体情况自行调整
// String keyName = "test";
// String publicKey = "去掉04标志位的hex字符串";
// String response = 加密机.导入公钥(keyName, publicKey);
加密这个接口主要功能是使用对称密钥sm4Key对报文msg加密得到msgBySm4,然后使用非对称密钥sm2Key对对称密钥sm4Key加密得到sm4KeyBySm2,其中非对称密钥sm2Key就是1.2章节中生成的公钥,对称密钥sm4Key是加密机自动生成。请求报文中主要上送密钥名称、待加密的明文,响应报文中包含密文msgBySm4和密文密钥sm4KeyBySm2。解密反之,不再赘述。
此前博主分别在两篇博文中演示了sm4对称加密和sm2非对称加密,传送门java国密 C#国密 golang国密 NodeJS国密汇总(四),java国密 C#国密 golang国密 NodeJS国密汇总(二)。这里演示融合后的代码。
请仔细阅读注释和伪代码。
import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.engines.SM4Engine; import org.bouncycastle.crypto.params.*; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.util.BigIntegers; import org.bouncycastle.util.encoders.Hex; import java.math.BigInteger; import java.nio.charset.StandardCharsets; public class DETest { public static void main(String[] args) { // 私钥(标志位00) String privateKeyHex = "00cc5ed0948826adb773cafd4b7514f5ff35ef05bd6374f07007049fec62bca144"; // 公钥(自己使用时候,需要加上标志位04) String publicKeyHex = "04b5ce6fb3a4cb301b4d06f4d53a0995caf8cbdb269af30f38868a39390139daba8f1c0daab5d73c7a0de9ed02986bb404196d035005958203abd1dc9eab7c345e"; // 明文 String msg = "hello"; // 数字信封加密开始 // 加密前明文填充,PKCS7Padding,如果使用其他工具类,则无需下面这些繁琐的过程 byte[] input = msg
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。