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?

+3


source to share


2 answers


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.

+6


source


Don't worry about the C # implementation. Follow the link below for encryption / decryption for Java language. Implementing RjIndeal in Java



+1


source







All Articles