[英]Encryption/Decryption equivalents in Java for C# constructs
我有一個使用 Rijndael 加密的 mp4,我正在按以下方式在 C# 中解密。
System.Security.Cryptography.Rijndael crypt = System.Security.Cryptography.Rijndael.Create();
crypt.Key = convertedSecureString;
byte[] initializationVectorLength = new byte[sizeof(int)];
CryptoStream cryptostream = new CryptoStream(inputStream, crypt.CreateDecryptor(), CryptoStreamMode.Read);
byte[] buffer = new byte[1024];
int len;
while ((len = cryptostream.Read(buffer, 0, buffer.Length)) > 0)
{
outputStream.Write(buffer, 0, len);
buffer = new byte[1024];
}
outputStream.Flush();
cryptostream.Close();
inputStream.Close();
現在我需要將此代碼轉換為 Java/Android 等效代碼。 坦率地說,我不知道從哪里開始。 我對這么多選項感到困惑 - 有些人說使用 Bouncy Castle,有些人說 Apache Commons,有些人說原生 Java lib。 我該怎么做呢。 我該如何處理 CryptoStream 等?
更新
我正在使用 C# 中的以下代碼來分配密鑰
byte[] convertedSecureString = new byte[this.key.Length];
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(this.key);
for (int i = 0, j = 0; i < this.key.Length * UnicodeByteLength; i = i + UnicodeByteLength, j++)
{
convertedSecureString[j] = System.Runtime.InteropServices.Marshal.ReadByte(ptr, i);
}
try
{
crypt.Key = convertedSecureString;
}
密鑰是安全的。 我在 Java 中有等效的不安全密鑰。如何將這段代碼轉換為 Java
更新
Rfc2898DeriveBytes newKey = new Rfc2898DeriveBytes(crypt.Key.ToString(), crypt.IV);
Array.Copy(newKey.GetBytes((int)crypt.KeySize / 8), crypt.Key, (int)crypt.KeySize / 8);
Array.Copy(newKey.GetBytes((int)crypt.BlockSize / 8), crypt.IV, (int)crypt.BlockSize / 8);
我在 C# 中使用它來使用 Rfc 2898 修改密鑰並派生字節 - 我在 Java 中找不到等效項 - 我在第二條評論中找到了Java 等效於 C# 的 Rfc2898DerivedBytes - 但是我為迭代器和 dklen 提供了什么值?
您需要獲取Cipher object。這是獲取它的一種方法,使用byte[] aesKey
和byte[] iv
(初始化向量,AES 必須始終為 16 個字節)。
// aesKey is 128, 196 or 256-bit key (8, 12 or 16 byte array)
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
// initialization vector
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// create and initialize cipher object
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
一旦你的Cipher
object 處於解密模式,你可以使用update
方法向它提供加密數據,它會返回純文本數據。 完成后,您必須調用其中一種doFinal
方法來獲取最終塊。
或者,您可以使用密碼 object 和提供加密數據的原始輸入 stream 創建CipherInputStream
。 您從CipherInputStream
讀取數據,后者又從原始輸入 stream 讀取數據,對其進行解密,然后返回純文本數據。
對於加密,您需要將Cipher.ENCRYPT_MODE
傳遞給Cipher.init
方法,並改用CipherOutputStream
。
更新:完整示例,或多或少等同於原始 C# 代碼:
// Algorithm, mode and padding must match encryption.
// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// If you have Bouncycastle library installed, you can use
// Rijndael/CBC/PKCS7PADDING directly.
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7PADDING");
// convertedSecureString and initVector must be byte[] with correct length
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(convertedSecureString, "AES"),
new IvParameterSpec(initVector));
CipherInputStream cryptoStream = new CipherInputStream(inputStream, cipher);
byte[] buffer = new byte[1024];
int len = cryptoStream.read(buffer, 0, buffer.length);
while (len > 0) {
outputStream.write(buffer, 0, len);
len = cryptoStream.read(buffer, 0, buffer.length);
}
outputStream.flush();
cryptoStream.close();
// no need to close inputStream here, as cryptoStream will close it
默認情況下,Java 不支持 Rijndael 算法(AES 可能有效也可能無效,請參閱其他答案)和 PKCS7 填充。 您需要為此安裝 Bouncycastle 擴展,然后只需使用Cipher.getInstance("Rijndael/CBC/PKCS7PADDING");
. 為什么使用 CBC 和 PKCS7 填充? 這些似乎是System.Security.Cryptography.Rijndael class 的默認設置。如果我弄錯了,請根據您的情況使用正確的模式和填充。
不用擔心 C# 中的實現。Go 通過以下鏈接對 Java 語言進行加密/解密。 Java 中的 RjIndeal 實現
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.