dracolytch Posted January 21, 2009 Share Posted January 21, 2009 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 Quote Link to comment Share on other sites More sharing options...
MadTechie Posted January 21, 2009 Share Posted January 21, 2009 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]; } ?> Quote Link to comment Share on other sites More sharing options...
btherl Posted January 21, 2009 Share Posted January 21, 2009 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 Quote Link to comment Share on other sites More sharing options...
dracolytch Posted January 21, 2009 Author Share Posted January 21, 2009 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()); } } } Quote Link to comment Share on other sites More sharing options...
btherl Posted January 21, 2009 Share Posted January 21, 2009 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? Quote Link to comment Share on other sites More sharing options...
premiso Posted January 21, 2009 Share Posted January 21, 2009 Is either, php or .net salting the hash automatically? Quote Link to comment Share on other sites More sharing options...
corbin Posted January 21, 2009 Share Posted January 21, 2009 I haven't read the entire thread, but the first thing I noticed is that the Silverlight code is using UTF8 and the PHP code is using ASCII. As long as none of the UTF8 chars are more than 1 byte it should be fine though.... Quote Link to comment Share on other sites More sharing options...
dracolytch Posted January 21, 2009 Author Share Posted January 21, 2009 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 Quote Link to comment Share on other sites More sharing options...
corbin Posted January 21, 2009 Share Posted January 21, 2009 It shouldn't make much of a difference assuming you don't have UTF8 data, and the coding of the .NET part follows specs. Quote Link to comment Share on other sites More sharing options...
dracolytch Posted January 21, 2009 Author Share Posted January 21, 2009 Corbin, you're right... The first bits of UTF8 were designed to map to ASCII precisely. Quote Link to comment Share on other sites More sharing options...
btherl Posted January 22, 2009 Share Posted January 22, 2009 What about strings greater than 32 bytes? Does only the first block decrypt correctly, and all subsequent blocks are garbage? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.