CryptoJS 加密 (AES)
CryptoJS Encryption (AES)
我的代码是用 Java 写的,我想把它用到 react-native 中,但我无法在 react-native 中正确转换它,我在过去的 36 小时里一直卡在里面。
我可以加密代码,但是 api 已经写好了,我必须创建 android 应用程序的副本。
input is : api/v1/master/Login/PinAuthentication
expected output is : BiR6DnP2PDlLRiRxlaqzK/p+ysGnvL6SF2SCZEN/UbIBQwJ/eDQT8uLuZffcT+kl
我的 react.js 代码是:
var CryptoJS = require("crypto-js");
let workingURL = "BiR6DnP2PDlLRiRxlaqzK%2Fp%2BysGnvL6SF2SCZEN%2FUbIBQwJ%2FeDQT8uLuZffcT%2Bkl"
let decryptedText = "BiR6DnP2PDlLRiRxlaqzK/p+ysGnvL6SF2SCZEN/UbIBQwJ/eDQT8uLuZffcT+kl"
let appstring = "api/v1/master/Login/PinAuthentication"
let appkey = "****************************************"
//JFACzfbeLzsha7vB5vl3QMgnl3iYX06LWb3tjjnNTYQkV8ZMFg+xEtxY/uM8vEZk
function encrypt10(){
let ciphertext = CryptoJS.enc.Utf8.parse(appstring)
let secSpec = [-53, -96, -53, -96, -53, -92, -52, -95, -54, -92, -54, -91, -54, -88, -54, -89]
let ivSpec = [-53, -96, -53, -96, -53, -92, -52, -95, -54, -92, -54, -91, -54, -88, -54, -89]
ivSpec = CryptoJS.enc.Utf8.parse(appkey)
secSpec = CryptoJS.enc.Utf8.parse(appkey)
console.log("ciphertext : " + ciphertext)
console.log("secSpec : " + secSpec)
console.log("ivSpec : " + ivSpec)
var encrypted = CryptoJS.AES.encrypt(ciphertext, secSpec, {
iv: ivSpec, //yes I used password as iv too. Dont mind.
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
keySize: 128 / 8,
});
console.log(encrypted.toString());
}
为了测试它我正在使用 react-js 因为 crypto-js 库。
private static byte[] getKeyBytes() throws UnsupportedEncodingException {
byte[] keyBytes = new byte[16];
byte[] parameterKeyBytes = KEY.getBytes("UTF-8");
System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
return keyBytes;
}
public static byte[] encrypt2(String value){
try{
byte[] keyBytes = getKeyBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec myKey = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec IVKey = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, myKey, IVKey);
byte[] outputBytes = cipher.doFinal(value.getBytes("UTF-8"));
return outputBytes;
}catch(Exception err){
err.printStackTrace();
return null;
}
}
在我看来,主要问题是密钥的推导。
Java代码对KEY
进行UTF8编码,然后使用前16个字节作为key。在 CryptoJS 代码中,您还执行了 appkey
的 UTF8 编码(使用 CryptoJS.enc.Utf8.parse()
),但随后将 整个 数据应用为密钥。
您需要缩短数据,例如使用 secSpec.words.slice(0, 16/4))
并类似于 ivSpec
,因为您将密钥用作 IV,顺便说一句,这是不安全的。
通过此更改,加密与 CryptoJS 代码一起工作,并且密文与预期结果/Java 代码(对于真实密钥)的结果相匹配:
let appstring = "api/v1/master/Login/PinAuthentication";
let appkey = "****************************************";
function encrypt10(){
let plaintext = CryptoJS.enc.Utf8.parse(appstring);
let secSpec = CryptoJS.enc.Utf8.parse(appkey);
let ivSpec = CryptoJS.enc.Utf8.parse(appkey);
secSpec = CryptoJS.lib.WordArray.create(secSpec.words.slice(0, 16/4));
ivSpec = CryptoJS.lib.WordArray.create(ivSpec.words.slice(0, 16/4));
var encrypted = CryptoJS.AES.encrypt(plaintext, secSpec, {iv: ivSpec});
document.getElementById("ct").innerHTML = encrypted.toString();
}
encrypt10();
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="ct"></p>
关于密钥:比 UTF8 解码更可靠的是二进制到文本的编码,如 Base64 或十六进制。
我的代码是用 Java 写的,我想把它用到 react-native 中,但我无法在 react-native 中正确转换它,我在过去的 36 小时里一直卡在里面。
我可以加密代码,但是 api 已经写好了,我必须创建 android 应用程序的副本。
input is : api/v1/master/Login/PinAuthentication
expected output is : BiR6DnP2PDlLRiRxlaqzK/p+ysGnvL6SF2SCZEN/UbIBQwJ/eDQT8uLuZffcT+kl
我的 react.js 代码是:
var CryptoJS = require("crypto-js");
let workingURL = "BiR6DnP2PDlLRiRxlaqzK%2Fp%2BysGnvL6SF2SCZEN%2FUbIBQwJ%2FeDQT8uLuZffcT%2Bkl"
let decryptedText = "BiR6DnP2PDlLRiRxlaqzK/p+ysGnvL6SF2SCZEN/UbIBQwJ/eDQT8uLuZffcT+kl"
let appstring = "api/v1/master/Login/PinAuthentication"
let appkey = "****************************************"
//JFACzfbeLzsha7vB5vl3QMgnl3iYX06LWb3tjjnNTYQkV8ZMFg+xEtxY/uM8vEZk
function encrypt10(){
let ciphertext = CryptoJS.enc.Utf8.parse(appstring)
let secSpec = [-53, -96, -53, -96, -53, -92, -52, -95, -54, -92, -54, -91, -54, -88, -54, -89]
let ivSpec = [-53, -96, -53, -96, -53, -92, -52, -95, -54, -92, -54, -91, -54, -88, -54, -89]
ivSpec = CryptoJS.enc.Utf8.parse(appkey)
secSpec = CryptoJS.enc.Utf8.parse(appkey)
console.log("ciphertext : " + ciphertext)
console.log("secSpec : " + secSpec)
console.log("ivSpec : " + ivSpec)
var encrypted = CryptoJS.AES.encrypt(ciphertext, secSpec, {
iv: ivSpec, //yes I used password as iv too. Dont mind.
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
keySize: 128 / 8,
});
console.log(encrypted.toString());
}
为了测试它我正在使用 react-js 因为 crypto-js 库。
private static byte[] getKeyBytes() throws UnsupportedEncodingException {
byte[] keyBytes = new byte[16];
byte[] parameterKeyBytes = KEY.getBytes("UTF-8");
System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
return keyBytes;
}
public static byte[] encrypt2(String value){
try{
byte[] keyBytes = getKeyBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec myKey = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec IVKey = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, myKey, IVKey);
byte[] outputBytes = cipher.doFinal(value.getBytes("UTF-8"));
return outputBytes;
}catch(Exception err){
err.printStackTrace();
return null;
}
}
在我看来,主要问题是密钥的推导。
Java代码对KEY
进行UTF8编码,然后使用前16个字节作为key。在 CryptoJS 代码中,您还执行了 appkey
的 UTF8 编码(使用 CryptoJS.enc.Utf8.parse()
),但随后将 整个 数据应用为密钥。
您需要缩短数据,例如使用 secSpec.words.slice(0, 16/4))
并类似于 ivSpec
,因为您将密钥用作 IV,顺便说一句,这是不安全的。
通过此更改,加密与 CryptoJS 代码一起工作,并且密文与预期结果/Java 代码(对于真实密钥)的结果相匹配:
let appstring = "api/v1/master/Login/PinAuthentication";
let appkey = "****************************************";
function encrypt10(){
let plaintext = CryptoJS.enc.Utf8.parse(appstring);
let secSpec = CryptoJS.enc.Utf8.parse(appkey);
let ivSpec = CryptoJS.enc.Utf8.parse(appkey);
secSpec = CryptoJS.lib.WordArray.create(secSpec.words.slice(0, 16/4));
ivSpec = CryptoJS.lib.WordArray.create(ivSpec.words.slice(0, 16/4));
var encrypted = CryptoJS.AES.encrypt(plaintext, secSpec, {iv: ivSpec});
document.getElementById("ct").innerHTML = encrypted.toString();
}
encrypt10();
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="ct"></p>
关于密钥:比 UTF8 解码更可靠的是二进制到文本的编码,如 Base64 或十六进制。