首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python to C# AES CBC PKCS7

Python to C# AES CBC PKCS7
EN

Stack Overflow用户
提问于 2011-07-19 20:22:39
回答 4查看 11.8K关注 0票数 9

我正在尝试将这段C#代码转换成Python (2.5,GAE)。问题是,每次运行加密(在相同的字符串上)时,来自python脚本的加密字符串是不同的。

代码语言:javascript
复制
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)

代码语言:javascript
复制
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的新手:)

编辑:对不起。应该区分有一个函数正在被调用。

谢谢!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-07-21 14:34:49

您的C#代码无效。

Encrypt函数接受作为string passphrase的密码短语,然后尝试在byte[] pwdBytes = Encoding.UTF8.GetBytes(key);这一行中引用它

key更改为passphrase

这两个函数现在为我产生了相同的结果:

Python

代码语言:javascript
复制
secret_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# (使用上面提到的拼写错误修复)

代码语言:javascript
复制
Console.WriteLine(Encrypt("The rooster crows at midnight!", "A16ByteKey......"));

Python结果

XAW5KXVbItrc3WF0xW175UJoiAfonuf+s54w2iEs+7A=

C#结果

XAW5KXVbItrc3WF0xW175UJoiAfonuf+s54w2iEs+7A=

我怀疑您在python代码中多次重复使用“e”。如果您取消注释我的python脚本的最后两行,您将看到现在的输出不同了。但是如果您取消对最后三行的注释,您将看到输出是相同的。正如Foon所说,这要归功于how CBC works

当加密块中的字节序列时,CBC (密码块链接)起作用。第一个块通过将IV与明文的第一个字节(“公鸡...”)结合在一起进行加密。第二个块使用第一个操作的结果,而不是IV。

当您再次调用e.encrypt()时(例如,取消python脚本的最后两行的逗号),您将从上次停止的地方继续。它将使用最后一个加密块的输出,而不是在加密第一个块时使用IV。这就是为什么结果看起来不同的原因。通过取消python脚本的最后三行的注释,您可以初始化一个新的加密器,该加密器将使用IV作为其第一个块,从而使您获得相同的结果。

票数 3
EN

Stack Overflow用户

发布于 2011-07-20 10:21:15

将python代码更改为:

代码语言:javascript
复制
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访问此页面

票数 3
EN

Stack Overflow用户

发布于 2013-03-19 19:53:41

这个esotic PKCS7编码器是其他任何东西,而不是一个静态长度填充的函数。所以我用一个非常小的代码来实现它

代码语言:javascript
复制
#!/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

我希望这能有所帮助。干杯

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6747042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档