在C#中解密用Python加密的AES密码
我有一个加密的密码,这个密码是用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 个回答
从你的问题中,我看到你提到:
当它在其他语言中加密时,我们如何计算 rijndaelCipher.IV?
AES是一种对称加密算法。这意味着你不能在没有密钥和初始化向量(IV)的情况下解密你的数据,除非你尝试暴力破解。
所以,基于你上面的说法,你不需要也不应该去计算IV来解密。你必须使用在加密时所用的IV。
你需要找出Python代码中使用的IV是什么。
我修复了base64中的无效字符。
现在运行正常
string textToDecrypt = "wDkvBlzgoRCz749u3OjL8/uXXc4CfdEg" + "qP7lk3okP104HxAxQaadVdCWgzE4uUNO" + "9B+RYnstFmDf21CSZ89GxnzBJtiirXi0" + "N+/IIocPjwg=";
你加密的是nonce和密码的组合。你得到的也是nonce和密码的组合。
你提到的前16个字节的无意义数据就是nonce。直接把它们丢掉就行。
补充说明:
正如@CodeInChaos提到的,在CBC模式下,如果你设置的初始化向量(IV)不对,第一块数据就无法正确解密,但后面的数据可以。不过在你的情况下,第一块数据就是加密后的nonce,而且你根本不在乎能不能得到nonce,因为反正你会把它丢掉。因此,解密时用什么IV并不重要。
我得到的前16个字符是乱码,后面的字符是正确的。
好的,这说明你的密码或密钥是有效的,但你在初始化向量(IV)上遇到了问题。
你需要弄清楚Python使用的是什么,因为在代码片段中没有看到IV,我猜它可能全是零。
//rijndaelCipher.IV = keyBytes;
rijndaelCipher.IV = new byte[keyBytes.Lenght]; // an array defaults to all 0x00 bytes