繁体   English   中英

从Python到C#的AES / RSA实现

[英]AES / RSA implementation from Python to C#

我想将以下python代码迁移到c#中。 入口点是方法encrypted_request

我在python或c#中没有关于aes / rsa的真正线索。 也许有人可以解释不同的代码部分,并在可能的情况下给我提示如何在c#中实现它。 尤其是在这里和那里使用的魔术数字我不明白。

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]

来源: https : //github.com/darknessomi/musicbox/blob/master/NEMbox/api.py

我在C#中的当前状态:

private byte[] hex2Binary(string hex) {
    byte[] binaryVal = new byte[hex.Length];
    for (int i = 0; i < 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<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")
}

这是我很快想到的几件事,但问题有点太开放了:

  • aesEncryptBase64您正在手动应用填充。 .NET中的AES实现为您完成了此任务。 如果您喜欢自己做,则需要设置aes.Padding = PaddingMode.None
  • aesEncryptBase64您将创建一个RijndaelManaged对象。 不要那样做 您需要AES,只需使用AES.Create()返回一个AES对象(而不是Rijndael对象)。
    • .NET在AES之前支持更大的Rijndael算法。 块大小为128位的Rijndael是作为AES选择的,但是Rijndael支持AES不支持的模式,并且您不应真正互换使用它们(尽管很多示例都可以使用)。
  • aesEncryptBase64您的aesmscs对象都是IDisposable ,因此应在using语句中使用它们。
  • Python中的rsaEncrypt方法正在执行原始RSA,.NET不支持该方法(通常也不认为是一个好主意)。 除非仅由执行填充的例程调用(否则,这只是一些旁通道漏洞)。

如果仅从执行签名或加密(或PSS或OAEP)填充的例程中调用rsaEncrypt(在Python中),则等效于.NET(使用方法命名框,而不是.NET中的常规名称)

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);
    }
}

但是,最好围绕它改进所有代码,这样就不必进行太多的字符串重新解析。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM