0

I have a encrypted password , which is encrypted in python. It is encrtypted using the base 64 encoded result of the AES 128 encryption with a fixed key.

Now my application is a C# application and I am decrypting it using RijndaelManaged. My code is

static String Decrypt(string textToDecrypt, string key)
{
    RijndaelManaged rijndaelCipher = new RijndaelManaged();
    rijndaelCipher.Mode = CipherMode.CBC;
    rijndaelCipher.Padding = PaddingMode.Zeros;

    rijndaelCipher.KeySize = 0x80; //128 
    rijndaelCipher.BlockSize = 0x80; //128
    byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
    byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
    byte[] keyBytes = new byte[0x10]; //16
    int len = pwdBytes.Length;
    if (len > keyBytes.Length)
    {
        len = keyBytes.Length;
    }
    Array.Copy(pwdBytes, keyBytes, len);
    rijndaelCipher.Key = keyBytes;
    rijndaelCipher.IV = keyBytes;

    byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);

   return Encoding.Unicode.GetString(plainText);
}

I know how the password is encrtpyed in the python.Its like

 key:    encryption key
    s:      string to be encrypted

    cipher            = AES.new(key, AES.MODE_CBC)
    str_to_encrypt    = _create_nonce() + _to_utf16(s)
    encrypted         = base64.b64encode(cipher.encrypt(str_to_encrypt))

_create_nonce() returns some 16 digit value depending on current time.

The issue here is I am getting first 16 as garbage and rest I am getting correctly. What can be the issue? I think the issue might be rijndaelCipher.IV. How do we calculate the rijndaelCipher.IV when its encrypted in other language?

I am using .Net 2.0 in my application and I can't change that. Python Code:

DEFAULT_KEY = 'SV5@9raQSV5@9raQ'
aes_encrypt(self.DEFAULT_KEY, password)

def _create_nonce():

+    t1 = time.strftime("%Y%m%d%H%M%S")
+    t2 = time.strftime("%Y%m%d%H%M%S")
+
+    return struct.pack('dd', float(t1), float(t2))
+
+
+def _to_utf16(s, max_len=32, pad='\0'):
+    
+    padded          = str.ljust(str(s), max_len, pad)
+    utf16_padded, _ = codecs.utf_16_be_encode(padded)
+    buffer          = struct.Struct(str(max_len * 2) + 'p')
+    return buffer.pack(utf16_padded)
+
+
+def aes_encrypt(key, s):

