Python для C # AES CBC PKCS7 - PullRequest
       9

Python для C # AES CBC PKCS7

7 голосов
/ 19 июля 2011

Я пытаюсь преобразовать этот код 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 # мог правильно декодировать значение.

Примечание.1011 * Редактировать: извините.должен был сделать различие в том, что была вызвана функция.

Спасибо!

Ответы [ 4 ]

3 голосов
/ 21 июля 2011

Ваш код C # недействителен.

Функция Encrypt принимает парольную фразу как string passphrase, но затем пытается сослаться на нее в этой строке byte[] pwdBytes = Encoding.UTF8.GetBytes(key);

Изменить keyна passphrase.

Две функции теперь дают одинаковые результаты для меня:

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 # (сописанное выше исправление опечатки)

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

Результат Python

XAW5KXVbItrc3WF0xW175UJoiAfonuf + s54w2iEs + 7A =

C # 1031 * C 1030*

XAW5KXVbItrc3WF0xW175UJoiAfonuf + s54w2iEs + 7A =

Я подозреваю, что вы повторно используете 'e' в коде Python несколько раз.Если вы раскомментируете последние две строки моего скрипта Python, вы увидите, что результат теперь другой.Но если вы раскомментируете последние три строки, вы увидите, что результат такой же.Как сказал Фун, это происходит из-за того, как работает CBC .

CBC (Cipher-block chaining) работает при шифровании последовательности байтов в блоках.Первый блок зашифрован путем включения IV с первыми байтами вашего открытого текста («Петух ...»).Второй блок использует результат этой первой операции вместо IV.

Когда вы вызываете e.encrypt() во второй раз (например, раскомментируя последние две строки скрипта Python), вы выбираете, где остановились,Вместо использования IV при шифровании первого блока, он будет использовать вывод последнего зашифрованного блока.Вот почему результаты выглядят иначе.Сняв три последние строки скрипта python, вы инициализируете новый шифратор, который будет использовать IV для своего первого блока, в результате чего вы получите идентичные результаты.

3 голосов
/ 20 июля 2011

изменил код 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

1 голос
/ 19 марта 2013

Этот эзотичный кодировщик 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

Я надеюсь, что это могло бы помочь. Приветствия

0 голосов
/ 04 декабря 2013

Реализация 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))
...