cryptojspkcs5,CryptoJs

本文目錄一覽:

如何使用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’

CryptoJS的AES方法密鑰安全問題

如果你的填充模式不是PKCS5Padding肯定就解密不了了

CryptoJS.aes.encrypt(srcs, key, { iv: iv,mode:CryptoJS.mode.cbc.padding:CryptoJS.pad.NoPadding});

CryptoJS可以用的填充模式:

Pkcs7 (the default)

Iso97971

AnsiX923

Iso10126

ZeroPadding

為什麼 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”)

最簡人機交互-加解密

上學時遞小紙條,尤其是需要中間人傳遞時,是不是使用過一套約定的符號代替普通的文字?特別有必要!

廣義來講,保護信息的各種方式都屬於加密範疇,而保護的形式、角度、等級和目標是多種多樣的。

電視劇里,經常有材料被情敵偷偷修改然後蒙冤的場景。何解?

策略:讓內容中每一個位元組都參與一項運算得出一個結果記錄下來,如果計算結果變了,說明內容被修改過。

這裡運算得出的結果叫做摘要,這個算法叫消息摘要算法,也叫單向散列函數。算法的科學性很重要,常見的算法有:MD5、SHA1、SHA256、SHA512、HmacMD5、HmacSHA1、HmacSHA256 等。

這個,只能說難免會被別人看到。

策略:使用密鑰變換內容,讓別人看到也不知道為何物,通過密鑰才可還原內容。

這種通過相同的密鑰來加密和解密的算法,叫對稱加密算法。常見算法DES、3DES(TripleDES)和AES(Advanced Encryption Standard)等。AES 根據密鑰長度不同又分為AES-128 AES-192 AES-256 對應16 24 32 位元組。

這些算法,通常是按塊來進行加密的,如 16 個位元組為一塊。當最後一塊不夠 16 個位元組時,通常是採用補齊的策略,補齊的方式也有不同講究。

策略一,數據長度不對齊時使用0填充,否則不填充,但補的0解密後無法區分是補的還是原本就有的,只適合以\0結尾的字符串加密,此謂之 ZeroPadding。

策略二,補充的位元組值設定為補充的數量,如要補充5個位元組,則這5個位元組的值都為 5,這樣根據最後一個位元組可得到填充數據的長度,在解密後可以準確刪除填充的數據。但如果剛好整塊無需補充,為了仍然滿足最後一個位元組表示填充的數據長度,填充一整塊,值為塊長度。此種方式有 PKCS7Padding,它假設數據長度需要填充n(n0)個位元組才對齊,那麼填充n個位元組,每個位元組都是n;如果數據本身就已經對齊了,則填充一塊長度為塊大小的數據,每個位元組都是塊大小。PKCS5Padding,PKCS7Padding的子集,塊大小固定為8位元組。

分塊加密時,每塊採用完成相同的加密過程,則可以並行加密再拼接,但當內容中有多塊相同的內容時加密結果會一樣,而這種重複會為破解提供線索,於是多種加密模式被提出。以下是兩種最常見的模式。

Electronic Code Book(ECB)

電子密碼本模式

最基本的加密模式,也就是通常理解的加密,相同的明文將永遠加密成相同的密文,無初始向量,容易受到密碼本重放攻擊,一般情況下很少用。

Cipher Block Chaining(CBC)

密碼分組鏈接模式

明文被加密前要與前面的密文進行異或運算後再加密,因此只要選擇不同的初始向量,相同的密文加密後會形成不同的密文,這是目前應用最廣泛的模式。CBC加密後的密文是上下文相關的,但明文的錯誤不會傳遞到後續分組,但如果一個分組丟失,後面的分組將全部作廢(同步錯誤)。

對稱加密中,接收方需要知道密鑰,這個密鑰本身的保密就成為了問題。密鑰泄漏,意味着正確解密的消息也變得不可靠,也許是偽造的。

策略:公開密鑰,即發給我的消息,使用公開密鑰加密,我收到之後只可用我的私有密鑰解密。

此謂之非對稱加密算法,一種強大的密鑰保密方法。這離不開理論上的研究成果。

非對稱加密算法需要兩個密鑰:公開密鑰(publickey:簡稱公鑰)和私有密鑰(privatekey:簡稱私鑰)。公鑰與私鑰是一對,如果用公鑰對數據進行加密,只有用對應的私鑰才能解密。

為了驗證是不是對的人,可以要求發送放對內容提取摘要,並使用其私鑰加密,將結果附在後邊作為簽名一併發送。這樣,就可以使用發送放的公鑰來解密這個簽名並驗證其一致性,如果一致說明是對的人發過來的。此過程謂之簽名驗簽。

使用最廣泛的是RSA算法。

很多常見的加密算法在 CryptoJS 中有實現,首先,在控制台引入擴展腳本。

加密結果 U2FsdGVkX1/Ry7m4YU7aTXizLMAGhn2EwZf555rz8neh6FP6/4p9CUaZpnBxvOKT

解密過程

加密的內容為16進制數據時,可以利用以下方式將16進制字符串轉換成位元組數組。

計算結果 c6a13b37878f5b826f4f8162a1c8d879

CryptoJS 當前尚未支持 RSA,可以引入以下 JS 擴展。

使用公鑰加密

OVNmfqDMAxHoiMbNHNQ4Olrb0BHGLHEPXM0EAJ/hTwEJsz+igrLIPnrqf1ABmWnoj6cOOcGNroYLa2xZ9/TkaF5UKG+H+RrjpbHHQVe3mWWlDsX9bZ/m8lP3izntwKHdklH+2vfeOlSJ3+PK3O6ILWvaVM4PVCzVo9lPiN7NkIE=

使用私鑰解密

反過來使用私鑰加密公鑰解密也是可以的,只是一般的工具方法,只會提供私密生成簽名,公鑰驗證簽名,但這足夠了。

更詳細用法,請參考

直接來看看二戰期間的故事,以下內容引用自

原創文章,作者:WNCF,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/140125.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
WNCF的頭像WNCF
上一篇 2024-10-04 00:23
下一篇 2024-10-04 00:23

相關推薦

發表回復

登錄後才能評論