Jump to content

Cross-language encryption woes


dracolytch

Recommended Posts

Alrighty folks... Time for a challenge question.

 

I'm writing a game in Silverlight (Because Flash programming makes me want to kill something). On the server-side, I'd like to use PHP for my high-score functionality, cuz I'm an old school PHP guy. Of course, high-score hacking is a very common practice, and I want to avoid that in my games. So, I've been looking at encrypting the data. Oddly enough Silverlight basically only supports AES, so that's what I'm using.

 

I've been able to transmit SHA1 hashes just fine between silverlight and PHP. I've even transmitted encrypted data, and partially decrypted it. The weird thing is, only the first 16 bytes of the transmission get decrypted correctly.

 

Any ideas/thoughts/suggestions are welcome!

 

On the PHP side, I noticed that MCRYPT_MODE_CBC seemed to be correct.

$plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);

 

~D

Link to comment
Share on other sites

try this..

if possible post a short encrypted and decrypted file from silverlight for testing.

 

<?php

$plaintext = aes_128_decrypt($data, $key);

function aes_128_decrypt($encrypted_text,$password)
{
    $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv   = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
    preg_match('/([\x20-\x7E]*)/',mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, pack("H*", $encrypted_text), MCRYPT_MODE_ECB, $iv), $a);
    return $a[0];
}
?>

Link to comment
Share on other sites

Oddly enough Silverlight basically only supports AES, so that's what I'm using.

 

That's because they're conspiring with the NSA, so they can use their AES backdoor to spy on you!

 

Back to the topic, can you show the rest of your code?  CBC needs you to chain decryption of each block in sequence, otherwise only the first block will come out right.

 

Edit: Here's a graphical representation of CBC

Link to comment
Share on other sites

Yeah, let's get some code out here.

First item of note: To help me keep my sanity, all byte arrays are base 64 encoded. That way 1) they can be compared in URLs and 2) as strings, they're easy to read/write/post to forums.

 

Known: The key and IV size for AES128 is 16 bytes (128 bits).

 

Ok, with more tests, I've found some strings work, some partially work, and some don't work at all.

Works:

string: |abc|

(As a side note: Silverlight encrypts this as: qBLfsnpWhfZyyVdjfVDYWQ== but PHP encrypts this as: WiNYk4GVVtYCypWKAxoffA==)

 

Partially works: <|Another test string|>

 

Does not work: <|This is another test string|>

 

The encryption KEY and the encryption IV for this example are the SAME. The base 64 encoded key / IV are:

hCcvRFCLhLSczcgbE6EFSg==

 

Both Silverlight and PHP show identical encoded key/iv values... So the good news is, if nothing else, I can create a message digest checksum.

 

On the server-side:

For now, I'm just putting the base64 encoded version of the encrypted data in a URL parameter called "content". I'll have silverlight POST the data once I get things working.

 

<?php
function getHashKey($string) {
$keylen = 16;
$salt = "\r\ndracosoftware\t";
$hash = sha1($salt . $string, true);
$result = '';

for ($i = 0; $i < $keylen; $i++) $result .= $hash[$i];

return $result;
}

$data = base64_decode($_GET['content']);
$key = getHashKey("password");
$iv = getHashKey("password");

$info['key'] = base64_encode($key);
$info['iv'] = base64_encode($iv);

print_r($info);
print('<br />');
print('<br />');

$plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
$plaintext = rtrim($plaintext, "\0"); 
print($plaintext);
?>

 

On the silverlight / .NET side of the house:

 

        public static byte[] GetHashKey(string hashKey)
        {
            // Initialise
            UTF8Encoding encoder = new UTF8Encoding();
            string salt = "\r\ndracosoftware\t";

            SHA1Managed sha = new SHA1Managed();
            byte[] result = new byte[mKeySize];
            byte[] hash = sha.ComputeHash(encoder.GetBytes(salt + hashKey));

            for (int i = 0; i < mKeySize; i++)
            {
                result[i] = hash[i];
            }

            return result;
        }

        public static string encrypt(string key, string dataToEncrypt)
        {
            // Initialise
            AesManaged encryptor = new AesManaged();

            // Set the key
            encryptor.Key = GetHashKey(key);
            encryptor.IV = GetHashKey(key);

            string keystring = base64_encode(encryptor.Key); // These values are just here for debug purposes
            string ivstring = base64_encode(encryptor.IV); // These values are just here for debug purposes

            // create a memory stream
            using (MemoryStream encryptionStream = new MemoryStream())
            {
                // Create the crypto stream
                using (CryptoStream encrypt = new CryptoStream(encryptionStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    // Encrypt
                    byte[] utfD1 = UTF8Encoding.UTF8.GetBytes(dataToEncrypt);
                    encrypt.Write(utfD1, 0, utfD1.Length);
                    encrypt.FlushFinalBlock();
                    encrypt.Close();

                    // Return the encrypted data
                    return Convert.ToBase64String(encryptionStream.ToArray());
                }
            }
        }

Link to comment
Share on other sites

Works:

string: |abc|

(As a side note: Silverlight encrypts this as: qBLfsnpWhfZyyVdjfVDYWQ== but PHP encrypts this as: WiNYk4GVVtYCypWKAxoffA==)

 

Well that's odd.. how does it work if they encrypt differently?  Is it due to different padding methods?

Link to comment
Share on other sites

 

Well that's odd.. how does it work if they encrypt differently?  Is it due to different padding methods?

 

I wish I knew!

 

 

 

 

Is either, php or .net salting the hash automatically?

 

No. .net has the ability to create salted keys & IVs using Rfc2898. However, I decided to forgo this step and use a simpler salting technique of my own creation, since I couldn't find a ready implementation of Rfc2898 for PHP.

 

The UTF8 vs ASCII encoding might be on to something. I'll have to investigate more.

 

~D

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.