09-crypt

1. Encrypt

1. sm4双向加密

1. 前端

var encryptedText = SmUtils.encryptTest(encryptText, 'sm4Key')
{
  "sm4": "045cda898fc466b8526ac121e7db57b71fde6ed2ae",
  "sm2": "392b4f156c2424217a68f68294"
}

2. 后端

Map<String, String> map = gson.<Map<String, String>>fromJson(encryptedText, HashMap.class);
String sm2 = map.get("sm2");
String sm4 = map.get("sm4");
String decrypt = SmUtils.decrypt(sm2, sm4, "sm4Key");

2. aes双向加密

1. 前端Ase.js

import CryptoJS from 'crypto-js'

/**
 * @word 要加密的内容
 * @keyWord String  服务器随机返回的关键字
 */
export function aesEncrypt(word, keyWord = "67192fb8b12e0bd073308c19ae8e8fee") {
  const key = CryptoJS.enc.Utf8.parse(keyWord);
  const srcs = CryptoJS.enc.Utf8.parse(word);
  const encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7});
  return encrypted.toString();
}
 








 


import {aesEncrypt} from '../utils/Ase'

sqlText = aesEncrypt(sqlText)

2. 后端

/**
 * AES解密
 *
 * @param encryptStr 密文
 * @param decryptKey 秘钥,必须为16个字符组成
 * @return 明文
 */
private String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
    if (StringUtils.isEmpty(encryptStr) || StringUtils.isEmpty(decryptKey)) {
        return null;
    }
    byte[] encryptByte = Base64.getDecoder().decode(encryptStr);
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
    byte[] decryptBytes = cipher.doFinal(encryptByte);
    return new String(decryptBytes);
}


String sql = this.aesDecrypt(encryptSql, sm4GenerateKey);











 


 





3. postman

var secretKey = '67192fb8b12e0bd073308c19ae8e8fee';

let key = CryptoJS.enc.Utf8.parse(secretKey);
// var content = request.data["sql"];
var content = "select 1";
let srcs = CryptoJS.enc.Utf8.parse(content);
let aesDecrypt = CryptoJS.AES.encrypt(srcs, key, { mode:CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });

postman.setGlobalVariable("encryptSql", aesDecrypt);






 


2. crypt

1. rsa非对称加密

1. jsencrypt项目

2191697808024_.pic
2201697808051_.pic
1. js前端

引入这个文件即可 jsencrypt.min.js

// 加密:公钥加密 + 私钥解密
// Encrypt with the public key...
var encrypt = new JSEncrypt();
encrypt.setPublicKey($('#pubkey').val());
var encrypted = encrypt.encrypt($('#input').val());

// Decrypt with the private key...
var decrypt = new JSEncrypt();
decrypt.setPrivateKey($('#privkey').val());
var uncrypted = decrypt.decrypt(encrypted);

// 签名:私钥签名 + 公钥验签
// Sign with the private key...
var sign = new JSEncrypt();
sign.setPrivateKey($('#privkey').val());
var signature = sign.sign($('#input').val(), CryptoJS.SHA256, "sha256");

// Verify with the public key...
var verify = new JSEncrypt();
verify.setPublicKey($('#pubkey').val());
var verified = verify.verify($('#input').val(), signature, CryptoJS.SHA256);




 




 





 




 
2. vue前端

sudo cnpm install jsencrypt --dep

2211697808286_.pic
  • vue项目用到了lib文件夹
<script>
import { JSEncrypt } from 'jsencrypt'
import RsaApi from './RsaApi'

export default {

  data() {
    return {
      pubKey: 'MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgGiyBQovCstb9hb+d0IsbQrg2k+3eNBTeGBzkHfcXAsqWg8ExZYhNQwmssaf3fO6opVjA+cZ61yexM+NYmILw8hcas313ucl62FDGpmuE0Mhhpvo9lJOLcvQirUFp3jihgQa4lYtR+mSP1CQNmPcp6E2OEq1e8rmGGjFDD9Fm4OvAgMBAAE=',
      mobile: '19910769053',
      encryptStr: ''
    }
  },
  methods: {
    send() {
      const crypt = new JSEncrypt()
      crypt.setPublicKey(this.pubKey)

      RsaApi.rsa({
        'appId': crypt.encrypt(this.mobile)
      }).then(res => {

      }).catch(err => {
        console.log(err)
      })
    }
  }
}
</script>















 
 


 









2. hutool

