Форум сайта python.su
Функция decrypt работает а вот не могу разобраться как наоборот зашифровать строку
from Crypto.Cipher import AES import base64 def _decrypt(msg, key = None): if key is None: key = 'mysecretpassword' obj = AES.new(key, AES.MODE_CBC, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') r = obj.decrypt(base64.b64decode(msg)) padding = ord(r[-1]) print padding return r[0:(-padding)] def decrypt_request(msg): return _decrypt(msg) request_crypted ='dasdasdsada' request = decrypt_request(request_crypted) print request
Офлайн
Алгоритм AES шифрует блоками по 16 байт. Последовательность байт, которую надо зашифровать, в конце может быть короче 16 байт, поэтому там применяется заполнитель. А чтобы отделить заполнитель от шифруемой последовательности, записывается ещё длина заполнителя.
Поэтому
1. Входную последовательность нужно поделить на 16 и взять остаток от деления.
2. Затем из 16 вычесть этот остаток от деления и сохранить полученную разность.
3. Затем к входной последовательности нужно дописать нулевые байты в количестве, которое равно этой разности.
4. Затем вместо последнего нулевого байта нужно записать эту разность.
Отредактировано py.user.next (Март 4, 2016 03:37:06)
Офлайн
py.user.next
…нужно дописать нулевые байты…
import random import string import base64 from Crypto import Random from Crypto.Cipher import AES import hashlib def padding(s, bs=AES.block_size): if len(s) % bs == 0: return s + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(bs - 1)) + chr(96 - bs) if len(s) % bs > 0 and len(s) > bs: res = s + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(bs - len(s) % bs -1)) + chr(96 + len(s) % bs - bs) else: res = s + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(bs - len(s) - 1)) + chr(96 + len(s) - bs) return res def unpadding(s, bs=AES.block_size): return s[:ord(s[-1])-96] if len(s) % bs == 0 else '' class AESCipher: def __init__(self, key): # Лучше использовать хэш от ключа, тогда длина ключа может быть произвольной, # а иначе нужно использовать ключи длиной 16, 24, 32 только... self.key = hashlib.md5(key).hexdigest() def encrypt(self, raw): raw = padding(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(self, enc): enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return unpadding(cipher.decrypt(enc[AES.block_size:])) mycif = AESCipher(key='mypasskey') msg = 'My secret message' encrypted_msg1 = mycif.encrypt(msg) print encrypted_msg1 encrypted_msg2 = mycif.encrypt(msg) print encrypted_msg2 # Одинаковый текст каждый раз кодируется по-разному! print mycif.decrypt(encrypted_msg1) # Хотя и разный, но одинаково расшифровывается! print mycif.decrypt(encrypted_msg2)
Отредактировано scidam (Июнь 25, 2016 06:56:16)
Офлайн
scidamА как ты отличишь потом расшифрованный блок с заполнителем от расшифрованного блока без заполнителя?
Дополнять лучше не нулевыми байтами, а случайными
scidamДля последнего блока. Сообщение разбивается на блоки, которые потом проходят ряд трансформаций по очереди (блочный шифр). Если ты в последнем что-то поменяешь, остальные останутся неизменными.
тогда результат шифрования для одного и того же сообщения будет различный
Отредактировано py.user.next (Июнь 25, 2016 13:33:28)
Офлайн
py.user.next
А как ты отличишь потом расшифрованный блок с заполнителем от расшифрованного блока без заполнителя?
Офлайн
scidamА строка из 16 байт? Как ты отличишь строку “aaaaaaaaaaaaaaa” от строки “aaaaaaaaaaaaaaa\x01” ? Вот тебе надо зашифровать две эти разные строки одним алгоритмом. И получится, что при расшифровке ты вместо строки “aaaaaaaaaaaaaaa\x01” будешь получать “aaaaaaaaaaaaaaa”. А с чего вдруг, ты же шифровал изначально вот эту “aaaaaaaaaaaaaaa\x01”?
Стррка из 15 байт будет дополнена до 16 байт, последний байт будет кодировать длину заполнителя, в данном случае число 1.
Отредактировано py.user.next (Июнь 29, 2016 05:53:33)
Офлайн
py.user.next
Как ты поймёшь, какая из них - выравненная 15-байтовая строка, а какая - 16-байтовая строка без выравнивания?
py.user.next
Как ты отличишь строку “aaaaaaaaaaaaaaa” от строки “aaaaaaaaaaaaaaa\x01” ?
Офлайн
scidamС чего это ты взял? Я могу вообще взять строку из одних нулей и зашифровать её. И при расшифровке мне нужно получить её же прямо в точности. Кто сказал, что шифровать можно только текст?
А этот случай, мне кажется, не относится к делу
scidamС чего ты взял, вот она как интерпретируется
“aaaaaaaaaaaaaaa\x01” интерпретируется как ‘a’*16
>>> b'aaaaaaaaaaaaaaa\x01' b'aaaaaaaaaaaaaaa\x01' >>> len(_) 16 >>>
Отредактировано py.user.next (Июнь 29, 2016 09:29:19)
Офлайн
Но…. Вот мой полностью работающий вариант:
>>> import random, string >>> >>> def padding(s, bs=16): ... if len(s) % bs == 0: ... return s + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(bs - 1)) + chr(96 - bs) ... if len(s) % bs > 0 and len(s) > bs: ... res = s + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(bs - len(s) % bs -1)) + chr(96 + len(s) % bs - bs) ... else: ... res = s + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(bs - len(s) - 1)) + chr(96 + len(s) - bs) ... return res ... >>> def unpadding(s, bs=16): ... return s[:ord(s[-1])-96] if len(s) % bs == 0 else '' ... ... >>> msg = b'aaaaaaaaaaaaaaa\x01' >>> >>> print msg, padding(msg), unpadding(padding(msg)) aaaaaaaaaaaaaaa aaaaaaaaaaaaaaa1km4m7rnx50twwcP aaaaaaaaaaaaaaa >>> >>> final = unpadding(padding(msg)) >>> >>> print final == msg True >>>
Офлайн
Как вам такая ф-цыя?
WTF(aaaaaaaaaaaaaaa1km4m7rnx50twwcP)
Офлайн