3

I have

byte[] request = UTF8Encoding.UTF8.GetBytes(requestParams); 

in a C# AES encryption only class that I'm converting to Python. Can anyone tell me the Python 2.5 equivalent(I'm using this on google app engine?

Example inputs:

request_params: &r=p&playerid=6263017 (or a combination of query strings)
dev_key: GK1FzK12iPYKE9Kt
dev_iv: E2I21NEwsC9RdSN2
dev_id: 12

Python function:

def Encrypt(self, request_params, dev_key, dev_iv, dev_id):

    data_bytes = request_params.encode("utf-8")
    block_size = 16
    mode = AES.MODE_CBC
    assert len(dev_key) == block_size and len(dev_iv) == block_size

    pad_char = '0'
    pad_length = block_size - len(data_bytes) % block_size
    padded_data_bytes = data_bytes + pad_length * pad_char

    encrypted_bytes = dev_iv + AES.new(dev_key, mode, dev_iv).encrypt(padded_data_bytes)
    base64_encrypted_string = base64.urlsafe_b64encode(str(encrypted_bytes))
    request_uri = "http://api.blackoutrugby.com/?d=" + dev_id + "&er=" + base64_encrypted_string
    #http://api.blackoutrugby.com/?d=19&er=RTJJNTFORXdzQzNSZFNObNerdsGhiNoeue6c3mzed4Ty1YE-gTlVJVXHz05uPT-8
    # output from this Python code, it's incorrect
    #http://api.blackoutrugby.com/?d=19&er=16t2waGI2h657pzebN53hPr4kEjOzgsOEZiycDwPXR4=
    # correct output from C# code
    return request_uri

C# Class:

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;
using Newtonsoft.Json;


namespace BlackoutRugbyPOC.Controllers {
    public class BlackoutRugbyAPI {
        public static string Request(string requestParams, string devKey, string devIV, string devID) {
            // Create an unencrypted request as an array of bytes
            byte[] request = UTF8Encoding.UTF8.GetBytes(requestParams);
            byte[] key = UTF8Encoding.UTF8.GetBytes(devKey);
            byte[] iv = UTF8Encoding.UTF8.GetBytes(devIV);

            AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
            aes.Key = key;
            aes.IV = iv;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.Zeros;

            // Get the transformer from the AES Encryptor
            ICryptoTransform cTransform = aes.CreateEncryptor();

            // Use the transformer to encrypt our request
            byte[] result = cTransform.TransformFinalBlock(request, 0, request.Length);
            aes.Clear();

            // Encode to base64
            string encryptedRequest = Convert.ToBase64String(result, 0, result.Length);

            // Send request to API
            string requestUri = "http://api.blackoutrugby.com/?d=" + devID + "&er=" + encryptedRequest;
            string xmlResponse = getWebResponse(requestUri);
            return XmlToJson(xmlResponse);
        }

        private static string getWebResponse(string url) {
            string html = "";

            WebRequest request = HttpWebRequest.Create(url);
            WebResponse response = request.GetResponse();

            using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
                html = reader.ReadToEnd();
            }
            return html;
        }

        public static string XmlToJson(string xml) {
            if (string.IsNullOrEmpty(xml))
                throw new ArgumentNullException("XML Input");

            XmlDocument doc = new XmlDocument();
            try {
                doc.LoadXml(xml);
            } catch {
                throw new ArgumentNullException("Input could not be loaded into XML Document");
            }

            return JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
        }
    }
}

Thanks,
Denis

Denis Hoctor
  • 2,597
  • 4
  • 33
  • 51
  • Why are you using a string as key/IV? I guess you're only using A-Za-z0-9?! That would reduce the key strength to 95 bits. BTW `PaddingMode.Zeros` refers to binary zeroes, not to the character '0' as in your Python code. Use "\x00" instead to produce a binary byte with the value zero. – AndiDog Jul 21 '10 at 12:06
  • The key and IV are supplied by the API service (blackoutrugby.com) which requires me to use AES on the requests I send to it – Denis Hoctor Jul 21 '10 at 12:34
  • possible duplicate of [How Does One Read Bytes from File in Python](http://stackoverflow.com/questions/150532/how-does-one-read-bytes-from-file-in-python) – devnull Mar 20 '14 at 05:50

2 Answers2

2

Don't know where you got the following code from

data_bytes = str.encode(request_params)
key_bytes = str.encode(dev_key)
iv_bytes = str.encode(dev_iv)

but you should know that it is equivalent to the following:

data_bytes = request_params.encode("ascii")
key_bytes = dev_key.encode("ascii")
iv_bytes = dev_iv.encode("ascii")

which means that non-ASCII characters in any of the three variables will cause an error (I hope you don't make up an AES key of ASCII characters only?).

In Python 2.x, str objects (byte[] in C#) are bytes and unicode objects (string in C#) are for text. This confusing fact was changed in Python 3.x, by the way.
That means if request_params is a Unicode object, you should encode it as UTF-8, and if it's a str object, you should assume (or check) that it is already encoded as UTF-8. So it might be something like:

if isinstance(request_params, unicode):
    data_bytes = request_params.encode("utf-8")
else:
    request_params.decode("utf-8") # optional check whether it is correct UTF-8
    data_bytes = request_params

As for key/IV, they will always be binary data (e.g. 16 bytes for AES-128), not text. So they don't have a character encoding. Remove those two lines of code and probably replace them with

assert len(dev_key) == block_size and len(dev_iv) == block_size
AndiDog
  • 68,631
  • 21
  • 159
  • 205
-1
     buffer = file.read(bytes)
Thorin Oakenshield
  • 14,232
  • 33
  • 106
  • 146