AES / RSA implementation from Python to C#
<p>I want to migrate following python code into c#.
The entry point is the method encrypted_request</p>

<p>I have no real clue about aes/rsa in python or in c#. 
Maybe someone could explain the different code sections and if possible give me a hint how to implement that in c#.
Especially the magic numbers used here and there I do not understand.</p>

<pre><code>modulus = ('00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7'
           'b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280'
           '104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932'
           '575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b'
           '3ece0462db0a22b8e7')
nonce = '0CoJUm6Qyw8W8jud'
pubKey = '010001'

def encrypted_request(text):
    text = json.dumps(text)
    secKey = createSecretKey(16)
    encText = aesEncrypt(aesEncrypt(text, nonce), secKey)
    encSecKey = rsaEncrypt(secKey, pubKey, modulus)
    data = {'params': encText, 'encSecKey': encSecKey}
    return data


def aesEncrypt(text, secKey):
    pad = 16 - len(text) % 16
    text = text + chr(pad) * pad
    encryptor = AES.new(secKey, 2, '0102030405060708')
    ciphertext = encryptor.encrypt(text)
    ciphertext = base64.b64encode(ciphertext).decode('u8')
    return ciphertext


def rsaEncrypt(text, pubKey, modulus):
    text = text[::-1]
    rs = pow(int(binascii.hexlify(text), 16), int(pubKey, 16)) % int(modulus, 16)
    return format(rs, 'x').zfill(256)


def createSecretKey(size):
    return binascii.hexlify(os.urandom(size))[:16]
</code></pre>

<p>Source: <a href="https://github.com/darknessomi/musicbox/blob/master/NEMbox/api.py" rel="nofollow">https://github.com/darknessomi/musicbox/blob/master/NEMbox/api.py</a></p>

<p><strong>My current state in c#:</strong></p>

<pre><code>private byte[] hex2Binary(string hex) {
    byte[] binaryVal = new byte[hex.Length];
    for (int i = 0; i &lt; hex.Length; i++) {
        string byteString = hex.Substring(i, 1);
        byte b = Convert.ToByte(byteString, 16);
        binaryVal[i] = b;
    }
    return binaryVal;
}
private string aesEncryptBase64(String plainText, string key) {
    return aesEncryptBase64(plainText, hex2Binary(key));
}
private string aesEncryptBase64(String plainText, byte[] key) {
    //pad = 16 - len(text) % 16
    //text = text + chr(pad) * pad
    int pad = 16 - plainText.Length % 16;
    for (int i=0; i&lt;pad; i++) {
        plainText = plainText + ((char)pad);
    }

    byte[] plainBytes = null;
    RijndaelManaged aes = new RijndaelManaged();
    //aes.KeySize = 16;
    aes.Mode = CipherMode.CBC;

    aes.Key = key;
    aes.IV = hex2Binary(client.neteaseFix.encryptInfo.iv);

    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
    cs.Write(plainBytes, 0, plainBytes.Length);
    cs.Close();
    byte[] encryptedBytes = ms.ToArray();
    return Convert.ToBase64String(encryptedBytes); //decode("u8")
}
</code></pre>

<p>Here are a couple of things I see right off the bat, but the question is a bit too open-ended:</p>

<ul>
<li>In <code>aesEncryptBase64</code> you are manually applying padding. The AES implementation in .NET does that for you.  If you prefer to do it yourself you need to set <code>aes.Padding = PaddingMode.None</code></li>
<li>In <code>aesEncryptBase64</code> you create a <code>RijndaelManaged</code> object.  Don't do that. You want AES, just use <code>AES.Create()</code>, which returns an AES object (not a Rijndael object).

<ul>
<li>.NET had support for the larger Rijndael algorithm before AES; and Rijndael with a block size of 128 bits is what got selected as AES, but Rijndael supports modes that AES does not, and you shouldn't really use them interchangeably (though many samples do).</li>
</ul></li>
<li>In <code>aesEncryptBase64</code> your <code>aes</code>, <code>ms</code>, and <code>cs</code> objects are all <code>IDisposable</code>, so you should have them in using statements.</li>
<li>The <code>rsaEncrypt</code> method in Python is doing raw RSA, which isn't supported in .NET (nor generally considered a good idea).  Unless it's only called by routines which do the padding (and then it's just a pit of side-channel vulnerabilities).</li>
</ul>

<p>If your rsaEncrypt (in Python) is only being called from routines which do the signature or encryption (or PSS or OAEP) padding then your .NET equivalent would be (using your method naming casing, instead of the normal ones in .NET)</p>

<pre><code>private static rsaEncrypt(string text, string pubKey, string modulus)
{
    RSAParameters rsaParams = new RSAParameters
    {
        Exponent = hex2Binary(pubKey),
        Modulus = hex2Binary(modulus),
    };

    using (RSA rsa = RSA.Create())
    {
        rsa.ImportParameters(rsaParams);
        return rsa.Encrypt(Encoding.ASCII.GetBytes(text), YOUNEEDTOPICKTHEPADDINGMODE);
    }
}
</code></pre>

<p>It would be worlds better to improve all of the code around this, though, so that it doesn't have to do so much string re-parsing. </p>

c# python encryption aes rsa