6

I am using RijndaelManaged to make a simple encryption/decryption utility. This is working fine, but I am trying to get it integrated with another program which is created in Unix (Oracle). My problem is, for all smaller input string, i am getting the exact same encrypted hex as the Unix code is generation, but for longer strings, half of my encrypted hex is same, but the other half is different:

Unix Output:

012345678901234 - 00984BBED076541E051A239C02D97117 
0123456789012345678 - A0ACE158AD8CF70CEAE8F76AA27F62A30EA409ECE2F7FF84F1A9AF50817FC0C4

Windows Output (my code):

012345678901234 - 00984BBED076541E051A239C02D97117 (same as above)
0123456789012345678 - A0ACE158AD8CF70CEAE8F76AA27F62A3D9A1B396A614DA2C1281AA1F48BC3EBB (half exactly same as above)

My Windows code is:

public string Encrypt(byte[] PlainTextBytes, byte[] KeyBytes, string InitialVector)
        {
            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            RijndaelManaged SymmetricKey = new RijndaelManaged();
            SymmetricKey.Mode = CipherMode.ECB;
            SymmetricKey.Padding = PaddingMode.PKCS7;
            ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
            MemoryStream MemStream = new MemoryStream();
            CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
            CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
            CryptoStream.FlushFinalBlock();
            byte[] CipherTextBytes = MemStream.ToArray();
            MemStream.Close();
            CryptoStream.Close();
            return ByteToHexConversion(CipherTextBytes);
        }

Unix (PL/SQL) code:

FUNCTION Encrypt_Card (plain_card_id  VARCHAR2)
    RETURN RAW AS
        num_key_bytes      NUMBER := 256/8;        -- key length 256 bits (32 bytes)
        encrypted_raw      RAW (2000);             -- stores encrypted binary text
        encryption_type    PLS_INTEGER :=          -- total encryption type
                        DBMS_CRYPTO.ENCRYPT_AES256
                      + DBMS_CRYPTO.CHAIN_CBC
                      + DBMS_CRYPTO.PAD_PKCS5;

        key_bytes_raw  RAW(64) :=my_hex_key;
    BEGIN



     encrypted_raw := DBMS_CRYPTO.ENCRYPT
           (
              src => UTL_I18N.STRING_TO_RAW (plain_card_id, 'AL32UTF8'),
              typ => encryption_type,
              key => key_bytes_raw
           );


      RETURN encrypted_raw;
    EXCEPTION
    WHEN OTHERS THEN
    dbms_output.put_line (plain_card_id || ' - ' || SUBSTR(SQLERRM,1,100) );
    RETURN HEXTORAW ('EEEEEE');

The only difference i see is use of PKCS5 and PCKS7. But, .NET doesn't have PCKS5.

colithium
  • 10,269
  • 5
  • 42
  • 57
Bhaskar
  • 10,537
  • 6
  • 53
  • 64

2 Answers2

12

What abc said and also you don't seem to have any IV (Initialization Vector) in you PL/SQL code at all.

The fact that the first part are the same has to do with the different modes (ECB and CBC). ECB encrypts each block separately while CBC uses the previous block when encrypting the next one.

What happens here is that since you use CBC and do not set an IV the IV is all zeroes.
That means that the first block of ECB encryption and CBC encryption will be the same.
(Since A XOR 0 = A).

You need to make sure you use the same encryption mode in both systems and if you decide on CBC make sure you use the same IV.

Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
  • Thanks, that explains a lot. But then, when I use CBC, why does my output encrypted hex is different from the encrypted hex produced by the Unix code, even for smaller input strings. Logically, it should be same, as it is using the same key, IV and the Mode (i.e. CBC). – Bhaskar Jul 03 '09 at 12:49
  • 2
    If you use an IV on .NET and you don't set any IV on Unix the IV aren't the same. As I mentioned I cannot see that you set the IV anywhere in the Unix code. – Sani Huttunen Jul 03 '09 at 12:56
  • Using the IV in the PL/SQL ("Unix") code: http://www.mcs.csueastbay.edu/support/oracle/doc/10.2/appdev.102/b14258/d_crypto.htm#i1004325 – Adam Paynter Jul 03 '09 at 13:07
3

You use ECB in one case and CBC in the other case.

abc
  • 516
  • 2
  • 3
  • If I user CBC in my .NET code, it gives a totally different result, for all input strings (small and big). – Bhaskar Jul 03 '09 at 12:31
  • Well, of course. CBC uses a randomly generated IV. Encrypt twice with different IVs and you get different results. That's not a bug. That is how CBC should work. – abc Jul 03 '09 at 12:37
  • 1
    Actually CBC does not use a random IV. ECB doesn't use an IV at all. The difference is that in CBC the previous encrypted block is XOR:ed with the next plaintext block before encryption. Therefore CBC needs an IV to XOR with the first plaintext block since there is no block before the first. – Sani Huttunen Jul 03 '09 at 12:47
  • 1
    Oh, I get you point. You SHOULD generate a random IV. True. (Thought you meant CBC uses an internally generated random IV). The IV must as always be stored/transmitted to the decryptor and is not a secret. – Sani Huttunen Jul 03 '09 at 13:01
  • Of course it does. Using a fixed IV is incorrect and leads to insecure encryption – abc Jul 03 '09 at 13:03
  • Ah. I wrote a comment without seeing your answer – abc Jul 03 '09 at 13:08
  • Just a stupied question....suppose I do my encryption using a Generated random IV, and I send my output hex string (along with the key) to some one esle. He uses his own API to do decryption, since his random IV would be different from mine, wont the decryption cause issue. To mitigate this, we will have to use a fixed IV and share it !!! – Bhaskar Jul 03 '09 at 13:46
  • 2
    No... you should send the IV along with the encrypted data. It is not necessary to keep the IV a secret. What is important though is that you do not use the same IV to encrypt different data with the same key. – Sani Huttunen Jul 03 '09 at 14:05
  • Another note on your "stupid" question: The key is the secret. You should NOT send it along with the encrypted data. You should implement a key sharing scheme (like Diffie-Hellman) to transfer the symmetric key (AES key). In doing so you can safely transfer the IV along with the encrypted data as long as you generate a new IV for each message you transfer. – Sani Huttunen Jul 06 '09 at 16:01