Sla*_*ast 3 java encryption android
我有一个使用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();
Run Code Online (Sandbox Code Playgroud)
现在我需要将此代码转换为Java/Android等效代码.我不确定从哪里开始坦率地说.我对很多选项感到困惑 - 有人说使用Bouncy Castle,有些人说Apache Commons,有些人说是原生的Java lib.我该怎么做呢.我该怎么办CryptoStream等?
UPDATE
我在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;
}
Run Code Online (Sandbox Code Playgroud)
钥匙是安全的.我在Java中拥有等效的不安全密钥.我如何将这段代码转换为Java
UPDATE
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);
Run Code Online (Sandbox Code Playgroud)
我在C#中使用它来使用Rfc 2898修改密钥并导出字节 - 我无法在Java中找到等价物 - 我在这里发现Java等同于C#的Rfc2898DerivedBytes在第二条评论中 - 但是我为iterator和dklen提供了什么值?
你需要得到Cipher对象.以下是获取它的一种方法,使用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);
Run Code Online (Sandbox Code Playgroud)
一旦你有Cipher解密模式的对象,你可以使用update方法为加密数据提供它,它将返回纯文本数据.完成后,必须调用其中一个doFinal方法来获得最终块.
或者,您可以CipherInputStream 使用Cipher对象和提供加密数据的原始输入流进行创建.您从中读取数据CipherInputStream,然后从原始输入流中读取数据,对其进行解密,并返回纯文本数据.
对于加密,你需要传递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
Run Code Online (Sandbox Code Playgroud)
默认情况下,Java不支持Rijndael算法(AES可能或可能不起作用,请参阅其他答案)和PKCS7填充.您需要为此安装Bouncycastle扩展,然后才能使用Cipher.getInstance("Rijndael/CBC/PKCS7PADDING");.为什么CBC和PKCS7填充?这些似乎是System.Security.Cryptography.Rijndael类的默认值.如果我弄错了,请根据您的情况使用正确的模式和填充.
| 归档时间: |
|
| 查看次数: |
2762 次 |
| 最近记录: |