本文目錄一覽:
- 1、為什麼 CryptoJS DES 加密的結果和 Java DES 不一樣
- 2、如何使用CryptoJS的AES方法進行加密和解密
- 3、【uniapp】Vue.js CryptoJs 中的 3des 加密解密
- 4、有關使用CryptoJS的AES方法進行加密和解密,後台獲取前端生成的公鑰進行AES加密。前端js如何使用私鑰解密
為什麼 CryptoJS DES 加密的結果和 Java DES 不一樣
最近需要對數據進行加密/解密, 因此選用了CryptoJS庫, 對數據做DES算法的加密/解密
首選查看官方示例, 將密文進行Base64編碼, 掉進一個大坑
script src=”htt p:/ /crypto-js.googlecod e.c om/svn/tags/3.1.2/build/rollups/tripledes.js”/script
script
var encrypted = CryptoJS.DES.encrypt(“Message”, “Secret Passphrase”);
// ciphertext changed every time you run it
// 加密的結果不應該每次都是一樣的嗎?
console.log(encrypted.toString(), encrypted.ciphertext.toString(CryptoJS.enc.Base64));
var decrypted = CryptoJS.DES.decrypt(encrypted, “Secret Passphrase”);
console.log(decrypted.toString(CryptoJS.enc.Utf8));
/script
對這些加密算法不了解, 只能求助Google
des encrypion: js encrypted value does not match the java encrypted value
In cryptoJS you have to convert the key to hex and useit as word just like above (otherwise it will be considered as passphrase)
For the key, when you pass a string, it’s treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key.
原來是我指定key的方式不對, 直接將字符串做為參數, 想當然的以為這就是key, 其實不然, CryptoJS會根據這個字符串算出真正的key和IV(各種新鮮名詞不解釋, 問我也沒用, 我也不懂 -_-“)
那麼我們只需要將key和iv對應的字符串轉成CryptoJS的WordArray類型, 在DES加密時做為參數傳入即可, 這樣對Message這個字符串加密, 每次得到的密文都是YOa3le0I+dI=
var keyHex = CryptoJS.enc.Utf8.parse(‘abcd1234’);
var ivHex = CryptoJS.enc.Utf8.parse(‘inputvec’);
var encrypted = CryptoJS.DES.encrypt(‘Message’, keyHex, { iv: ivHex });
這樣是不是就萬事OK了? 哪有, 誰知道這坑是一個接一個啊.
我們再試試Java這邊的DES加密是不是和這個結果一樣, 具體實現請參考Simple Java Class to DES Encrypt Strings
果真掉坑裡了, Java通過DES加密Message這個字符串得到的結果是8dKft9vkZ4I=和CryptoJS算出來的不一樣啊…親
繼續求助Google
C# and Java DES Encryption value are not identical
SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES.(JCA Doc)
This means that in the case of the SunJCE provider,
Cipher c1 = Cipher.getInstance(“DES/ECB/PKCS5Padding”);
and
Cipher c1 = Cipher.getInstance(“DES”);
are equivalent statements.
原來是CryptoJS進行DES加密時, 默認的模式和padding方式和Java默認的不一樣造成的, 必須使用ECB mode和PKCS5Padding, 但是CryptoJS中只有Pkcs7, 不管了, 試試看…
script src=”htt p:/ /crypto-js.googleco de.c om/svn/tags/3.1.2/build/rollups/tripledes.js”/script
script src=”ht tp:/ /crypto-js.googleco de.c om/svn/tags/3.1.2/build/components/mode-ecb.js”/script
script
var keyHex = CryptoJS.enc.Utf8.parse(‘abcd1234’);
var encrypted = CryptoJS.DES.encrypt(‘Message’, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
console.log(encrypted.toString(), encrypted.ciphertext.toString(CryptoJS.enc.Base64));
/script
咦…使用Pkcs7能得到和Java DES一樣的結果了, 哇塞…好神奇
那我們試試統一Java也改成Cipher.getInstance(“DES/ECB/PKCS7Padding”)試試, 結果得到一個大大的錯誤
Error:java.security.NoSuchAlgorithmException: Cannot find any provider supporting DES/ECB/PKCS7Padding
沒辦法, 繼續Google
java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7PADDING
I will point out that PKCS#5 and PKCS#7 actually specify exactly the same type of padding (they are the same!), but it’s called #5 when used in this context. :)
這位大俠給出的解釋是: PKCS#5和PKCS#7是一樣的padding方式, 對加密算法一知半解, 我也只能暫且認可這個解釋了.
忙完了DES的加密, 接下來就是使用CryptoJS來解密了. 我們需要直接解密DES加密後的base64密文字符串. CryptoJS好像沒有提供直接解密DES密文字符串的方法啊, 他的整個加密/解密過程都是內部自己在玩, 解密時需要用到加密的結果對象, 這不是坑我嗎?
只好研究下CryptoJS DES加密後返回的對象, 發現有一個屬性ciphertext, 就是密文的WordArray, 那麼解密的時候, 我們是不是只要提供這個就行了呢?
var keyHex = CryptoJS.enc.Utf8.parse(‘abcd1234’);
// direct decrypt ciphertext
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(‘8dKft9vkZ4I=’)
}, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
果不其然, 到此為止, 問題全部解決, 豁然開朗…
完整代碼請參考CryptoJS-DES.html
Use CryptoJS encrypt message by DES and direct decrypt ciphertext, compatible with Java Cipher.getInstance(“DES”)
如何使用CryptoJS的AES方法進行加密和解密
首先準備一份明文和秘鑰:
var plaintText = ‘aaaaaaaaaaaaaaaa’; // 明文
var keyStr = ‘bbbbbbbbbbbbbbbb’; // 一般key為一個字符串
參看官網文檔,AES方法是支持AES-128、AES-192和AES-256的,加密過程中使用哪種加密方式取決於傳入key的類型,否則就會按照AES-256的方式加密。
CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.
由於Java就是按照128bit給的,但是由於是一個字符串,需要先在前端將其轉為128bit的才行。
最開始以為使用CryptoJS.enc.Hex.parse就可以正確地將其轉為128bit的key。但是不然…
經過多次嘗試,需要使用CryptoJS.enc.Utf8.parse方法才可以將key轉為128bit的。好吧,既然說了是多次嘗試,那麼就不知道原因了,後期再對其進行更深入的研究。
// 字符串類型的key用之前需要用uft8先parse一下才能用
var key = CryptoJS.enc.Utf8.parse(keyStr);
由於後端使用的是PKCS5Padding,但是在使用CryptoJS的時候發現根本沒有這個偏移,查詢後發現PKCS5Padding和PKCS7Padding是一樣的東東,使用時默認就是按照PKCS7Padding進行偏移的。
// 加密
var encryptedData = CryptoJS.AES.encrypt(plaintText, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
由於CryptoJS生成的密文是一個對象,如果直接將其轉為字符串是一個Base64編碼過的,在encryptedData.ciphertext上的屬性轉為字符串才是後端需要的格式。
var encryptedBase64Str = encryptedData.toString();
// 輸出:’RJcecVhTqCHHnlibzTypzuDvG8kjWC+ot8JuxWVdLgY=’
console.log(encryptedBase64Str);
// 需要讀取encryptedData上的ciphertext.toString()才能拿到跟Java一樣的密文
var encryptedStr = encryptedData.ciphertext.toString();
// 輸出:’44971e715853a821c79e589bcd3ca9cee0ef1bc923582fa8b7c26ec5655d2e06′
console.log(encryptedStr);
由於加密後的密文為128位的字符串,那麼解密時,需要將其轉為Base64編碼的格式。
那麼就需要先使用方法CryptoJS.enc.Hex.parse轉為十六進制,再使用CryptoJS.enc.Base64.stringify將其變為Base64編碼的字符串,此時才可以傳入CryptoJS.AES.decrypt方法中對其進行解密。
// 拿到字符串類型的密文需要先將其用Hex方法parse一下
var encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedStr);
// 將密文轉為Base64的字符串
// 只有Base64類型的字符串密文才能對其進行解密
var encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
使用轉為Base64編碼後的字符串即可傳入CryptoJS.AES.decrypt方法中進行解密操作。
// 解密
var decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
經過CryptoJS解密後,依然是一個對象,將其變成明文就需要按照Utf8格式轉為字符串。
// 解密後,需要按照Utf8的方式將明文轉位字符串
var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8);
console.log(decryptedStr); // ‘aaaaaaaaaaaaaaaa’
【uniapp】Vue.js CryptoJs 中的 3des 加密解密
或者手動導入工程里加密文件
注意加密方法是【TripleDES】不是【DES】
解密只支持 Base64 解密方式,如果是16進制的字符串,需要把16進制轉換成base64 再解密。
好多人寫完不知道加密的是否正確,下面提供一個 3des 加密例子
反之,解密後能獲取原字符串,即成功了。
如果你加密是下面的結果,那麼就是加密方式錯了,注意使用【CryptoJS.TripleDES】而不是【CryptoJS.DES】
使用DES加密方式的結果
有關使用CryptoJS的AES方法進行加密和解密,後台獲取前端生成的公鑰進行AES加密。前端js如何使用私鑰解密
如果你的填充模式不是PKCS5Padding肯定就解密不了了
CryptoJS.aes.encrypt(srcs, key, { iv: iv,mode:CryptoJS.mode.cbc.padding:CryptoJS.pad.NoPadding});
CryptoJS可以用的填充模式:
Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
原創文章,作者:DABMP,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/330664.html