Python to C# AES CBC PKCS7
本文关键字:CBC PKCS7 AES to Python | 更新日期: 2023-09-27 18:02:59
我正在尝试将此c#代码转换为Python (2.5, GAE)。问题是python脚本中的加密字符串每次(对同一字符串)执行加密时都是不同的。
string Encrypt(string textToEncrypt, string passphrase)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 128;
rijndaelCipher.BlockSize = 128;
byte[] pwdBytes = Encoding.UTF8.GetBytes(passphrase);
byte[] keyBytes = new byte[16];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = new byte[16];
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
byte[] plainText = Encoding.UTF8.GetBytes(textToEncrypt);
return Convert.ToBase64String(transform.TransformFinalBlock(plainText, 0, plainText.Length));
}
Python代码:(PKCS7Encoder: http://japrogbits.blogspot.com/2011/02/using-encrypted-data-between-python-and.html)
from Crypto.Cipher import AES
from pkcs7 import PKCS7Encoder
#declared outside of all functions
key = '####'
mode = AES.MODE_CBC
iv = ''x00' * 16
encryptor = AES.new(key, mode, iv)
encoder = PKCS7Encoder()
def function(self):
text = self.request.get('passwordTextBox')
pad_text = encoder.encode(text)
cipher = encryptor.encrypt(pad_text)
enc_cipher = base64.b64encode(cipher)
c#代码是继承的。Python代码必须以相同的方式加密和解密,以便c#代码可以正确解码该值。
注意:我是python的新手:)
编辑:对不起。应该区分有一个函数被调用
谢谢!
您的c#代码无效。
Encrypt
函数接受密码短语作为string passphrase
,但随后试图在这一行引用它byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
将key
改为passphrase
。
这两个函数现在为我产生相同的结果:
Pythonsecret_text = 'The rooster crows at midnight!'
key = 'A16ByteKey......'
mode = AES.MODE_CBC
iv = ''x00' * 16
encoder = PKCS7Encoder()
padded_text = encoder.encode(secret_text)
e = AES.new(key, mode, iv)
cipher_text = e.encrypt(padded_text)
print(base64.b64encode(cipher_text))
# e = AES.new(key, mode, iv)
# cipher_text = e.encrypt(padded_text)
# print(base64.b64encode(cipher_text))
c#(修复上面提到的错字)
Console.WriteLine(Encrypt("The rooster crows at midnight!", "A16ByteKey......"));
Python结果c#结果XAW5KXVbItrc3WF0xW175UJoiAfonuf + s54w2iEs + 7 =
XAW5KXVbItrc3WF0xW175UJoiAfonuf + s54w2iEs + 7 =
我怀疑你在python代码中多次重复使用'e'。如果取消我的python脚本的最后两行注释,您将看到现在的输出是不同的。但是如果取消注释最后三行,您将看到输出是相同的。正如Foon所说,这是由于CBC的工作方式。
CBC (Cipher-block chains)在加密区块中的字节序列时起作用。第一个块通过将IV与明文的第一个字节("The rooster…")合并来加密。第二个块使用第一个操作的结果,而不是IV。
当你第二次调用e.encrypt()
时(例如通过取消python脚本的最后两行注释),你从你离开的地方捡起。在加密第一个块时,它将使用最后一个加密块的输出,而不是使用IV。这就是为什么结果看起来不同。通过取消python脚本的最后三行注释,您将初始化一个新的加密器,该加密器将使用IV作为其第一个块,从而使您获得相同的结果。
修改python代码为:
from Crypto.Cipher import AES
from pkcs7 import PKCS7Encoder
#declared outside of all functions
key = '####'
mode = AES.MODE_CBC
iv = ''x00' * 16
encoder = PKCS7Encoder()
def function(self):
encryptor = AES.new(key, mode, iv)**
text = self.request.get('passwordTextBox')
pad_text = encoder.encode(text)
cipher = encryptor.encrypt(pad_text)
enc_cipher = base64.b64encode(cipher)
如果有人通过google找到这个页面
这个简洁的PKCS7编码器是一个静态长度填充的函数。所以我用一小段代码实现了它
#!/usr/bin/env python
from Crypto.Cipher import AES
import base64
# the block size for the cipher object; must be 16, 24, or 32 for AES
BLOCK_SIZE = 16
# the character used for padding--with a block cipher such as AES, the value
# you encrypt must be a multiple of BLOCK_SIZE in length. This character is
# used to ensure that your value is always a multiple of BLOCK_SIZE
# PKCS7 method
PADDING = ''x06'
mode = AES.MODE_CBC
iv = ''x08' * 16 # static vector: dangerous for security. This could be changed periodically
#
# one-liner to sufficiently pad the text to be encrypted
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
# one-liners to encrypt/encode and decrypt/decode a string
# encrypt with AES, encode with base64
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
def CryptIt(password, secret):
cipher = AES.new(secret, mode, iv)
encoded = EncodeAES(cipher, password)
return encoded
def DeCryptIt(encoded, secret):
cipher = AES.new(secret, mode, iv)
decoded = DecodeAES(cipher, encoded)
return decoded
我希望这能帮到你。欢呼声
Microsoft的PKCS7实现与Python的有点不同。
这篇文章帮我解决了这个问题:http://japrogbits.blogspot.com/2011/02/using-encrypted-data-between-python-and.html
他的pkcs7编码和解码代码在github这里:https://github.com/janglin/crypto-pkcs7-example
使用PKCS7库,下面的代码对我来说很有效:
from Crypto.Cipher import AES
aes = AES.new(shared_key, AES.MODE_CBC, IV)
aes.encrypt(PKCS7Encoder().encode(data))