String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIL7pbQ+5KKGYRhw7jE31hmA"
        + "f8Q60ybd+xZuRmuO5kOFBRqXGxKTQ9TfQI+aMW+0lw/kibKzaD/EKV91107xE384qOy6IcuBfaR5lv39OcoqNZ"
        + "5l+Dah5ABGnVkBP9fKOFhPgghBknTRo0/rZFGI6Q1UHXb+4atP++LNFlDymJcPAgMBAAECgYBammGb1alndta"
        + "xBmTtLLdveoBmp14p04D8mhkiC33iFKBcLUvvxGg2Vpuc+cbagyu/NZG+R/WDrlgEDUp6861M5BeFN0L9O4hz"
        + "GAEn8xyTE96f8sh4VlRmBOvVdwZqRO+ilkOM96+KL88A9RKdp8V2tna7TM6oI3LHDyf/JBoXaQJBAMcVN7fKlYP"
        + "Skzfh/yZzW2fmC0ZNg/qaW8Oa/wfDxlWjgnS0p/EKWZ8BxjR/d199L3i/KMaGdfpaWbYZLvYENqUCQQCobjsuCW"
        + "nlZhcWajjzpsSuy8/bICVEpUax1fUZ58Mq69CQXfaZemD9Ar4omzuEAAs2/uee3kt3AvCBaeq05NyjAkBme8SwB0iK"
        + "kLcaeGuJlq7CQIkjSrobIqUEf+CzVZPe+AorG+isS+Cw2w/2bHu+G0p5xSYvdH59P0+ZT0N+f9LFAkA6v3Ae56OrI"
        + "wfMhrJksfeKbIaMjNLS9b8JynIaXg9iCiyOHmgkMl5gAbPoH/ULXqSKwzBw5mJ2GW1gBlyaSfV3AkA/RJC+adIjsRGg"
        + "JOkiRjSmPpGv3FOhl9fsBPjupZBEIuoMWOC8GXK/73DHxwmfNmN7C9+sIi4RBcjEeQ5F5FHZ";

RSA rsa = new RSA(PRIVATE_KEY, null);

String a = "2707F9FD4288CEF302C972058712F24A5F3EC62C5A14AD2FC59DAB93503AA0FA17113A020EE4EA35EB53F"
        + "75F36564BA1DABAA20F3B90FD39315C30E68FE8A1803B36C29029B23EB612C06ACF3A34BE815074F5EB5AA3A"
        + "C0C8832EC42DA725B4E1C38EF4EA1B85904F8B10B2D62EA782B813229F9090E6F7394E42E6F44494BB8";

byte[] aByte = HexUtil.decodeHex(a);
byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);
// Junit单元测试
Assertions.assertEquals("虎头闯杭州,多抬头看天,切勿只管种地", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));

String decryptStr = rsa.decryptStr(a, KeyType.PrivateKey);











 






 



 

2. 新版国密SM

1. sm2 sm3 sm4后端

public class JunitSm {

    static final String pubKey = "3059301306072a8648ce3d020106082a811ccf5501822d0342000401cebfe224b122b3682e7683b3e449df919ef09dcc762cb107f1c2e7a39ecbb73dad92c94279252bdd97cc58666fa9483a804a785dc935d29ec12c2971ded43e";
    static final String priKey = "308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420aea516cb710b634e4b6e4ebe650d3c8d168e735f69fbc36aa4b5ef3ae6e5e13ba00a06082a811ccf5501822da1440342000401cebfe224b122b3682e7683b3e449df919ef09dcc762cb107f1c2e7a39ecbb73dad92c94279252bdd97cc58666fa9483a804a785dc935d29ec12c2971ded43e";
    static final String pubKeyQ = "0401cebfe224b122b3682e7683b3e449df919ef09dcc762cb107f1c2e7a39ecbb73dad92c94279252bdd97cc58666fa9483a804a785dc935d29ec12c2971ded43e";
    static final String priKeyD = "00aea516cb710b634e4b6e4ebe650d3c8d168e735f69fbc36aa4b5ef3ae6e5e13b";
    static final String sm2_vue_ciphertext = "73cfe0a7c50949db28377c25d0459ff29d5eaafddc890149c248c717d3c518d5eb1bbd78a4e92fec21def5aebb20752c5aebc7919cfe9787c7931925c4c1363bc57d7cefe396e03ec1816a52b3e1c41321fc3d5a96a1c6e107c98f1c6890f414d38f374817e1";
    static final String sm3_vue = "b65e9d49ad52f48947b191eab56eef91412f0e2b9d6be918df19a2c64dd178a6";
    static final String sm4_key = "cf9fcc051a78c53f634e421b71fb0af8";


    /**
     * 后端生成,前端可用
     */
    @Test
    public void sm2Key() {
        SM2 sm2 = SmUtil.sm2();

        // sm2的加解密时有两种形式即 C1C2C3、 C1C3C2
        sm2.setMode(SM2Engine.Mode.C1C3C2);

        // 生成公钥
        String pubKey = HexUtil.encodeHexStr(sm2.getPublicKey().getEncoded());
        System.out.println(pubKey);

        // 生成私钥
        String priKey = HexUtil.encodeHexStr(sm2.getPrivateKey().getEncoded());
        System.out.println(priKey);

        // 生成公钥Q,以Q值直接做为js端的加密公钥(以04开头,表示未压缩)
        String pubKeyQ = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
        System.out.println(pubKeyQ);

        // 生成私钥D,以D值做为js端的解密私钥
        // ((BCECPrivateKey) privateKey).getD().toByteArray();
        String priKeyD = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        System.out.println(priKeyD);
    }

