Python for C # AES CBC PKCS7

I am trying to convert this C # code to Python (2.5, GAE). The problem is that the encrypted string from the python script is different every time the encryption is run (on the same string).

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 code: (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 # code is inherited. Python code must be encrypted and decrypted in the same way so that C # code can correctly decode the value.

Note: I write in python :)

Edit: Sorry. had to make a difference in what function was called.

Thanks!

+6
source share
4 answers

Invalid C # code.

The Encrypt function accepts a passphrase as a string passphrase , but then tries to refer to it in this line byte[] pwdBytes = Encoding.UTF8.GetBytes(key);

Change key to passphrase .

Two functions now give me the same results:

Python

 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 # (with the above fix)

 Console.WriteLine(Encrypt("The rooster crows at midnight!", "A16ByteKey......")); 

Python result

XAW5KXVbItrc3WF0xW175UJoiAfonuf + s54w2iEs + 7A =

C # result

XAW5KXVbItrc3WF0xW175UJoiAfonuf + s54w2iEs + 7A =

I suspect you are reusing 'e' in your python code several times. If you uncomment the last two lines of my python script, you will see that the result is now different. But if you uncomment the last three lines, you will see that the output is the same. As Fun said, this has to do with how CBC works .

CBC (Cipher-block chaining) works when encrypting a sequence of bytes in blocks. The first block is encrypted by including IV with the first byte of your plaintext ("Rooster ..."). The second block uses the result of this first operation instead of IV.

When you call e.encrypt() a second time (for example, by highlighting the last two lines of the python script), you select the place where you left off. Instead of using IV when encrypting the first block, it will use the output of the last encrypted block. This is why the results look different. Without commenting on the last three lines of the python script, you initialize a new cipher that will use IV for its first block, which will produce identical results.

+2
source

changed python code to:

 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) 

in case anyone reaches this page via google

+3
source

This exotic PKCS7 encoder is something else, and then a function that has a static length. So I implemented it with a very code chip

 #!/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 

I hope this can help. Greetings

0
source

The implementation of Microsoft PKCS7 is slightly different from Python.

This article helped me with this problem: http://japrogbits.blogspot.com/2011/02/using-encrypted-data-between-python-and.html

Its code for encoding and decoding pkcs7 is here: https://github.com/janglin/crypto-pkcs7-example

With this PKCS7 library, this code worked for me:

 from Crypto.Cipher import AES aes = AES.new(shared_key, AES.MODE_CBC, IV) aes.encrypt(PKCS7Encoder().encode(data)) 
0
source

Source: https://habr.com/ru/post/893066/


All Articles