最近, 開発はドッキング インターフェースの必要性に遭遇しました. このインターフェースはフロントエンドの Ajax によって直接呼び出されます. インターフェースの前後に暗号化と復号化のプロセスがあります. CryptoJS が使用されます, 暗号化モードは: パディング: CryptoJS.pad.Pkcs7
フロントエンドの暗号化方式は
事前リクエストスクリプト:
var reqeust_data =
{
"data": {
"你的参数1": "***",
"你的参数2": "***",
"你的参数3": "***"
},
"req_time":Date.parse(new Date()), // 请求时间戳
"request_string":randomString(32), // 32位随机字符串
}
var aes_key = pm.request.getHeaders().AES_KEY;
console.log("传入参数 -> " + JSON.stringify(reqeust_data));
var en_reqdata = AES_CBC_encrypt(JSON.stringify(reqeust_data), aes_key);
pm.environment.set("params",en_reqdata); // {
{params}} 为接口传入body的参数
//Generate 32-bit random string
function randomString(len) {
len = len || 32;
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var maxPos = $chars.length;
var random_str = '';
for (i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
}
return random_str;
}
//aes encode
function AES_CBC_encrypt(message, key) {
let keyHex = CryptoJS.enc.Hex.parse(key); //
let ivHex = CryptoJS.enc.Utf8.parse("0000000000000000");
let messageHex = CryptoJS.enc.Utf8.parse(message);
let encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
iv: ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
//aes decode
function decrypt(word, keyStr){
//console.log('decrypt key:' + keyStr);
let keyHex = CryptoJS.enc.Hex.parse(keyStr); //
let ivHex = CryptoJS.enc.Utf8.parse("0000000000000000");
let base64 = CryptoJS.enc.Base64.parse(word);
let src = CryptoJS.enc.Base64.stringify(base64);
var decrypt = CryptoJS.AES.decrypt(src, keyHex,
{
iv: ivHex,
mode:CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7
});
return decrypt.toString(CryptoJS.enc.Utf8);
}
リクエスト後に復号化された Js スクリプト
テスト:
var aes_key = pm.request.getHeaders().AES_KEY;
var result = decrypt(responseBody, aes_key);
console.log("返回信息明文 -> " + result);
//aes decode
function decrypt(word, keyStr){
//console.log('decrypt key:' + keyStr);
let keyHex = CryptoJS.enc.Hex.parse(keyStr); //
let ivHex = CryptoJS.enc.Utf8.parse("0000000000000000");
let base64 = CryptoJS.enc.Base64.parse(word);
let src = CryptoJS.enc.Base64.stringify(base64);
var decrypt = CryptoJS.AES.decrypt(src, keyHex,
{
iv: ivHex,
mode:CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7
});
return decrypt.toString(CryptoJS.enc.Utf8);
}
したがって、Java を使用してこの暗号化を実装し、インターフェイスを要求する必要がある場合は、最初に Hutool を使用してツール クラスを実装し、それを呼び出すことができます。ただし、Js の CryptoJS のパディング: CryptoJS.pad.Pkcs7、Java の AES に対応するデフォルト モードは AES/ECB/PKCS7Padding です。そして、Hutool の列挙型クラスにはこのモードがありません:
Hutoolの問題で、誰かがこの質問を提起したところ、元の作者も回答しました
Hutool 単体ではこの暗号化アルゴリズムを持っていないため、使用するには BC ライブラリと連携する必要があります。
まず、BC ライブラリを Maven にインポートする必要があります。
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
Java 標準ライブラリのパッケージはjava.security
、サードパーティ プロバイダによるシームレスな統合を可能にする標準メカニズムを提供します。BouncyCastle が提供する AES/ECB/PKCS7Padding アルゴリズムを使用する場合は、最初に BouncyCastle を登録する必要があります (必要なものと必要でないものがありますが、実行するだけです)。
その中で、BouncyCastle の登録は、次のステートメントを通じて実現されます。
Security.addProvider(new BouncyCastleProvider());
次に、暗号化ツール クラスの作成を開始します。
package com.psds.credit.data.utils;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.symmetric.AES;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* @author JMzz
* @description
*/
@Slf4j
public class AESUtil {
private static String AES_KEY = "你的密钥";
private static final String IV_KEY = "0000000000000000";
public static String encrypt(String message, String key, Mode mode, String padding) {
byte[] baseKey = null;
if (StringUtils.isNotEmpty(key)) {
baseKey = HexUtil.decodeHex(key);
} else {
baseKey = HexUtil.decodeHex(AES_KEY);
}
byte[] ivBytes = IV_KEY.getBytes(StandardCharsets.UTF_8);
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
AES aes = new AES(mode.name(), padding, baseKey, ivBytes);
return new Base64().encodeAsString(aes.encrypt(messageBytes));
}
public static String decrypt(String message, String key, Mode mode, String padding) {
byte[] baseKey = null;
if (StringUtils.isNotEmpty(key)) {
baseKey = HexUtil.decodeHex(key);
} else {
baseKey = HexUtil.decodeHex(AES_KEY);
}
byte[] ivBytes = IV_KEY.getBytes(StandardCharsets.UTF_8);
AES aes = new AES(mode.name(), padding, baseKey, ivBytes);
return aes.decryptStr(message);
}
// 不用HexUtil.decodeHex,也可以这个方法
private static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static String randomString(int len) {
len = len > 0 ? len : 32;
String chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
int maxPos = chars.length();
StringBuilder pwd = new StringBuilder();
for (int i = 0; i < len; i++) {
pwd.append(chars.charAt((int) (Math.random() * maxPos)));
}
return pwd.toString();
}
}
復号化するには、取得した response.body() を使用して復号化します。
AES/CBC/PKCS7Padding と AES/CBC/PKCS5Padding の違いについて:
PKCS5Padding は PKCS7Padding のサブセットです. PKCS5Padding は PKCS7Padding の特定のブロックであることが理解できます. JDK の PKCS5Padding 実装は PKCS7Padding 標準に従って実装されているため, Java で Cipher を構築する場合に PKCS5Padding と PKCS7Padding の使用に違いはありません.