§ September 28, 2006

Triple DES between PHP and C#

The past while at work I've been working through some annoyingly overcomplicated encryption issues. The problem is not that Triple DES is all that complicated or annoying, it's just that when you have 2 different technologies (one doing the encrypting and one doing the decrypting) at work; it can be frustrating to get anything accomplished.

Our issues stemmed around the fact that we were using .NET 1.1 and they were using Java (with the standard crypto providers). There are a few subtleties between Microsoft's crypto providers and Java's. .NET provides 3 (ok, really only 2) Padding modes, and Java provides like 5, but they don't provide any in common. One easy padding mode is to append 0x00 bytes to the end of the final block to make it an even 64 bits wide. The Java provider didn't have this, but its easy enough to add ( by appending null char's '\0' to the end of the string then calling getBytes() ). So that's the route we took. After overcoming a few problems with "How do we encode our bytes used for the key and IV and still be compatible" we were off and running.

That made me wonder how compatible PHP and .NET's 3DES were. Since I didn't see any "Padding Mode" for PHP's, I simply hand coded the padding the same way we did with the Java code.

Here's my php script:
<?php

if(!isset($_POST['op'])) {
    ?>
<form id="form1" name="form1" method="post" action="">
  enter text
  <input name="data" type="text" />
  <input type="hidden" value="op" name="op" />
  <input type="submit" name="Submit" value="Submit" />
</form>
    <?php
}else {
    $buffer = $_POST['data']; 
    // get the amount of bytes to pad
    $extra = 8 - (strlen($buffer) % 8);
    // add the zero padding
    if($extra > 0) {
        for($i = 0; $i < $extra; $i++) {
            $buffer .= "\0";
        }
    }
    // very simple ASCII key and IV
    $key = "passwordDR0wSS@P6660juht";
    $iv = "password";
    // hex encode the return value
    echo "Result: ".bin2hex(mcrypt_cbc(MCRYPT_3DES, $key, $buffer, MCRYPT_ENCRYPT, $iv));	
}
?>


Entering 'Test' into the textbox

Then entered in my text (in this case I used "Test" in both)

Then I wrote up a sample in .NET to try to see if we had to massage the data or not:
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace TestBed {
    class Program {
        static void Main(string[] args) {
            byte[] key = Encoding.ASCII.GetBytes("passwordDR0wSS@P6660juht");
            byte[] iv = Encoding.ASCII.GetBytes("password");
            byte[] data = Encoding.ASCII.GetBytes("Test");
            byte[] enc = new byte[0];
            TripleDES tdes = TripleDES.Create();
            tdes.IV = iv;
            tdes.Key = key;
            tdes.Mode = CipherMode.CBC;
            tdes.Padding = PaddingMode.Zeros;
            ICryptoTransform ict = tdes.CreateEncryptor();
            enc = ict.TransformFinalBlock(data, 0, data.Length);
            Console.WriteLine(Bin2Hex(enc));
            Console.ReadLine();
        }
        // my bin2hex implementation		
        static string Bin2Hex(byte[] bin) {
            StringBuilder sb = new StringBuilder(bin.Length * 2);
            foreach(byte b in bin) {
                sb.Append(b.ToString("x").PadLeft(2, '0'));
            }
            return sb.ToString();
        }
    }
}
"47794945c0230c3d" Wouldn't you know it! It worked like a charm!

Would have been nice if the Java -> .NET solution had been that easy.

For those looking for an example of both encryption and decryption of 3des, check out a user submitted post on the forums here
Posted 8 years, 11 months ago on September 28, 2006

 Comments can be posted in the forums.

© 2003 - 2014 NullFX
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License