Decrypting from C#

So I am trying to recover from a server disaster that wiped out my code (yes, yes, I know, backup strategies etc etc. The IT department’s backups all magically were unrecoverable and the RAID6 setup apparently suffered 3 HDD failures in the span of a couple of hours…)

The C# block that does the encryption is as follows:

       private string EncryptStupidThing(string thing)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] encodedSecret = encoding.GetBytes(thing);
            byte[] encodedKey = encoding.GetBytes("<a key that is 16 characters long>");
            Aes rijndael = Aes.Create();

            // the encodedKey must be a valid length so we pad it until it is (it checks // number of bits) 
            while (encodedKey.Length * 8 < rijndael.KeySize)
            {
                byte[] tmp = new byte[encodedKey.Length + 1];
                encodedKey.CopyTo(tmp, 0);
                tmp[tmp.Length - 1] = (byte)'\0';
                encodedKey = tmp;
            }

            rijndael.Key = encodedKey;
            rijndael.Mode = CipherMode.ECB;
            rijndael.Padding = PaddingMode.Zeros;
            ICryptoTransform ict = rijndael.CreateEncryptor();

            byte[] result = ict.TransformFinalBlock(encodedSecret, 0, encodedSecret.Length);

            // convert the encodedSecret to a Base64 string to return 
            return Convert.ToBase64String(result);
        }

Now I need to catch this base64 string in PHP (it’s being sent via $_GET['task']) and decrypt it.

I know this works somehow; I had it working before.

I have tried this:

$ciphertext = base64_decode($_GET['task']);
error_log($ciphertext);
$plaintext = openssl_decrypt($ciphertext, 'aes-128-ecb', "<The Same Key>", OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING);
if ($plaintext === false) {
    error_log("SSL Decrypt returned False: ". openssl_error_string());
    exit;
}
error_log($plaintext);
$task = json_decode($plaintext, true);
error_log($task);

I’ve tried combinations of sending the ciphertext or the raw $_GET[‘task’] in, with or without the various options; At best, I get gibberish out; most times I get Wrong final block length out.

Am I missing something obvious? I made this work before, so I know there must be some way to do it, but my brain is unable to recollect/reconstruct the code…

Just a wild guess.

In the c# part you are modifying the key while in PHP you do not do anything then sending it to decode function.

It’s… possible i suppose, but a 16 character key should be 128 bits long… so there shouldnt be any padding there… unless the key is somehow not 128, but i would have thought that would be overt…

So, it’s at least partially that.

The KeyLength in C#, according to the developer, is 256.
Why the key is 16 characters then, I… I’m just going to say I love my fellow developers.

$key = hex2bin(str_pad(bin2hex("<originalkey>"), 64, "00", STR_PAD_RIGHT));

$plaintext = openssl_decrypt($ciphertext, 'aes-256-ecb', $key);

Still getting wrong final block length though. Hrm.

What if you print out the key string in c# before using it in encrypt and hardcode this key to the decrypt I’m PHP?

Well i dont have control over the C# code; but from the code block, it would seem they’re null-padding it (byte value 0), you cant… really copy a key containing nonprinting characters…especially null, which terminates strings in most output commands…

that’s why I said you should copy a string (for example bas64 encode it) but if you do not have the possibility to access the c# part it does not help at all

In vaguely scrabbling around trying to find something that would work, I seem to have run over another weird one:

If I HMAC SHA512 something in C#:

            Encoding encoding = Encoding.UTF8;            
            using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes("<a very long string that makes up 128 characters in total>")))
            {
                var message = encoding.GetBytes(thing);
                var hash = hmac.ComputeHash(message);
                return Convert.ToBase64String(hash).TrimEnd(padding).Replace('+', '-').Replace('/', '_');
            }

(the bit at the end is to handle URL encoding)
and then shove it through PHP:
$check = hash_hmac("sha512", $nonb64 , <the same very long key>, true);

I get different hashes.
The key is hex-identical.
The message is hex-identical.
How am i getting different hash values?
The hash starts identically, but then wanders off… and comes up with a different length??
C# says:
5caef81a38714cbce93ab36b6fe3f138fd7a6ae6f6ba410f43827d9b2dd2f72330b3a551073f03cf467c911c1b2b008038695c43aba8a35ca4e88a58b959ac
PHP says:
5caef81a38714cbce93ab36b6fe3f138fd7a6ae6f6ba410f43827d9b2dd2f72330b3a551073f03cf467c911c1b2b00bf00e1a5710eaea28d7293a22962e566b3

EDIT: and the next time i run it, it wanders off even earlier:
13382a972677086246f367c64439b62d22eb1442e32497648a4f8b6e8424856d24efe267de0bf4b189cc5d9199c7293332555aefac0b3145cd5cd8c32814
133fe0aa5c99dc21891bcd9f1910e6d8b48baff1442e3249764fe293e2dba109215b493bf899f782fd2c627317646671ca4ccc9556bbeb02cc5173573630ca05

Something very weird there…

So for me this is only possible if thing or key are not the same

Here’s a sample of how i might decrypt in PHP:

$ciphertext = base64_decode($_GET['task']);
$key = "<The Same Key>";

// Ensure the key is padded in the same way as your C# code.
while (strlen($key) < 16) {
    $key .= "\0";
}

$plaintext = openssl_decrypt($ciphertext, 'aes-128-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);

if ($plaintext === false) {
    error_log("SSL Decrypt returned False: ". openssl_error_string());
    exit;
}

// Remove zero padding.
$plaintext = rtrim($plaintext, "\0");

error_log($plaintext);

$task = json_decode($plaintext, true);
error_log(print_r($task, true));

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.