在C#中解密用Python加密的AES密码

0 投票
3 回答
2430 浏览
提问于 2025-04-17 12:15

我有一个加密的密码,这个密码是用Python加密的。它是通过使用一个固定的密钥,先进行AES 128加密,然后再用Base64编码的结果进行加密。

现在我的应用程序是用C#写的,我用RijndaelManaged来解密。我的代码是

static String Decrypt(string textToDecrypt, string key)
{
    RijndaelManaged rijndaelCipher = new RijndaelManaged();
    rijndaelCipher.Mode = CipherMode.CBC;
    rijndaelCipher.Padding = PaddingMode.Zeros;

    rijndaelCipher.KeySize = 0x80; //128 
    rijndaelCipher.BlockSize = 0x80; //128
    byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
    byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
    byte[] keyBytes = new byte[0x10]; //16
    int len = pwdBytes.Length;
    if (len > keyBytes.Length)
    {
        len = keyBytes.Length;
    }
    Array.Copy(pwdBytes, keyBytes, len);
    rijndaelCipher.Key = keyBytes;
    rijndaelCipher.IV = keyBytes;

    byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);

   return Encoding.Unicode.GetString(plainText);
}

我知道这个密码在Python中是怎么加密的。它的过程是这样的

 key:    encryption key
    s:      string to be encrypted

    cipher            = AES.new(key, AES.MODE_CBC)
    str_to_encrypt    = _create_nonce() + _to_utf16(s)
    encrypted         = base64.b64encode(cipher.encrypt(str_to_encrypt))

_create_nonce() 这个函数会根据当前时间返回一个16位的值。

现在的问题是,我得到的前16位是乱码,后面的部分是正确的。可能是什么问题呢?我觉得问题可能出在rijndaelCipher.IV上。那在其他语言加密时,我们该怎么计算rijndaelCipher.IV呢?

我在应用程序中使用的是.NET 2.0,不能更改这个版本。

Python代码:

DEFAULT_KEY = 'SV5@9raQSV5@9raQ'
aes_encrypt(self.DEFAULT_KEY, password)

def _create_nonce():

+    t1 = time.strftime("%Y%m%d%H%M%S")
+    t2 = time.strftime("%Y%m%d%H%M%S")
+
+    return struct.pack('dd', float(t1), float(t2))
+
+
+def _to_utf16(s, max_len=32, pad='\0'):
+    
+    padded          = str.ljust(str(s), max_len, pad)
+    utf16_padded, _ = codecs.utf_16_be_encode(padded)
+    buffer          = struct.Struct(str(max_len * 2) + 'p')
+    return buffer.pack(utf16_padded)
+
+
+def aes_encrypt(key, s):

+    This will encrypt username and/or password
+    for IP Office Manager application.
+
+    Args:
+
+    key:    encryption key
+    s:      string to be encrypted
+    """
+    cipher            = AES.new(key, AES.MODE_CBC)
+    str_to_encrypt    = _create_nonce() + _to_utf16(s)
+    encrypted         = base64.b64encode(cipher.encrypt(str_to_encrypt))
+
+    return encrypted

3 个回答

-1

从你的问题中,我看到你提到:

当它在其他语言中加密时,我们如何计算 rijndaelCipher.IV?

AES是一种对称加密算法。这意味着你不能在没有密钥初始化向量(IV)的情况下解密你的数据,除非你尝试暴力破解。

所以,基于你上面的说法,你不需要不应该去计算IV来解密。你必须使用在加密时所用的IV。

你需要找出Python代码中使用的IV是什么。

2

我修复了base64中的无效字符。

  • 现在运行正常

       string textToDecrypt = 
            "wDkvBlzgoRCz749u3OjL8/uXXc4CfdEg"
          + "qP7lk3okP104HxAxQaadVdCWgzE4uUNO"
          + "9B+RYnstFmDf21CSZ89GxnzBJtiirXi0"
          + "N+/IIocPjwg=";
    

你加密的是nonce和密码的组合。你得到的也是nonce和密码的组合。

你提到的前16个字节的无意义数据就是nonce。直接把它们丢掉就行。

补充说明:

正如@CodeInChaos提到的,在CBC模式下,如果你设置的初始化向量(IV)不对,第一块数据就无法正确解密,但后面的数据可以。不过在你的情况下,第一块数据就是加密后的nonce,而且你根本不在乎能不能得到nonce,因为反正你会把它丢掉。因此,解密时用什么IV并不重要。

2

我得到的前16个字符是乱码,后面的字符是正确的。

好的,这说明你的密码或密钥是有效的,但你在初始化向量(IV)上遇到了问题。
你需要弄清楚Python使用的是什么,因为在代码片段中没有看到IV,我猜它可能全是零。

//rijndaelCipher.IV = keyBytes;
rijndaelCipher.IV = new byte[keyBytes.Lenght];  // an array defaults to all 0x00 bytes

撰写回答