Encryption / Decryption Equivalents in Java Constructs for C #
I have an encrypted mp4 using Rijndael and I am decrypting in C # as follows.
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();
Now I need to convert this code to Java / Android equivalent. I'm not sure where to start frankly. I am confused by many options - some say they use Bouncy Castle, some say Apache Commons, some native Java lib. How should I do it. And what should I do with CryptoStream etc.
UPDATE
I am using the following code in C # to assign a key
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;
}
where the key is protected. I have an equivalent unsecured key in Java. How to convert this piece of code to 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);
I use this in C # to modify a key with Rfc 2898 and output bytes - I can't find the equivalent in Java - I found the Java equivalent of Rfc2898DerivedBytes from C # here in the second comment - but what values do I give for the iterator and dklen?
source to share
You need to get the Cipher object. Here is one way to get it using byte[] aesKey
and byte[] iv
(initialization vector, should always be 16 bytes for AES).
// 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);
Once you have the object Cipher
in decryption mode, you can transfer it with encrypted data using methods update
, and it will return you text data. When you're done, you must call one of the methods doFinal
to get the final block.
Alternatively, you can create CipherInputStream
with your Cipher object and the original input stream that supplies the encrypted data. You read data from CipherInputStream
, which in turn reads data from the original input stream, decrypts it, and returns the text data to you.
For encryption, you need to pass Cipher.ENCRYPT_MODE
to a method Cipher.init
and use instead CipherOutputStream
.
Update: A complete example , more or less equivalent to the original C # code:
// 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
By default Java does not support Rijndael algorithm (AES may or may not work, see other answer) and PKCS7 addon. To do this, you will need to install the Bouncycastle extension and then just use Cipher.getInstance("Rijndael/CBC/PKCS7PADDING");
. Why CBC and PKCS7 Padding? These seem to be the defaults for the System.Security.Cryptography.Rijndael class . If I am wrong, use the correct mode and addition for your situation.
source to share
Don't worry about the C # implementation. Follow the link below for encryption / decryption for Java language. Implementing RjIndeal in Java
source to share