    /**
     * 前端加密,后端解密(密文需要加04未压缩标识)
     * 后端加密,前端解密(密文需要去掉04未压缩标识)
     */
    @Test
    public void sm2() {
        SM2 sm2 = SmUtil.sm2(priKey, pubKey);
        // sm2的加解密时有两种方式:1-C1C2C3,2-C1C3C2
        sm2.setMode(SM2Engine.Mode.C1C3C2);

        // 后端解密
        String plaintext = sm2.decryptStr("04" + sm2_vue_ciphertext, KeyType.PrivateKey);
        System.out.println(plaintext);

        // 公钥加密plaintext,生成16进制ciphertext。去掉04传前端
        String ciphertext = sm2.encryptHex(plaintext, KeyType.PublicKey);
        System.out.println("vue_ciphertext: " + ciphertext.substring(2));
    }

    @Test
    public void sm3() {
        String sm3_digest = SmUtil.sm3("sm3_plaintext");
        boolean flag = sm3_vue.equalsIgnoreCase(sm3_digest);
        System.out.println(flag);
    }

    @Test
    public void sm4() {
        // 无参:生成key,有参:指定key
        // SymmetricCrypto sm4 = SmUtil.sm4();
        SymmetricCrypto sm4 = SmUtil.sm4(HexUtil.decodeHex(sm4_key));
        // sm4_key 16进制字符串
        String sm4_key = HexUtil.encodeHexStr(sm4.getSecretKey().getEncoded());
        System.out.println(sm4_key);

        // 加密
        String sm4_ciphertext = sm4.encryptHex("hello sm4!");
        System.out.println(sm4_ciphertext);

        // 解密
        String sm4_plaintext = sm4.decryptStr(sm4_ciphertext, CharsetUtil.CHARSET_UTF_8);
        System.out.println(sm4_plaintext);
    }

    /**
     * sm2 签名、验签,不能和前端联动
     */
    @Test
    public void sign() {
        // 两种构造都可以
        // SM2 sm2 = new SM2(priKeyD, pubKeyQ);
        SM2 sm2 = new SM2(priKey, pubKey);
        String content = "sign_plaintext";

        String sm2_sign = sm2.signHex(HexUtil.encodeHexStr(content));
        System.out.println("sm2_sign: " + sm2_sign);

        boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(content), sm2_sign);
        System.out.println(verify);
    }

}






























 




 














 



 





 








 

 



 



 










 


 


 




2. sm2 sm3 sm4前端

<script>
export default {
  data() {
    return {
      pubKeyQ: '0401cebfe224b122b3682e7683b3e449df919ef09dcc762cb107f1c2e7a39ecbb73dad92c94279252bdd97cc58666fa9483a804a785dc935d29ec12c2971ded43e',
      priKeyD: '00aea516cb710b634e4b6e4ebe650d3c8d168e735f69fbc36aa4b5ef3ae6e5e13b'
    }
  },
  methods: {
    sm() {
      // 04未压缩标识。hutool的默认实现是压缩过,js端是未压缩的
      const sm2 = require('sm-crypto').sm2
      // 1-C1C3C2,0-C1C2C3,默认为1
      const cipherMode = 1

      // sm2
      // 验证pubKey
      let verifyPubKeyQ = sm2.verifyPublicKey(this.pubKeyQ)
      console.log('verifyPubKeyQ:', verifyPubKeyQ)

      // 加密结果(后端加上04,进行解密)
      let ciphertext = sm2.doEncrypt('明文', this.pubKeyQ, cipherMode)
      console.log('sm2_ciphertext: ', ciphertext)

      // 解密结果(去掉04,前端解密)
      let plaintext = sm2.doDecrypt(ciphertext, this.priKeyD, cipherMode)
      console.log('sm2_plaintext: ', plaintext)

      // sm3
      const sm3 = require('sm-crypto').sm3
      let sm3_ciphertext = sm3('sm3_plaintext')
      console.log('sm3_ciphertext: ', sm3_ciphertext)

      // sm4
      const sm4 = require('sm-crypto').sm4
      // utf8串或字节数组
      const sm4Text = 'hello sm4!'
      // 16进制串或字节数组,要求为 128 比特(后端生成)
      const sm4_key = '45f9102170b0b719a524fbea17234eae'

      // 加密,默认输出 16进制字符串,默认使用 pkcs#5 填充
      let sm4_ciphertext = sm4.encrypt(sm4Text, sm4_key)
      console.log('sm4_ciphertext: ', sm4_ciphertext)
      let sm4_plaintext = sm4.decrypt(sm4_ciphertext, sm4_key)
      console.log('sm4_plaintext: ', sm4_plaintext)

      // sm2 签名、验签,不能和后端联动
      let sm2_sign = sm2.doSignature('sign_plaintext', this.priKeyD)
      console.log('sm2_sign: ', sm2_sign)
      let verifyResult = sm2.doVerifySignature('sign_plaintext', sm2_sign, this.pubKeyQ)
      console.log('verify_sm2_sign: ', verifyResult)
    }
  }
}
</script>