問題描述
我需要解密我從服務器接收到的一些數據,制作 API 的程序員將我引導到這個 Encrypter 類,看看他用來加密什么.
現在基于該類,我發現使用的算法是 AES128 CBC,并且我收到的字符串是 Base64 編碼的,并且包含其他數據,而不僅僅是密文.
即如果我收到以下字符串:
<預> <代碼> eyJpdiI6InJsSzRlU3pDZTBBUVNwMzdXMjVcL0tBPT0iLCJ2YWx1ZSI6Ik5JOENsSVVWaWk2RGNhNlwvWjJNeG94UzVkclwvMGJOREQreWUyS1UzclRMND0iLCJtYWMiOiJhZTZkYjNkNGM2ZTliNmU0ZTc0MTRiNDBmMzFlZTJhNTczZWIxMjk4N2YwMjlhODA1NTIyMDEzODljNDY2OTk2In0base64 解碼后我得到:
基于 Encrypter
類的 line 99
( iv = base64_decode($payload['iv']);
),我執行了另一個在 iv
和 value
上進行 base64 解碼,得到長度為 16 的 iv
.我將這些作為參數傳遞給下面的函數:
但我收到以下錯誤:
注意:字符串 iv
的長度為 16,但 iv.getBytes()
返回一個長度為 26 的數組.
誰能指出我哪里出錯了,我該如何解決.謝謝/
編輯
評論后,我做了一些更改,解決了上述錯誤:
在我對 iv
進行 base64 解碼之前,將字節轉換為字符串,然后將該字符串傳遞給解密方法,該方法反過來調用它的 getBytes().不知何故,這使得字節數組的長度為 26.
將我base64解碼后得到的字節數組發送到decrypt方法解決了問題.
現在方法如下:
現在我又遇到了一個奇怪的問題:
我首先加密的文本是 KushtrimPacaj
,但解密后的文本是 s:13:"KushtrimPacaj";
.那另一部分是從哪里來的?13或許代表KushtrimPacaj
的長度?
編輯
這是工作代碼,以防萬一有人需要它:
https://gist.github.com/KushtrimPacaj/43a383ab419fc222f80e
可以在padAndMcrypt()
函數,即給定的 $value 使用 PHP 的 serialize()
函數.你可以重新實現 unserialize() 函數,或者如果您總是在 PHP 中加密字符串,您可以自己拆分字節數組.
int firstQuoteIndex = 0;while(decValue[firstQuoteIndex] != (byte)'"') firstQuoteIndex++;return new String(Arrays.copyOfRange(decValue, firstQuoteIndex + 1, decValue.length-2));
完整代碼:
public static String decrypt(byte[] keyValue, String ivValue, String encryptedData) 拋出異常 {Key key = new SecretKeySpec(keyValue, "AES");byte[] iv = Base64.decode(ivValue.getBytes("UTF-8"), Base64.DEFAULT);byte[] decodedValue = Base64.decode(encryptedData.getBytes("UTF-8"), Base64.DEFAULT);密碼 c = Cipher.getInstance("AES/CBC/PKCS7Padding");//或 PKCS5Paddingc.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));byte[] decValue = c.doFinal(decodedValue);int firstQuoteIndex = 0;while(decValue[firstQuoteIndex] != (byte)'"') firstQuoteIndex++;return new String(Arrays.copyOfRange(decValue, firstQuoteIndex + 1, decValue.length-2));}
驗證 MAC 始終是一個好主意,因為它可以防止一些攻擊,例如填充預言攻擊.這也是一種很好的檢測密文一般修改的方法.
帶有 MAC 驗證的完整代碼:
public static String decrypt(byte[] keyValue, String ivValue, String encryptedData, String macValue) 拋出異常 {Key key = new SecretKeySpec(keyValue, "AES");byte[] iv = Base64.decode(ivValue.getBytes("UTF-8"), Base64.DEFAULT);byte[] decodedValue = Base64.decode(encryptedData.getBytes("UTF-8"), Base64.DEFAULT);SecretKeySpec macKey = new SecretKeySpec(keyValue, "HmacSHA256");Mac hmacSha256 = Mac.getInstance("HmacSHA256");hmacSha256.init(macKey);hmacSha256.update(ivValue.getBytes("UTF-8"));byte[] calcMac = hmacSha256.doFinal(encryptedData.getBytes("UTF-8"));byte[] mac = Hex.decodeHex(macValue.toCharArray());if (!secureEquals(calcMac, mac))返回空值;//或拋出異常密碼 c = Cipher.getInstance("AES/CBC/PKCS7Padding");//或 PKCS5Paddingc.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));byte[] decValue = c.doFinal(decodedValue);int firstQuoteIndex = 0;while(decValue[firstQuoteIndex] != (byte)'"') firstQuoteIndex++;return new String(Arrays.copyOfRange(decValue, firstQuoteIndex + 1, decValue.length-2));}/* 恒定時間比較以防止對無效身份驗證標簽的定時攻擊.*/公共靜態布爾secureEquals(最終字節[]已知,最終字節[]用戶){int knownLen = known.length;int userLen = user.length;int 結果 = knownLen ^ userLen;for (int i = 0; i < knownLen; i++) {結果 |= 已知[i] ^ 用戶[i % userLen];}返回結果 == 0;}
I need to decrypt some data that I receive from the server, and the programmer who made the API directed me to this Encrypter class, to see what he used to encrypt.
Now based on that class, I found that the algorithm used is AES128 CBC, and that the string I receive is Base64 encoded and contains other data, not just the ciphertext.
Namely that if I receive the following String:
after base64 decoding I get:
Based on line 99
of Encrypter
class ( iv = base64_decode($payload['iv']);
), I performed another base64 decode on the iv
and the value
, and got an iv
of length 16. Those I passed as parameters to the function below:
But I'm getting the following error:
Note: The String iv
has length of 16, but iv.getBytes()
returns an array of length 26.
Could someone point me to where I went wrong, and how do I fix it.
Thanks/
EDIT
After the comment, I made some changes, that resolved the above error:
Before I was base64 decoding iv
, converting the bytes to String, then passing that String to the decrypt method, which in return called the getBytes() on it. Somehow this made the byte array have a length of 26.
Sending the byte array I obtained after base64 decoding to the decrypt method fixed the problem.
Now the method is as follows:
Now I have another weird problem:
The text I encrypted on the first place was KushtrimPacaj
, but the decrypted text is s:13:"KushtrimPacaj";
.
Where is that other part coming from ? 13 perhaps represents the length of KushtrimPacaj
?
Edit
Here's the working code, in case anyone needs it :
https://gist.github.com/KushtrimPacaj/43a383ab419fc222f80e
解決方案 You can see in the padAndMcrypt()
function, that the given $value is serialized using PHP's serialize()
function. You can re-implement the unserialize()
function in Java or you can split the byte array yourself if you're always encrypting strings in PHP.
Full code:
Verifying the MAC is always a good idea, because it prevents some attacks such as the padding oracle attack. It is also a very good way to detect general modifications of ciphertexts.
Full code with MAC verification:
這篇關于如何解密在 Laravel 中使用 Crypt 加密的 Java (Android) 文本?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!
【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!