背景
当要实现申请参数加密的性能,应用的是国密SM2算法,前端向后盾发送申请获取公钥,将申请加密发送到后盾,后盾用对应的私钥进行解密
解决方案:
前端采纳:SM2加密js库(sm-crypto)
后端采纳:Hutool工具
因为以后的前端SM2加密js库(sm-crypto)都是应用SM2公钥的Q值转成16进制进行加密,所以在后盾给前端发送公钥时,须要提取公钥的Q值并且转成16进制。
后端生成秘钥对与前端的公钥公钥Q
/** * 生成SM2公钥,私钥,公钥Q,私钥D <br/> * 通常因为js端提供的 SM2代码实现的计划,都是间接应用的私钥的d值和公钥的q值间接进行的加解密, * 所以后端返回的是从公钥外面提取的q值,以q值做为js端的加密公钥,从私钥提取d值,作为js端的解密私钥 * @author 杨攀 * @date 2021/5/13 16:29 * @param * @return void */ public static void createSm2Key() { SM2 sm = SmUtil.sm2(); // sm2的加解密时有两种形式即 C1C2C3、 C1C3C2, sm.setMode(SM2Engine.Mode.C1C3C2); // 生成私钥 String privateKey = HexUtil.encodeHexStr(sm.getPrivateKey().getEncoded()); LOGGER.info("私钥: {}", privateKey); // 生成公钥 String publicKey = HexUtil.encodeHexStr(sm.getPublicKey().getEncoded()); LOGGER.info("公钥: {}", publicKey); // 生成私钥D String privateKeyD = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm.getPrivateKey())); // ((BCECPrivateKey) privateKey).getD().toByteArray(); LOGGER.info("私钥D: {}", privateKeyD); // 生成公钥Q,以q值做为js端的加密公钥 String publicKeyQ = HexUtil.encodeHexStr(((BCECPublicKey) sm.getPublicKey()).getQ().getEncoded(false)); LOGGER.info("公钥Q: {}", publicKeyQ); }
前段依据公钥Q进行加密
前端测试代码:
data() { return { // 申请的 service service: this.$svc.sys.demo, // 表单数据 formData: { content: '', encContent: '', decContent: '', }, // 公钥Q publicKey:'04be3415fd3a7231fa23e4cfdf6f857b0f3137e75692f7b5011d459afc0cdd7741676dca32ca6489cfe0f0fd43b5e9f9f0f77c7997630ba1142c725178a9181558', // 私钥D (测试才放前端) privateKey: '74b24bfa8a55127c0fcbe87d7a112e398fd291fd72314e1c56e8d575664a1148', } },
办法:
// 加密 sm2Encrypt() { const sm2 = require('sm-crypto').sm2 //let keypair = sm2.generateKeyPairHex() //this.publicKey = keypair.publicKey // 公钥 //this.privateKey = keypair.privateKey // 私钥 const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为 1 //let publicKey = "3059301306072a8648ce3d020106082a811ccf5501822d03420004efddac6873492c460eac87b0b12bec1258f181a5093d62bbb622a7192d58c6c7278f45880dfc226bb0b645268e33a3a8de9d12b7397e05ab729fb35ead70dded"; let encContent = sm2.doEncrypt(this.formData.content, this.publicKey, cipherMode) // sm2加密 this.formData.encContent = encContent; }, // 解密 sm2Decrypt() { const sm2 = require('sm-crypto').sm2 let encryptData = this.formData.encContent; const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为 1 let decryptData = sm2.doDecrypt(encryptData, this.privateKey, cipherMode) // 解密后果sm2 this.formData.decContent = decryptData; },