🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.programming
8 messages
8 total messages Started by Roman Tyczka Mon, 15 Feb 2021 13:28
Algorytm AES
#217394
Author: Roman Tyczka
Date: Mon, 15 Feb 2021 13:28
58 lines
3466 bytes
Witam,

Nie znam Pythona, ale się trochę go zaczynam uczyć, bo potrzebuję nim 
sprawdzić poprawność szyfrowania/deszyfrowania różnymi algorytmami 
biblioteki w innym języku.
Napisałem krótki program, który za pomocą dwóch implementacji algorytmu 
AES szyfruje i deszyfruje łańcuch tekstowy:

import binascii
import pyaes
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

key = b'01234567012345670123456701234567'
iv = bytearray(16)

plaintext = ('Some short description with looooooooong '
              'additional data like polish diacritical chars... łóżźćęół 
and digits 0123456789')
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(key, iv.decode()))
ciphertext = encrypter.feed(plaintext.encode('utf_8'))
ciphertext += encrypter.feed()
print("Encrypted AES256'1:", binascii.hexlify(ciphertext).upper())

aes = pyaes.AESModeOfOperationCBC(key)
decrypter = pyaes.Decrypter(aes)
decrypt = decrypter.feed(ciphertext)
decrypt += decrypter.feed()
print('Decrypted:', decrypt.decode('utf_8'))
print()

iv = bytearray(16)
cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
encryptor = cipher.encryptor()
ct = encryptor.update(plaintext.encode('utf_8')) + encryptor.finalize()
print("Encrypted AES256'2:", binascii.hexlify(ct).upper())

decryptor = cipher.decryptor()
dc = decryptor.update(ct) + decryptor.finalize()
print('Decrypted:', dc.decode('utf_8'))

Wyniki:

Encrypted AES256'1: 
b'B623A479FC657E31F219287CD191075575B2FB56485D0C22E9168A2BF2289C7165CDA67586A486E14115C754ABA158A84A8C3B521E0DF87505D77649A8F1CB52A03D41E205849F28BCA2DE189A9C65CDB648DBC9F7D49AF2F1704B491E9E2DE6FC357ADC8E15733394C3C75B45570AE77A2A6CB6CC4418A558A78313C0C16478A7D61538B88B486BCAE89235D8FCEEB8'

Encrypted AES256'2: 
b'B623A479FC657E31F219287CD191075575B2FB56485D0C22E9168A2BF2289C7165CDA67586A486E14115C754ABA158A84A8C3B521E0DF87505D77649A8F1CB52A03D41E205849F28BCA2DE189A9C65CDB648DBC9F7D49AF2F1704B491E9E2DE6FC357ADC8E15733394C3C75B45570AE77A2A6CB6CC4418A558A78313C0C16478'

I teraz mam pytanie dlaczego szyfrogram pierwszej biblioteki jest o 16 
bajtów dłuższy niż drugiej? Nie jest to initialization vector, bo ten 
ustawiony jest na 16 zer. Z czego wynika i czym jest ta różnica?
Różnica jest na końcu i wygląda tak:

A7D61538B88B486BCAE89235D8FCEEB8

-- 
pzdr
Roman
Re: Algorytm AES
#217395
Author: Roman Tyczka
Date: Mon, 15 Feb 2021 15:19
11 lines
1526 bytes
W dniu 15.02.2021 o 14:28, Roman Tyczka pisze:
> I teraz mam pytanie dlaczego szyfrogram pierwszej biblioteki jest o 16 
> bajtów dłuższy niż drugiej? Nie jest to initialization vector, bo ten 
> ustawiony jest na 16 zer. Z czego wynika i czym jest ta różnica?
> Różnica jest na końcu i wygląda tak:

Ok, już doszedłem, chodziło o defaultowy padding.

-- 
pzdr
Roman
Re: Algorytm AES
#217396
Author: Maciej Sobczak
Date: Mon, 15 Feb 2021 16:03
13 lines
2570 bytes
> > I teraz mam pytanie dlaczego szyfrogram pierwszej biblioteki jest o 16 
> > bajtów dłuższy niż drugiej?
> Ok, już doszedłem, chodziło o defaultowy padding. 

Jeśli 16, to raczej nie padding, bo cały blok ma 16. Tu masz dodany cały blok, a nie dodany padding jako wypełniacz do końca bloku.

