Muszę napisać zestaw opakowań w Pythonie wokół symetrycznych szyfrów (AES, des itp.) W różnych trybach działania, które pozwalają na Crypto Agility. W szczególności, kod, który nazywa opakowania musi nie potrzebować wiedzy na to, co faktycznie chroni dane, dzięki czemu można go zmienić dynamicznie

Zasadniczo następujące następujące powinny trzymać (czy są to metody na obiekcie, oddzielne funkcje lub coś innego)

foo = MagicalEncryptor()
foo.ciphertext = foo.encrypt(data)
key = foo.key 
bar = MagicalEncryptor()
bar.key = key 
data = bar.decrypt(ciphertext)

Problem polega na tym, że w zależności od używanego trybu, wynikowy cypertekst będzie inny. Może być (tryb_CBC, IV, CipHertekst) dla CBC lub (Mode_GCM, IV, CIPHERTEXT, MAC) dla trybu GCM.

To bardzo wyraźnie narusza Zasada substytucji Lisku Ponieważ argument odszyfrowania Covariant. Jeśli dzwoniący zawiera instancję interfejsu generycznego {X0}}, który ma być w trybie GCM, nie może przekazać go instancji trybu EBC.

Co to jest dobre rozwiązanie Pythonic? (Lub czy odpowiedź po prostu nie troszczy się o to, aby nie przejmować się?) W szczególności potrzebuję, powinien pracować zarówno w 2,7, jak i 3.0, ale interesują mnie rozwiązania.