+    This will encrypt username and/or password
+    for IP Office Manager application.
+
+    Args:
+
+    key:    encryption key
+    s:      string to be encrypted
+    """
+    cipher            = AES.new(key, AES.MODE_CBC)
+    str_to_encrypt    = _create_nonce() + _to_utf16(s)
+    encrypted         = base64.b64encode(cipher.encrypt(str_to_encrypt))
+
+    return encrypted
Sunil
  • 1,941
  • 3
  • 19
  • 25
  • `pwdBytes = Encoding.UTF8.GetBytes(key);` is wrong, weak and could very well be part of your problem. – H H Feb 03 '12 at 10:53
  • Seems strange that you encrypt with AES (a specific subset of Rijndael) but are using Rijndael to decrypt. Why not use AesCryptoServiceProvider? It seems like a better fit, and there is less scope for incompatibility. http://stackoverflow.com/a/4863924/14357 – spender Feb 03 '12 at 10:55
  • @Henk - Then what should I do to get pwdBytes? – Sunil Feb 03 '12 at 11:06
  • @spender - I will check with that – Sunil Feb 03 '12 at 11:07
  • You do seem to have an IV problem, you'll have to mimic what happens in Phyton. Maybe use a block of 0x00s. – H H Feb 03 '12 at 11:09
  • @HenkHolterman -- I am very new to this. Can you please explain in detail about the 0X00 thing – Sunil Feb 03 '12 at 11:15
  • 1
    You need to post the Python code too. – Ben Feb 03 '12 at 11:31
  • @Ben - I have posted the python code – Sunil Feb 03 '12 at 12:53
  • Looks like you're using UTF-16 in python, and UTF-8 in C#. – CodesInChaos Feb 03 '12 at 12:56
  • And why are you using such a crappy encryption scheme in the first place? The way you turn a password into a key sucks. And your nonce generation isn't good either. – CodesInChaos Feb 03 '12 at 12:56
  • I can't change the encryption logic, its already fixed. If I do like this byte[] pwdBytes = Encoding.UNICODE.GetBytes(key);, then every thing fails – Sunil Feb 03 '12 at 13:00
  • And for some reason you're using an IV in C#, but not in python. Also using the key as IV totally misses the point of an IV. – CodesInChaos Feb 03 '12 at 13:00
  • If the scheme is fixed, tough luck. Tell whoever invented it, to stop inventing his own crypto schemes, because he doesn't know what he's doing. – CodesInChaos Feb 03 '12 at 13:07
  • *Which* Python AES are you using!!!!! Also please post sample inputs and outputs from python, and the bad output from C# – Ben Feb 03 '12 at 13:28
  • Crypto.Cipher import AES. Encrtyped value o/p of python code: "wDkvBlzgoRCz749u3OjL8/uXXc4CfdEgqP7lk3okP104HxAxQaadVdCWgzE4uUNO9B+RYnstFmDf21C‌ ​SZ89GxnzBJtiirXi0N+/IIocPjwg=" Decrtyped value must be : 16 digit Nonce value + "Administrator" + \0\0\0\0.... – Sunil Feb 03 '12 at 14:03

3 Answers3

2

I am getting first 16 as garbage and rest I am getting correctly.

OK, that means you password/key is working but you have a problem with the IV.
You should find out what Python is using, since no IV is visible in the code fragment I guess it could be all zeroes.

//rijndaelCipher.IV = keyBytes;
rijndaelCipher.IV = new byte[keyBytes.Lenght];  // an array defaults to all 0x00 bytes
H H
  • 263,252
  • 30
  • 330
  • 514
  • By doing that, I am getting everything as garbage. I have posted the python code, can you please have a look – Sunil Feb 03 '12 at 12:48
  • @Sunil that sounds implausible. Changing the IV in CBC mode decryption does not affect any later blocks. – CodesInChaos Feb 03 '12 at 13:05
  • Can you please compile the code and tell me issue here. Encrtyped value: "wDkvBlzgoRCz749u3OjL8/uXXc4CfdEgqP7lk3okP104HxAxQaadVdCWgzE4uUNO9B+RYnstFmDf21CSZ89GxnzBJtiirXi0N+/IIocPjwg=" Decrtyped value must be : 16 digit Nonce value + "Administrator" + \0\0\0\0.... – Sunil Feb 03 '12 at 13:13
  • @Ben The choice of IV only affects all blocks during encryption, but not during decryption. Each block only depends on the cipher text of the previous block. So choosing a wrong IV for decryption only affects the first block. – CodesInChaos Feb 03 '12 at 13:28
  • @CodeInChaos, in CBC mode the IV affects all blocks. See http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29. Also using a nonce for the first block is more-or-less equivalent to using an IV - the first block cyphertext is the IV for the second block. – Ben Feb 03 '12 at 13:31
  • @CodeInChaos -- In which line it is getting rejected? – Sunil Feb 03 '12 at 14:00
  • @CodeInChaos, answered question with your help! He doesn't need the first block as the first block only contains the nonce, so it doesn't matter what he puts for IV. – Ben Feb 03 '12 at 15:12
2

I fixed the invalid characters in the base64.

  • It is working correctly

       string textToDecrypt = 
            "wDkvBlzgoRCz749u3OjL8/uXXc4CfdEg"
          + "qP7lk3okP104HxAxQaadVdCWgzE4uUNO"
          + "9B+RYnstFmDf21CSZ89GxnzBJtiirXi0"
          + "N+/IIocPjwg=";
    

What you encrypted was nonce+password. What you are getting back is nonce+password.

The first 16 bytes of nonsense you are complaining about are the nonce. Just throw them away.

Edit:

As @CodeInChaos pointed out, in CBC mode, if you get the IV wrong, the first block will not decrypt correctly, though the subsequent blocks will. However in your case the first block is the encrypted nonce, and you don't care if you get the nonce back or not, since you are going to throw it away anyway. Therefore it does not matter what you use for the IV when decrypting.

Ben
  • 34,935
  • 6
  • 74
  • 113
  • Actually I care for NOnce also. I need that value also :( . Anyway Thanks for the help. – Sunil Feb 06 '12 at 05:34
-1

From your question I saw that you said this:

How do we calculate the rijndaelCipher.IV when its encrypted in other language?

AES is a symmetric cipher. You cannot (without attempting brute force) decrypt your cipher WITHOUT the KEY and the IV.

So, taking from your quote above, you do not and should not calculate the IV to decrypt. You must use the IV that was used when it was encrypted.

You must find out what the phyton code is using for the IV.

Adam Spicer
  • 2,703
  • 25
  • 37
  • I have posted the python code used for encryption. How to find it? – Sunil Feb 03 '12 at 13:20
  • Perhaps you need to find out more about the AES library being used. Your code only shows `cipher = AES.new(key, AES.MODE_CBC)`. I suggest finding out more about that `AES` class. It could be that it is using a IV of all zeros, which is not secure. – Adam Spicer Feb 03 '12 at 13:26
  • @Adam an all 0 IV is the least of his problems. The nonce mitigates the lack of IV somewhat, assuming it is really unique(Which it might not be if several strings are encrypted in quick succession). – CodesInChaos Feb 03 '12 at 13:36
  • Down vote with no comment? *Don't be an anonymous coward.* It is a fact that @Sunil will need the IV used when encrypted in order to decrypt. Whether it be a generated IV or static IV (_including all zeros_) – Adam Spicer Feb 03 '12 at 16:24
  • 1
    @AdamSpicer, that was my downvote, Sunil does not need the IV to decrypt because it is CBC mode and he doesn't need the first block. – Ben Feb 06 '12 at 12:16