Miałem podobną zagadkę z Wolframem, i tam ten efekt był wywołany nie paddingiem, tylko tym, że Wolfram dodaje do początkowej tablicy informację o jej długości - bo można szyfrować tekst o dowolnej długości, np. "Hello" ma 5 bajtów. Dodanie długości do czegoś, co ma 5 bajtów nie jest problemem, bo robi się z tego powiedzmy 6 bajtów, czyli nadal mieścimy się w jednym bloku. Zabawa jest przy szyfrowaniu tekstu, który już na początku ma równe 16 bajtów (np. "abcdefghijklmnop"), bo nie ma gdzie dodać znacznika długości - wtedy dodawany jest pełny nowy blok tylko po to, żeby miał zaszytą informację, że ten ostatni blok ma długość 0 (tak, głupie, ale odszyfrowanie zawsze wtedy dobry wynik). I stąd się robi równe 16 bajtów więcej w zaszyfrowanej wiadomości.
Może w Twoim przypadku też tak jest?

Te drobiazgi są oczywiście istotne wtedy, gdy jedną biblioteką szyfrujemy a inną deszyfrujemy, bo jedna biblioteka sama ze sobą zwykle nie sprawia problemów.

-- 
Maciej Sobczak * http://www.inspirel.com
Re: Algorytm AES
#217397
Author: Roman Tyczka
Date: Tue, 16 Feb 2021 13:19
44 lines
3902 bytes
W dniu 15.02.2021 o 17:03, Maciej Sobczak pisze:
>>> I teraz mam pytanie dlaczego szyfrogram pierwszej biblioteki jest o 16
>>> bajtów dłuższy niż drugiej?
>> Ok, już doszedłem, chodziło o defaultowy padding.
> 
> Jeśli 16, to raczej nie padding, bo cały blok ma 16. Tu masz dodany cały blok, a nie dodany padding jako wypełniacz do końca bloku.
> 
> Miałem podobną zagadkę z Wolframem, i tam ten efekt był wywołany nie paddingiem, tylko tym, że Wolfram dodaje do początkowej tablicy informację o jej długości - bo można szyfrować tekst o dowolnej długości, np. "Hello" ma 5 bajtów. Dodanie długości do czegoś, co ma 5 bajtów nie jest problemem, bo robi się z tego powiedzmy 6 bajtów, czyli nadal mieścimy się w jednym bloku. Zabawa jest przy szyfrowaniu tekstu, który już na początku ma równe 16 bajtów (np. "abcdefghijklmnop"), bo nie ma gdzie dodać znacznika długości - wtedy dodawany jest pełny nowy blok tylko po to, żeby miał zaszytą informację, że ten ostatni blok ma długość 0 (tak, głupie, ale odszyfrowanie zawsze wtedy dobry wynik). I stąd się robi równe 16 bajtów więcej w zaszyfrowanej wiadomości.
> Może w Twoim przypadku też tak jest?

W moim przypadku, gdy jawnie nie podałem rodzaju paddingu to był brany 
DEFAULT_PADDING i wtedy rozmiar był o blok dłuższy. Gdy podałem 
PADDING_NONE to rozmiar wyniku był taki sam jak z drugiej biblioteki.
A tak wygląda kod, który dodaje te dodatkowe dane:

def _block_final_encrypt(self, data, padding = PADDING_DEFAULT):
     if padding == PADDING_DEFAULT:
         data = append_PKCS7_padding(data)

     elif padding == PADDING_NONE:
         if len(data) != 16:
             raise Exception('invalid data length for final block')
     else:
         raise Exception('invalid padding option')

     if len(data) == 32:
         return self.encrypt(data[:16]) + self.encrypt(data[16:])

     return self.encrypt(data)

Nie jestem ekspertem od kryptografii, więc nie wiem dlaczego dodawany 
jest cały blok, może błąd w bibliotece. Patrząc zaś na ten kod 
zastanawia mnie jeszcze warunek w elif... wygląda to jakbym fuksem 
trafiał z PADDING_NONE w 16 bajtowy ostatni blok.
Ale już tego nie drążę, bo używam tylko tej drugiej biblioteki, jest 
bardziej uniwersalna i ma więcej algorytmów.

> Te drobiazgi są oczywiście istotne wtedy, gdy jedną biblioteką szyfrujemy a inną deszyfrujemy, bo jedna biblioteka sama ze sobą zwykle nie sprawia problemów.

No właśnie szukam zgodności do wymiany danych między systemami.

-- 
pzdr
Roman
Re: Algorytm AES
#217398
Author: Roman Tyczka
Date: Tue, 23 Feb 2021 09:03
34 lines
2455 bytes
W dniu 15.02.2021 o 17:03, Maciej Sobczak pisze:
>>> I teraz mam pytanie dlaczego szyfrogram pierwszej biblioteki jest o 16
>>> bajtów dłuższy niż drugiej?
>> Ok, już doszedłem, chodziło o defaultowy padding.
> 
> Jeśli 16, to raczej nie padding, bo cały blok ma 16. Tu masz dodany cały blok, a nie dodany padding jako wypełniacz do końca bloku.

