[英]Compatibility between node crypto and crypto-js encryption and decryption
[英]Encryption interop between Java (Cipher) & JavaScript (crypto-js)
我的任務是修復一種互操作的加密算法,該算法以前一直工作得很好,但是由於未知的原因突然陷入困境,沒人碰過兩種語言(Java和JS)的任何代碼。
我對密碼學不是很熟悉,所以我不知道尋找或使用哪種可能的解決方案。 基本上,任務是將Java上的此加密代碼轉換為JavaScript,這兩個代碼都將具有通過Java解密的結果Base64字符串。
以下是使用Java和JS進行加密以及在Java上進行解密過程的代碼片段:
Java加密
public static String encryptMsg(String message) {
@SuppressLint("GetInstance") Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] cipherText = cipher.doFinal(message.getBytes(UTF_CHARSET));
return Base64.encodeToString(cipherText, Base64.DEFAULT);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
} catch (NullPointerException e) {
//Do nothing, nothing to encrypt
}
return null;
}
JavaScript加密
function encryptData(data, key) {
const options = {
mode: Crypto.mode.ECB,
padding: Crypto.pad.Pkcs7
}
const secret = Crypto.enc.Utf8.parse(key)
const encrypted = Crypto.AES.encrypt(data, secret, options)
return encrypted.ciphertext.toString(Crypto.enc.Base64)
}
Java解密
public static String decryptMsg(String base64cipherText) {
@SuppressLint("GetInstance") Cipher cipher = null;
try {
cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secret);
String decryptString = new String(cipher.doFinal(Base64.decode(base64cipherText, Base64.DEFAULT)), UTF_CHARSET);
return decryptString;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
} catch (NullPointerException e) {
//Do nothing, nothing to decrypt
}
return null;
}
當前,當解密時,結果使用JavaScript加密函數在加密的字符串上返回null
,因此它可能正確加密了(?)我不確定在這里丟失或做錯了什么...
似乎您缺少IV(初始化向量)。
真的不知道IV是什么,或者這里是否需要IV,加密的Java代碼沒有在任何地方聲明它
IV是一個初始化向量,它允許重用密鑰來加密多個消息(或塊),請在使用它時查看CBC塊模式 。
我不確定使用JavaScript API,但至少可以舉一個Java的例子。 您也可以看看我的有關加密貨幣示例的博客
Java加密
SecureRandom rnd = new SecureRandom();
byte[] iv = new byte[SYMMETRIC_BLOCK_SIZE / 8];
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
SecretKey symmetricKey = new SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);
Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, ivParamSpec);
byte[] encrypted = cipher.doFinal(encryptionParams.getPlaintext());
/* and encoded form can contain form of base64( IV + ciphertext ) */
對於CBC模式,IV必須是隨機的。 如果不指定IVParameter,它將被生成,並且您可以從cipher.getIV();
讀取它cipher.getIV();
。 IV可以是公共的,通常在密文之前,因為IV需要解密密文本身。
Java解密
/* if IV is prepended before the ciphertext, it can be fetched as sub-array
of the decoded message */
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, symmetricKey, ivParamSpec);
byte[] decrypted = cipher.doFinal(encryptionParams.getCiphertext());
在此示例中,沒有Mac(包括消息身份驗證代碼),您可以查看鏈接的示例。
對於JavaScript,您應該查看所使用的API,但是原理保持不變(您也必須以某種方式生成,使用,傳遞和提供IV)。 該博客似乎包含更完整的代碼。
var iv = CryptoJS.lib.WordArray.random(128/8);
var encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.