前言:
而今你们对“国密算法代码”大体比较关怀,你们都想要学习一些“国密算法代码”的相关资讯。那么小编同时在网摘上搜集了一些对于“国密算法代码””的相关文章,希望我们能喜欢,同学们快快来了解一下吧!问题
开发中发现,我们采用Java或者NodeJS的国密SM2加密、解密、签名单边操作等正常,但是通过Nodejs加密或者生成的签名在Java下就不能解密或者不能验签。整个百度都看了,还是没有搞定通过国密算法实现前端加密、签名Java解密验签。[晕]没错,看完下面就全部都将明白。
前端部分安装国密操作依赖
npm install --save sm-crypto生成sm2公私钥
// 引入sm-cryptoconst sm2 = require("sm-crypto").sm2;// 生成密钥对let keypair = sm2.generateKeyPairHex();// 公钥publicKey = keypair.publicKey; // 私钥privateKey = keypair.privateKey;签名
注意:由于要能java解密必须配置参数hash是true,true不是默认值。
// 参数介绍(明文,私钥,配置项)// 由于要能java解密必须配置参数hash是true,true不是默认值。sm2.doSignature("asdasd", privateKey, { hash: true})验签
注意:由于要能java解密必须配置参数hash是true,true不是默认值。
// 参数介绍(明文,签名值,公钥,配置项)sm2.doVerifySignature("asdasd", "4c31b7d83e5ea9a77bb369be9eb28a418aa3f29b83c6df251abab9d38685a0f3e1f54fb667f6b0901915ea7c662ff7bc439b0f575359aa4a4dbc7e849ce40061", publicKey,{ hash: true})加密
const msgString = "20201325xjr"// 加密sm2.doEncrypt(msgString, publicKey)解密
// 解密sm2.doDecrypt("c278ca67cb5def5b8bed5919d9ce4a8ea29f49d6145d0b6b8acffce81c64de2691d8cf1d888cec20eab11b90c4e3816751afb8e8e42d309decdd81e162085a4c2760ab85c6e938574c005140c4ff6eb57fec03336aef8e179ce41c2119a98809b5a04f40344fa1eadd03d3d6cb1c", privateKey)后端部分引入maven依赖
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version></dependency><dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version></dependency>生成sm2公私钥
SM2 sm2 = SmUtil.sm2();String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));System.out.println(privateKey);System.out.println(publicKey);签名
注意:前端采用C1C3C2模式,DSA编码,并且是16进制字符串,所有这些模式需要配置完成。
/** * 签名 * * @param privateKey 私钥 * @param msg 味精 * @return {@link String} */public static String signature(String privateKey, String msg) { return SmUtil.sm2(privateKey, null).usePlainEncoding().setMode(SM2Engine.Mode.C1C3C2).signHex(HexUtil.encodeHexStr(msg));}验签
/** * 验证签名 * * @param publicKey 公钥 * @param signHex 十六进制符号 * @param msg 味精 * @return {@link Boolean} */ public static Boolean doVerifySignature(String publicKey, String signHex, String msg) { return SmUtil.sm2(null, publicKey).setMode(SM2Engine.Mode.C1C3C2).usePlainEncoding().verify(msg.getBytes(), HexUtil.decodeHex(signHex)); }加密
注意:由于Java生成的代码多了04字符串,所以需要截取掉,不然前端没法解密
/** * 加密 * * @param publicKey 公钥 * @param data 明文 * @return 密文 */ public static String encrypt(String publicKey, String data) { return SmUtil.sm2(null, publicKey).encryptHex(data.getBytes(), KeyType.PublicKey) // 加密后,密文前面会有04,需要去掉 .substring(2); }解密
注意:由于前端解密部分少了04字符串,所以解密是否需要添加
/** * 解密 * * @param privateKey 私钥 * @param data 密文 * @return 明文 */ public static String decrypt(String privateKey, String data) { // 前端加密是没有04的,所以解析的时候要加04 data = "04" + data; return SmUtil.sm2(privateKey, null).decryptStr(data, KeyType.PrivateKey); }总结
跨语言间不能加解密和验证签名,主要问题还是Nodejs和JAVA在SM2算法实现上默认配置导致的问题。
前端
// npm install --save sm-crypto const sm2 = require("sm-crypto").sm2;// let keypair = sm2.generateKeyPairHex();// publicKey = keypair.publicKey; // 公钥// privateKey = keypair.privateKey; // 私钥publicKey = '04164e5372cf8a44d091780ccacde2ed3b7b1199285d004261a2dc8f9ce893d79001f348cd8feaeeacb883c703bc9dca8f215ba6bd3a20b6169908d3a902e030ad'; // 公钥privateKey = '7f054f0a7bd3b03199646d7195887ee48dda2ed9eb2b579f4acd13c9fd788872'; // 私钥// 签名const sign = sm2.doSignature("asdasd", privateKey, { hash: true})console.log(sign)// 验签console.log(sm2.doVerifySignature("asdasd", "4c31b7d83e5ea9a77bb369be9eb28a418aa3f29b83c6df251abab9d38685a0f3e1f54fb667f6b0901915ea7c662ff7bc439b0f575359aa4a4dbc7e849ce40061", publicKey,{ hash: true}));const msgString = "20201325xjr"// 加密console.log(sm2.doEncrypt(msgString, publicKey))// 解密console.log(sm2.doDecrypt("c278ca67cb5def5b8bed5919d9ce4a8ea29f49d6145d0b6b8acffce81c64de2691d8cf1d888cec20eab11b90c4e3816751afb8e8e42d309decdd81e162085a4c2760ab85c6e938574c005140c4ff6eb57fec03336aef8e179ce41c2119a98809b5a04f40344fa1eadd03d3d6cb1c", privateKey))后端工具类
import cn.hutool.core.util.HexUtil;import cn.hutool.crypto.SmUtil;import cn.hutool.crypto.asymmetric.KeyType;import org.bouncycastle.crypto.engines.SM2Engine;/** * 加解密工具类 * * @author yanliang */public class Sm2Util { /** * 加密 * * @param publicKey 公钥 * @param data 明文 * @return 密文 */ public static String encrypt(String publicKey, String data) { return SmUtil.sm2(null, publicKey).encryptHex(data.getBytes(), KeyType.PublicKey) // 加密后,密文前面会有04,需要去掉 .substring(2); } /** * 解密 * * @param privateKey 私钥 * @param data 密文 * @return 明文 */ public static String decrypt(String privateKey, String data) { // 前端加密是没有04的,所以解析的时候要加04 data = "04" + data; return SmUtil.sm2(privateKey, null).decryptStr(data, KeyType.PrivateKey); } /** * 验证签名 * * @param publicKey 公钥 * @param signHex 十六进制符号 * @param msg 味精 * @return {@link Boolean} */ public static Boolean doVerifySignature(String publicKey, String signHex, String msg) { return SmUtil.sm2(null, publicKey).setMode(SM2Engine.Mode.C1C3C2).usePlainEncoding().verify(msg.getBytes(), HexUtil.decodeHex(signHex)); } /** * 签名 * * @param privateKey 私钥 * @param msg 味精 * @return {@link String} */ public static String signature(String privateKey, String msg) { return SmUtil.sm2(privateKey, null).usePlainEncoding().setMode(SM2Engine.Mode.C1C3C2).signHex(HexUtil.encodeHexStr(msg)); }}测试类
public void test() { //// 生成公私钥 //SM2 sm2 = SmUtil.sm2(); //String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey())); //String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false)); //System.out.println(privateKey); //System.out.println(publicKey); String publicKey = "04164e5372cf8a44d091780ccacde2ed3b7b1199285d004261a2dc8f9ce893d79001f348cd8feaeeacb883c703bc9dca8f215ba6bd3a20b6169908d3a902e030ad"; String privateKey = "7f054f0a7bd3b03199646d7195887ee48dda2ed9eb2b579f4acd13c9fd788872"; // 解密 String decrypt = Sm2Util.decrypt(privateKey, "9d15178ae86c5679735dfbd2e556a64e5bcbc3c7ff9117e95ff9c58b81f71219394dd306509a3e1063d9caf0276f4019c77ff66c4be4bcc9b7ef076431adb14254c67a842773819af812f1d4c4a03d4d091f401adcef97b21fa852d4117e067c496b7a84c2de330a97b1ad"); System.out.println(decrypt); // 加密 String encryData = Sm2Util.encrypt(publicKey, "asdni你啊后"); System.out.println(encryData); // 签名 String data = "asdasd"; String sign = Sm2Util.signature(privateKey, data); System.out.println(sign); // 验签 sign = "c0899f68fbeaa9569126ec64a9519d0771d2dc26dbb2d1f01d7c4a0ff5a49aa4089302c2604b4ed84c6f8a17ee8fa5efc75ce80e8d959097b79b4861cbbcfc37"; Boolean b = Sm2Util.doVerifySignature(publicKey, sign, data); System.out.println(b); }
标签: #国密算法代码