Również klucz musi mieć krótką reprezentację jako bitstream (prawdopodobnie 128 lub 256 bitów max). Ma to być stosowane w schematach szyfrowania hybrydowych, gdzie na przykład można wysłać (Rsa_enc (PublicKey, symetric_key_as_message) || AES (Symetrice_key_as_message, faktyczne_message).

2
imichaelmiers 27 październik 2011, 19:36

3 odpowiedzi

Najlepsza odpowiedź

Po Kirk, ale obierając w ostatniej chwili, niech polimorficzny klucz dba o wybór odpowiedniego rodzaju Decryptor:

foo = MagicalEncryptor()
foo.ciphertext = foo.encrypt(data)
key = foo.key 

bar = key.decryptor()
data = bar.decrypt(ciphertext)

Może tworzyć odpowiedni odcinek i przejść do siebie. Lub cokolwiek: protokół między kluczem a tworzeniem deszyrctorów jest prywatny.

Mogę nawet zmienić takie rzeczy:

key = createMagicalKey()

foo = key.encryptor()
ciphertext = foo.encrypt(data)

bar = key.decryptor()
data = bar.decrypt(ciphertext)

I oczywiście jest to tylko prosty krok do:

key = createMagicalKey()

ciphertext = key.encrypt(data)

data = key.decrypt(ciphertext)
1
Tom Anderson 27 październik 2011, 16:23

Metoda pierwsza: Zdecydowanie wpisz zaszyfrowane dane:

class GCMData(object):
    def __init__(self, data): self.data = data

    def __str__(self): return self.data
    __repr__ = __str__


class MagicalGCMEncryptor(object):
    def encrypt(self, data):
        return GCMData(self._encrypt(data))

    def decrypt(self, dataobj):
        if not isinstance(dataobj, GCMData):
            raise ValueError('Only decrypts GCM data')

Metoda Dwa: Inwert kontroli przepływu. Nie rób klas, które szyfrują dane. Utwórz obiekty danych, które przechowują zaszyfrowane dane:

class GCMEncryptedData(object):
    def __init__(self, data):
        self.data = [... do something with data]

    def __str__(self): return self.data
    __repr__ = __str__

    def decrypt(self):
        return [... do something with self.data]
0
Kirk Strauser 27 październik 2011, 16:05

"Bardzo wyraźnie narusza zasadę substytucji Lisków, ponieważ sprawia, że argument do odszyfrowania Covariant. Jeśli dzwoniący utrzymuje instancję ogólnego interfejsu Magicalkryptor, który ma być dla trybu GCM, nie może przekazać go instancji trybu EBC".

Nie powinno też. Szyfrowanie nie może być niezależne od trybu czarnego pudełka. Tak, można swap TDES z AES-256 bez zmiany wielu logiki wyższej, ale nie jest to prawdą dla zmiany trybów szyfrowania . Pomyśl o trybie jako protokołu i algorytm jako silnik. Protokół jest skomplikowany, ponieważ wymaga jego własnego zgłoszenia błędów specjalnych, mechanizmu awarii, procedur inicjalizacji, powiązanych danych, informacji państwa itp. Natomiast przełączanie silnika algorytmu jest łatwe.

Na przykład, gdy używasz GCM, musisz dbać, że nie szyfrujesz zbyt wiele wiadomości i szybciej obracasz klucze, aby utrzymać siłę kryptograficzną komputera Mac. To prawda, czy jest to TDES-GCM lub AES-256-GCM. Oznacza to, że powinieneś śledzić, ile wiadomości zostało zaszyfrowanych - nawet jeśli jest to szacunek ballpark, taki jak "Repeey w każdy x dni podczas korzystania z trybu Y" (choć naprawdę dbasz o ilość przetwarzanych danych).

Nie masz tych obaw (na poziomie praktycznym) z EBC, ale masz cały inny zestaw (znacznie trudniejszych) dotyczących wycieków informacji.

Tryb CBC ma własne pułapki zużycia, zwłaszcza jeśli korzystasz z CBC-Mac. W zależności od zastosowanej metody uwierzytelniania należy zachować ostrożność na temat zgłaszania komunikatów o błędach, gdy Mac nie powiedzie się - w niektórych przypadkach awaria MAC powinna spowodować zniszczenie klucza (np. Klawisze sesji), ale w innych przypadkach niepowodzenie Mac powinien doprowadzić tylko do resetowania uruchomienia protokołu (utrzymywanie zestawów kluczy uwierzytelniających). Albo może może odtworzyć wiadomość - zależy od tego, jak budujesz protokół i jakie algorytmy używasz.

Jeśli używasz trybu szyfrowania poprawek do przechowywanych danych, zależy Ci na tym, gdzie dane znajdują się na dysku, a ponowne użycie tego samego klucza poprawiającego i wartości pozycyjnej, jeśli nadpisujesz blok na miejscu. Ale nigdy nie ponowne wykorzystanie licznika wiadomości z tym samym kluczem sesji, jeśli szyfrujesz kanał. Tryby szyfrowania odpowiednie do szyfrowania danych w miejscu nie mają nakładania się z trybami szyfrowania odpowiednich do szyfrowania kanału. Nie są ze sobą zmienni.

Wszystko to narusza zasadę podstawienia Liskova, chyba że spróbujesz wdrożyć ogólny obiekt "Bezpieczeństwo", który może specjalizować się do każdego możliwego protokołu ochrony danych.

Ponadto nigdy * * * Używaj tego samego klucza w dwóch różnych trybach lub dwóch różnych silnikach algorytmowych.

Dlaczego więc zaprojektować kod w taki sposób, który pozwala na specjalizację kluczowego obiektu do specjalizacji do więcej niż jednej implementacji algorytmu? Teraz Twój zespół Bezpieczeństwa będzie wracać nad kodem i upewnić się, że ta ogólność nie otwiera żadnych otworów dla atakującego, aby uzyskać twoją aplikację nadużywać klucza, używając go w niewłaściwy sposób. Musisz wrócić i upewnić się, że po utworzeniu klucza, w pełni określić tryb i algorytm, z którym będzie używany w konstruktorze klucza, który wraca do problemu długości klucza. Wszelkie późniejsze próby użycia klucza w A z innym algorytmem lub trybem, z którym został utworzony, powinien skutkować błędem krytycznym.

Ale w takim przypadku, co oznacza "Agility algorytm" oznacza, czy użytkownicy lub aplikacja musi tworzyć nowe klucze i / lub rejestrować istniejące dane na miejscu za każdym razem, gdy system bazowy przyjmuje nowy algorytm?

0
rsj 1 listopad 2011, 21:44