3

I have the following Java code that needs to be translated to c#:

public static byte[] encryptAES(byte[] toEncrypt, byte[] key,
                                boolean encrypte) throws Exception {

    Security.addProvider(new BouncyCastleProvider());

    byte[] iv = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                  (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                  (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                  (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };

    IvParameterSpec salt = new IvParameterSpec(iv);
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");

    if (encrypte == false)
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"),  salt);
    else
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"),  salt);

    byte[] result = cipher.doFinal(toEncrypt);
    return result;
}

How do you do the equivalent of:

Security.addProvider(new BouncyCastleProvider());

and what is the equivalent of:

IvParameterSpec salt = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Karel
  • 2,112
  • 1
  • 15
  • 25
  • http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged.aspx – SLaks Oct 09 '13 at 16:19
  • [What have you tried?](http://mattgemmell.com/2008/12/08/what-have-you-tried/) – ntoskrnl Oct 09 '13 at 16:27
  • Thanks SLaks. I tried that, but without good results. The other party gave me a working Java example that uses BoucyCastle, so I thought I'd use that. There is no PKCS5Padding in the AESManaged class. (Although I don't think it makes a difference) – Karel Oct 09 '13 at 16:30
  • @ntoskrnl Thanks for the interesting article!! But no, it's not my intention to let others do my work. I did try a lot, first with AESManaged, then I asked tech assistance of the other party, who just gave me the Jave code, and now I just want the BouncyCastle thing working... – Karel Oct 09 '13 at 16:43
  • There is a BouncyCastle c# version. Try it? http://www.bouncycastle.org/csharp/ – Quintium Oct 09 '13 at 16:45
  • @Quintium: That's what I'm trying to do. But I got stuck. How to translate: Security.addProvider(new BouncyCastleProvider()); and IvParameterSpec salt = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); – Karel Oct 09 '13 at 16:52
  • @Karel - Gotcha. I read it as you had it in Java only. My bad. – Quintium Oct 09 '13 at 19:00
  • Can you replace the crypto by something secure? A fixed IV is a bad idea and you should add authentication/a MAC to protect against active attacks. – CodesInChaos Nov 17 '14 at 17:26

1 Answers1

5

Try this out.

According to http://social.msdn.microsoft.com/Forums/en-US/13a20d89-7d84-4f7d-8f5c-5ae108a7f5cf/des-encryption-padding-mode-pkcs5?forum=csharplanguage pkcs#5 is the same as pkcs#7.

public static byte[] EncryptDataAES(byte[] toEncrypt, byte[] key)
    {
        byte[] encryptedData;
        byte[] iv = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                                                        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                                                        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                                                        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };


        using (SymmetricAlgorithm aes = SymmetricAlgorithm.Create())
        {
            aes.Mode = CipherMode.CBC;
            aes.Key = key;
            aes.IV = iv;
            aes.Padding = PaddingMode.PKCS7;
            ICryptoTransform encryptor = aes.CreateEncryptor();
            using (MemoryStream mStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(mStream, encryptor, CryptoStreamMode.Write))
                {
                    cStream.Write(toEncrypt, 0, toEncrypt.Length);
                    cStream.FlushFinalBlock();
                    encryptedData = mStream.ToArray();
                }
            }
        }
        return encryptedData;
    }

To Decrypt:

public static string DecryptDataAES(byte[] cipherText, byte[] key, byte[] iv)
        {
            string plaintext = null;

            using (Rijndael rijAlg = Rijndael.Create())
            {
                rijAlg.Key = key;
                rijAlg.IV = iv;

                ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption. 
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;
        }

Use this to decode your key that is a hex representation of the bytes.

public static byte[] StringToByteArray(String hex)
    {
        int NumberChars = hex.Length / 2;
        byte[] bytes = new byte[NumberChars];
        using (var sr = new StringReader(hex))
        {
            for (int i = 0; i < NumberChars; i++)
                bytes[i] =
                  Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
        }
        return bytes;
    }
Animal Style
  • 689
  • 2
  • 10
  • 31
  • My problem is with decryption. I receive an encryped (and b64 encoded) string and have to dercypt it. I tried something similar as what you wrote but for decryption using the AESManaged class and get a "Padding is invalid and cannot be removed." error using PKCS7. (The encryptor uses PKCS5, but as you state that is a subset). Using None or Zero padding modes, I get no error but wrong results. – Karel Oct 09 '13 at 17:37
  • Do you convert the string using Convert.FromBase64String(YOURSTRING); to get the byte array? – Animal Style Oct 09 '13 at 17:40
  • Yes, that's what I use: byte[] cryptoBytes = Convert.FromBase64String(b64EncodedCryptoText); – Karel Oct 09 '13 at 17:43
  • I get the following error: "Padding is invalid and cannot be removed." – Karel Oct 09 '13 at 17:48
  • I called your function like this: string b64EncodedCryptoText = "Td6cGqFDvaKQes/ewPHX+Ygwl5IipdnyJf9hKiZbNv8="; string key = "6F2F108EB7F65452A1EE3E5B007103ED"; string expectedResult = "4083000234209973"; byte[] cryptoBytes = Convert.FromBase64String(b64EncodedCryptoText); byte[] keyBytes = ASCIIEncoding.ASCII.GetBytes(key); The IV as in your encryption example – Karel Oct 09 '13 at 17:50
  • 1
    I found your problem the key isn't ascii encoding. It is the hex representation of the key. So use the method I am adding to decode the key to bytes. So use: byte[] keyBytes = StringToByteArray(key); – Animal Style Oct 09 '13 at 18:16
  • Thank you so much!! You saved my day (night actually). I owe you a beer! – Karel Oct 09 '13 at 18:27
  • You can call `TransformFinalBlock` directly on the encryptor/decryptor. No need for using all those streams. – CodesInChaos Oct 10 '13 at 08:38
  • @AnimalStyle I need your help. I'm trying to perform decryption on a string return from clickbank. It uses CBC-AES-256 encryption algorithm. For details please check my thread http://www.codeproject.com/Questions/889826/How-do-I-decrypt-encoded-string-using-CBC-AES-decr and http://stackoverflow.com/questions/29208552/clickbank-cbc-aes-256-decryption-in-c-sharp?noredirect=1#comment46654293_29208552 . Awaiting your reply. Let me know for further details. – waghekapil Mar 24 '15 at 17:24