views:

129

answers:

4

Hi,

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

A: 

you should take a look on "struct" module

mack369
A: 
     buffer = file.read(bytes)
Pramodh
+1  A: 

refer this

http://stackoverflow.com/questions/150532/how-does-one-read-bytes-from-file-in-python

Pramodh
Thanks for that. Had a look through it and http://docs.python.org/library/struct.html but am more confused now than I was. I'm able to use unpack when I know the length but the format is wrong if the length changes as it does for my set of query strings (request_params).
Denis Hoctor
A: 

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