Encryption in Java and Decrypting in .NET

I'm encrypting with Triple DES in Java and decrypting in .NET (C#).  In .NET, the decrypted text is gibberish.  Meaning, I get some little boxes for the string value.  In the console, it just prints out question marks.  I've tried to make the process simple by not using any padding and no IV.  Can anyone see what I might be doing wrong?

Java (Eclipse Build id: 20100218-1602 and Java SE 1.6):
http://dl.dropbox.com/u/1667842/javaEncryption.zip

.NET (VS.NET 2008 C#):
http://dl.dropbox.com/u/1667842/TripleDES.zip

There isn't much code in either project.
brettrAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

RameshSCommented:
I have put a break point at Console.WriteLine(s) and it shows the value of s is ¿¿¿¿¿¿¿¿
Since it has different characters than normal characters displayed in console, it displays then as question marks.
Actually you must set the Key property and IV property to the same values that were used for encryption in your code.   Check those details.
0
brettrAuthor Commented:
RameshS:

Yes - that is the same thing I see in the console.

--Actually you must set the Key property and IV property to the same values that were used for encryption in your code.   Check those details.--

Everything I'm doing is in the code.  You can see I'm using the same key to encrypt (java) and decrypt (.net).  3DES doesn't actually require an IV if both encryptor and decryptor aren't using it.

One thing I'm unsure about is the padding.  I have .NET set to Padding.None and Java to Cipher.getInstance("DESede").  Do those seem to jive?

Thanks for the help.
0
b_levittCommented:
My first guess is a character encoding issue.  If you're using a StreamReader to get the decrypted CryptoStream bytes, the second parameter on the constructor is the encoding type, ie..

StreamReader reader = new StreamReader(cryptoStream,Encoding.Unicode);


0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

b_levittCommented:
Sorry I didn't see that you had posted the code.

return Encoding.Unicode.GetString(output);

I guess I would confirm that you truely are sending unicode.  Maybe cast a single char to make sure that's not the issue?  ie byte dataToEncode = (byte)'B';

Here's here's a clip of my version of TripleDes decryption in .net:



public static String Decrypt(string base64Data, String key)
    {
      //separate the initialization vector from the encrypted data
      String[] base64Parts = base64Data.Split(':');
      byte[] iv = Convert.FromBase64String(base64Parts[1]);
      byte[] encryptedData = Convert.FromBase64String(base64Parts[0]);

      MemoryStream encryptedStream = new MemoryStream(encryptedData);
      TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
      tripleDes.IV = iv;

      //use md5 to create a 128bit key out of the preshared key for tripledes
      MD5 md5hasher = MD5.Create();
      tripleDes.Key = md5hasher.ComputeHash(
        Encoding.UTF8.GetBytes(key);


      CryptoStream cStream = new CryptoStream(
        encryptedStream,
        tripleDes.CreateDecryptor(),
        CryptoStreamMode.Read);

      StreamReader reader = new StreamReader(cStream);

      String unencryptedString = reader.ReadToEnd();

      // Close the streams.
      cStream.Close();
      encryptedStream.Close();
      reader.Close();

      // Return the unencrypted string
      return unencryptedString;

    }

Open in new window

0
brettrAuthor Commented:
Thanks.  So you are encrypting everything into a base64 string?  Do you convert to base64 before or after encrypting?
0
b_levittCommented:
after.  I don't think my code is any different than yours in that respect.  I just wanted to show you the CryptoStream way.  For all I know your way will work just as well.  But i do append the iv and the encrypted data together separated by a colon into a single 'data' param.  

Below is my corresponding encrypt function if you want to test your .net side or compare the output from your java side.
public static String Encrypt(string data, String key)
    {
      MemoryStream encryptedStream = new MemoryStream();
      TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
      tripleDes.GenerateIV();
      
      //use md5 to create a 128bit key out of the preshared key for tripledes
      MD5 md5hasher = MD5.Create();
      tripleDes.Key = md5hasher.ComputeHash(
        Encoding.UTF8.GetBytes(key));
      
      
      CryptoStream cStream = new CryptoStream(
        encryptedStream,
        tripleDes.CreateEncryptor(),
        CryptoStreamMode.Write);


      // Convert the passed string to a byte array.
      byte[] unencryptedBytes = Encoding.UTF8.GetBytes(data);

      // Write the byte array to the crypto stream and flush it.
      cStream.Write(unencryptedBytes, 0, unencryptedBytes.Length);
      cStream.FlushFinalBlock();

      //encode the encrypted data as base64 and append the initialization vector
      String base64EncryptedDataPlusIV =
        Convert.ToBase64String(encryptedStream.ToArray())
        + ":" + Convert.ToBase64String(tripleDes.IV);

      // Close the streams.
      cStream.Close();
      encryptedStream.Close();

      // Return the encrypted string plus the iv.
      return base64EncryptedDataPlusIV;

    }

Open in new window

0
b_levittCommented:
Also note I use MD5 to derive a key rather than use the bytes from the actual string secret.  The reason relates to this fact (from the .net ref for TripleDesServiceProvider):

"This algorithm supports key lengths from 128 bits to 192 bits in increments of 64 bits."

By using md5, I end up with a perfect 128bit key.  I don't know how it handles keys that don't fit those bit lengths.  That might be your problem - java might be doing one thing, and .net is doing another.

B
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.