Mam fajny przykład, że to jednak padding. Bierzemy powszechnego i 
uznanego za standard klienta openssl, tworzymy plik tekstowy o długości 
32 bajtów oraz nazwie test.txt i wykonujemy polecenie:

openssl enc -aes-128-cbc -in test.txt -out test.enc -K 
$"30313233343536373839303132333435" -iv $"30313233343536373839303132333435"

Jako wynik otrzymujemy plik test.enc o rozmiarze ...48 bajtów!

I teraz do parametrów wywołania openssl dodajemy parametr -nopad:

openssl enc -aes-128-cbc -nopad -in test.txt -out test.enc -K 
$"30313233343536373839303132333435" -iv $"30313233343536373839303132333435"

i nagle plik wynikowy ma 32 bajty... czyli tyle ile wejściowy.
A parametr -nopad opisany jest w dokumentacji tak:

-nopad

     Disable standard block padding.


Czyli jak to rozumieć? :-)

-- 
pzdr
Roman
Re: Algorytm AES
#217399
Author: Maciej Sobczak
Date: Tue, 23 Feb 2021 16:15
22 lines
2477 bytes
> Mam fajny przykład, że to jednak padding.
[...]
> A parametr -nopad opisany jest w dokumentacji tak: 
> 
> Disable standard block padding. 
> 
> Czyli jak to rozumieć? :-) 

https://en.wikipedia.org/wiki/Padding_(cryptography)

Według tej terminologii, jest to padding. Ale co to jest "standard block padding", to już niestety tylko autorzy tej dokumentacji wiedzą.
Natomiast to:

https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS#5_and_PKCS#7

jest "standardowym" paddingiem i działa dokładnie tak, jak opisałem poprzednio, czyli pozwala na odtworzenie oryginalnej długości komunikatu i wymaga dodania pełnego bloku, jeśli oryginał miał już długość będącą wielokrotnością bloku.
Może jednak o to chodzi? Dla mnie to jest kodowanie długości a nie padding, ale nie będę się o to strzelał.

Zrób tak: zaszyfruj coś z paddingiem i odszyfruj bez niego. I zobacz wtedy, jaka jest zawartość tego dodatkowego bloku, bo on się "odszyfruje" i w ten sposób ujawni. Jeśli to będą same bajty o wartości 16, to jest to właśnie ten rodzaj paddingu.

-- 
Maciej Sobczak * http://www.inspirel.com
Re: Algorytm AES
#217400
Author: Roman Tyczka
Date: Thu, 25 Feb 2021 11:10
13 lines
2059 bytes
W dniu 23.02.2021 o 17:15, Maciej Sobczak pisze:
> Zrób tak: zaszyfruj coś z paddingiem i odszyfruj bez niego. I zobacz wtedy, jaka jest zawartość tego dodatkowego bloku, bo on się "odszyfruje" i w ten sposób ujawni. Jeśli to będą same bajty o wartości 16, to jest to właśnie ten rodzaj paddingu.

Zrobiłem jak proponujesz, z 48 bajtowego pliku z paddingiem powstał 32 
bajtowy plik ze stringiem początkowym... i ani bicika więcej :-)

Pozostanie to już zagadką deweloperów openssla. Ja w każdym razie 
poczyniłem postępy na polu rozumienia szyfrowania symetrycznego, 
blokowego i dzięki Ci za udział w lekcji.

-- 
pzdr
Roman
Re: Algorytm AES
#217401
Author: Maciej Sobczak
Date: Thu, 25 Feb 2021 15:38
13 lines
2221 bytes
> Zrobiłem jak proponujesz, z 48 bajtowego pliku z paddingiem powstał 32 
> bajtowy plik ze stringiem początkowym... i ani bicika więcej :-) 

To lipa jakaś. Ja właśnie w ten sposób (ale nie z openssl) odkryłem, co tam jest dodawane. To tak, jakby opcja no-padding nie działała. A może przy odszyfrowaniu ta funkcja się inaczej nazywa? Np. --no-remove-padding?
Bo przecież możesz mieć zupełnie legalny komunikat z 3 bloków po 16 bajtów, bez paddingu albo z paddingiem innego rodzaju i chcesz go odszyfrować. I po odszyfrowaniu mają być 3 bloki po 16 bajtów.
Albo możesz chcieć odszyfrować to inną biblioteką. Itd.

> Pozostanie to już zagadką deweloperów openssla.

Ja bym walczył dalej. ;-)

-- 
Maciej Sobczak * http://www.inspirel.com
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads