因此,我一直在與Bouncycastle庫一起嘗試連接遠程服務器。這個過程從一開始就存在問題,現在我已經接近讓所有的工作都能正常工作,但一些奇怪的事情正在發生。Java中的Bouncycastle奇數加密和解密結果
當我第一次開始構建加密過程時,我被告知使用帶有PKCS7Padding的AES 256。經過一番嘮叨,我得到了一個C++的服務器代碼例子。事實證明,IV是256位,所以我不得不使用RijndaelEngine。此外爲了這個工作正常,我必須使用ZeroBytePadding。
這裏是我的代碼:
socket = new Socket(remoteIP, port);
outputStream = new PrintWriter(socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
byte[] base_64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/".getBytes("UTF-8");
Security.addProvider(new BouncyCastleProvider());
public String AESEncrypt(String out) throws IOException, DataLengthException, IllegalStateException, InvalidCipherTextException {
byte[] EncKey = key;
byte randKey;
Random randNumber = new Random();
randKey = base_64[randNumber.nextInt(base_64.length)];
EncKey[randKey&0x1f] = randKey;
RijndaelEngine rijndaelEngine = new RijndaelEngine(256);
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(rijndaelEngine), new ZeroBytePadding());
ParametersWithIV keyParameter = new ParametersWithIV(new KeyParameter(EncKey), iv);
cipher.init(true, keyParameter);
byte[] txt = out.getBytes();
byte[] encoded = new byte[cipher.getOutputSize(txt.length)];
int len = cipher.processBytes(txt, 0, txt.length, encoded, 0);
cipher.doFinal(encoded, len);
char keyChar = (char) randKey;
String encString = new String(Base64.encode(encoded));
encString = encString.substring(0, encString.length()-1) + randKey;
return encString;
}
public void AESDecrypt(String in) throws DataLengthException, IllegalStateException, IOException, InvalidCipherTextException {
byte[] decKey = key;
byte[] msg = in.getBytes();
byte randKey = msg[msg.length-1];
decKey[randKey&0x1f] = randKey;
byte[] trimMsg = new byte[msg.length-1];
System.arraycopy(msg, 0, trimMsg, 0, trimMsg.length);
in = new String(trimMsg);
RijndaelEngine rijndaelEngine = new RijndaelEngine(256);
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(rijndaelEngine), new ZeroBytePadding());
ParametersWithIV keyParameter = new ParametersWithIV(new KeyParameter(decKey), iv);
cipher.init(false, keyParameter);
byte[] encoded = Base64.decode(in.trim());
byte[] decoded = new byte[cipher.getOutputSize(encoded.length)];
int len = cipher.processBytes(encoded, 0, encoded.length, decoded, 0);
cipher.doFinal(decoded, len);
String decString = new String(decoded);
}
這裏是我使用的發送和接收消息的測試功能:
public void serverTest() throws DataLengthException, IllegalStateException, InvalidCipherTextException, IOException {
//out = AESEncrypt(out);
outputStream.write(out + "\n");
outputStream.flush();
String msg = "";
while ((msg = inputStream.readLine()) != null) {
AESDecrypt(msg);
}
}
密鑰和IV不符合的異常改變密鑰中的最後一個字節。如果我正在加密,我會得到一個隨機的base64字符並將最後一個字節更改爲該字符。如果解密,我從消息中得到最後一個字節,並將密鑰的最後一個值設置爲解密。
在C++示例中,存在未加密的消息和兩條加密的消息。我可以處理那些罰款。
這是問題所在,當我將消息發送到遠程服務器「加密」時,應用程序會等待響應,直到連接超時但從未獲得響應。如果我發送郵件的未加密的,我得到或者7層的反應,我可以成功解密,最後
org.bouncycastle.util.encoders.DecoderException: unable to decode base64 string:
String index out of range: -4 at org.bouncycastle.util.encoders.Base64.decode(Unknown Source)
或我的錯誤之前最後一行看起來像這樣:
?"??n?i???el????s???!_S=??ah????CR??l6??]?{?l??Y?????Gn???+?????9!'??gU&4>??{X????G?.$c=??0?5??GP???_Q5????8??Z\?~???<Kr?????[2\ ???a$?C??z%?W???{?.?????eR?j????~?B"$??"z??W;???<?Yu??Y*???Z?K?e!?????f?;O(?Zw0B??g<???????????,)?L>???A"?????<[email protected]\???f%??j ?EhY/?? [email protected]?1??I??????M
如果我設置的加密/解密使用PKCS7Padding我沒有得到任何迴應時,我的消息仍然是加密,但是從我2至6響應之間獲得服務器解密,然後
org.bouncycastle.crypto.InvalidCipherTextException: pad block corrupted
我很茫然機智這個。我不知道我可能做錯了什麼,所以我來到了這裏。我希望這樣的社區能指出我的錯誤,並指導我走向正確的方向。
我有一點更新,我發現我的加密錯誤。我沒有正確地將隨機base64值放在加密字符串的末尾,所以現在我正在這樣做。
encString += (char)randKey;
我現在可以從服務器得到響應。現在的問題是我有時會得到一兩個可讀的行,但其餘的都是垃圾。我問誰運行服務器關於它的人,他們在他們引用一些C#代碼表示,有
return UTF8Encoding.UTF8.GetString(resultArray);
和多數民衆贊成所有我必須走下車的。我已經嘗試過使用UTF-8編碼的地方,我在那裏做了getBytes或新的String,並且我試圖製作BurrferReader流UTF-8,但它仍然是垃圾。
聽起來像你只是想直到有工作隨意的事情。爲什麼不從服務器的運營商那裏獲得真正的規範? –
「隨機」是一個安全的PRNG嗎?標準的Random類不安全,不應該用在加密代碼中。 – CodesInChaos
@GregS問題之一是來自服務器運營商的規範。他們一直告訴我必須使用256位AES,但初始化向量是256位。 AES的塊大小不會允許。當我提到這一點時,我不得不使用Rijndael或使用提供的IV。另外,我被告知使用的填充從不用於解密。 – hswets