2016-09-21 81 views
0

我想將以下python代碼遷移到c#中。 入口點是方法encrypted_request從Python到C#的AES/RSA實現#

我沒有真正的線索關於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") 
} 
+0

您是否理解算法的工作原理(例如,對稱密鑰和公鑰加密之間的區別,RSA如何加密/解密數據,何時使用RSA和AES等)? – EJoshuaS

+0

我知道AES是對稱和快速的,RSA是公開密鑰,並且質數慢。所以我會使用rsa來加密我的aes密鑰,以便將密鑰的速度和安全傳輸與rsa結合起來。 – Schnulli

回答

0

這裏有一對夫婦的事情,我看到了蝙蝠的權利,但問題是有點過於開放-ndded:

  • aesEncryptBase64你是男人ually應用填充。 .NET中的AES實現爲您做到了這一點。如果你喜歡自己動手,你需要設置aes.Padding = PaddingMode.None
  • aesEncryptBase64中創建一個RijndaelManaged對象。不要這樣做。您需要AES,只需使用AES.Create(),它將返回一個AES對象(不是Rijndael對象)。
    • .NET在AES之前支持更大的Rijndael算法;和128位塊大小的Rijndael被選爲AES,但Rijndael支持AES不支持的模式,您不應該將它們交換使用(儘管許多示例都是這樣做的)。
  • aesEncryptBase64aesmscs對象都是IDisposable,所以你應該使用的語句有他們。
  • Python中的rsaEncrypt方法使用原始RSA,這在.NET中不受支持(通常也不是一個好主意)。除非它只被填充的例程調用(然後它只是一個旁路漏洞)。

如果rsaEncrypt(在Python)只被從其中執行簽名或加密(或PSS或OAEP)填充然後您的.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); 
    } 
} 

這將是世界上更好地改善所有這周圍的代碼,雖然如此,它並沒有做那麼多串重新解析。