Czy Python ma wbudowany, prosty sposób kodowania / dekodowania ciągów za pomocą hasła?
Coś takiego:
>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'
Zatem ciąg „John Doe” zostaje zaszyfrowany jako „sjkl28cn2sx0”. Aby uzyskać oryginalny ciąg, „odblokowałbym” ten ciąg za pomocą klucza „mypass”, który jest hasłem w moim kodzie źródłowym. Chciałbym, aby był to sposób, w jaki mogę zaszyfrować / odszyfrować dokument Word za pomocą hasła.
Chciałbym użyć tych zaszyfrowanych ciągów jako parametrów adresu URL. Moim celem jest zaciemnianie, a nie silne zabezpieczenia; nic krytycznego dla misji nie jest kodowane. Zdaję sobie sprawę, że mógłbym użyć tabeli bazy danych do przechowywania kluczy i wartości, ale staram się być minimalistyczny.
python
encryption
passwords
RexE
źródło
źródło
Odpowiedzi:
Zakładając, że szukasz tylko prostego zaciemnienia, które zasłoni rzeczy przed bardzo przypadkowym obserwatorem i nie chcesz korzystać z bibliotek stron trzecich. Poleciłbym coś takiego jak szyfr Vigenere. Jest to jeden z najsilniejszych z prostych starożytnych szyfrów.
Szyfr Vigenère'a
To szybkie i łatwe do wdrożenia. Coś jak:
Dekodowanie jest prawie takie samo, z wyjątkiem odejmowania klucza.
Znacznie trudniej jest złamać, jeśli kodowane łańcuchy są krótkie i / lub jeśli trudno jest odgadnąć długość użytego hasła.
Jeśli szukasz czegoś kryptograficznego, PyCrypto jest prawdopodobnie najlepszym rozwiązaniem, chociaż poprzednie odpowiedzi pomijają niektóre szczegóły: tryb EBC w PyCrypto wymaga, aby twoja wiadomość składała się z wielokrotności 16 znaków. Więc musisz padać. Ponadto, jeśli chcesz ich używać jako parametrów adresu URL, użyj
base64.urlsafe_b64_encode()
zamiast standardowego. Spowoduje to zastąpienie kilku znaków w alfabecie base64 znakami bezpiecznymi dla adresów URL (jak sugeruje nazwa).Jednak powinieneś być ABSOLUTNIE pewny, że ta bardzo cienka warstwa zaciemniania wystarczy dla twoich potrzeb przed użyciem. Artykuł w Wikipedii, do którego odsyłam, zawiera szczegółowe instrukcje dotyczące łamania szyfru, aby każdy z umiarkowaną determinacją mógł go łatwo złamać.
źródło
'str' object cannot be interpreted as an integer
Ponieważ wyraźnie stwierdzasz, że wolisz tajemnicę, a nie bezpieczeństwo, unikniemy upominania Cię za słabość tego, co sugerujesz :)
Tak więc, używając PyCrypto:
Jeśli ktoś przejmie Twoją bazę danych i bazę kodu, będzie mógł odszyfrować zaszyfrowane dane. Dbaj o swoje
secret_key
bezpieczeństwo!źródło
encrypt
funkcja jest stanową dlitz.net/software/pycrypto/api/current/, więc nie powinieneś próbować jej używać ponownie.Python nie ma wbudowanych schematów szyfrowania, nie. Powinieneś również poważnie potraktować przechowywanie zaszyfrowanych danych; trywialne schematy szyfrowania, które jeden programista uważa za niepewne, a schemat zabawkowy może być mylony z bezpiecznym schematem przez mniej doświadczonego programistę. Jeśli szyfrujesz, zaszyfruj poprawnie.
Jednak nie musisz wykonywać wiele pracy, aby zaimplementować odpowiedni schemat szyfrowania. Przede wszystkim nie wymyślaj ponownie koła kryptograficznego , użyj zaufanej biblioteki kryptograficznej, aby załatwić to za Ciebie. W przypadku Pythona 3 ta zaufana biblioteka to
cryptography
.Zalecam również, aby szyfrowanie i deszyfrowanie dotyczyło bajtów ; najpierw zakoduj wiadomości tekstowe do bajtów;
stringvalue.encode()
koduje do UTF8, łatwo przywracany ponownie przy użyciubytesvalue.decode()
.Wreszcie, podczas szyfrowania i odszyfrowywania mówimy o kluczach , a nie hasłach. Klucz nie powinien być niezapomniany dla człowieka, jest to coś, co przechowujesz w tajnym miejscu, ale można je odczytać maszynowo, podczas gdy hasło często może być czytelne dla człowieka i zapamiętane. Państwo może czerpać klucz z hasłem, przy odrobinie opieki.
Ale aby aplikacja internetowa lub proces działały w klastrze bez ludzkiej uwagi, aby go nadal uruchamiać, chcesz użyć klucza. Hasła są używane, gdy tylko użytkownik końcowy potrzebuje dostępu do określonych informacji. Nawet wtedy zazwyczaj zabezpieczasz aplikację hasłem, a następnie wymieniasz zaszyfrowane informacje za pomocą klucza, być może dołączonego do konta użytkownika.
Szyfrowanie klucza symetrycznego
Fernet - AES CBC + HMAC, zdecydowanie zalecane
cryptography
Biblioteka zawiera przepis Fernet , najlepszy przepis na praktykach za pomocą kryptografii. Fernet to otwarty standard , z gotowymi implementacjami w szerokiej gamie języków programowania, który zawiera szyfrowanie AES CBC wraz z informacjami o wersji, sygnaturą czasową i podpisem HMAC, aby zapobiec manipulowaniu wiadomościami.Fernet bardzo ułatwia szyfrowanie i odszyfrowywanie wiadomości oraz zapewnia bezpieczeństwo. Jest to idealna metoda szyfrowania danych za pomocą sekretu.
Zalecam użycie
Fernet.generate_key()
do wygenerowania bezpiecznego klucza. Możesz też użyć hasła (następna sekcja), ale pełny 32-bajtowy tajny klucz (16 bajtów do zaszyfrowania plus kolejne 16 do podpisu) będzie bezpieczniejszy niż większość haseł, jakie możesz sobie wyobrazić.Klucz, który generuje Fernet, to
bytes
obiekt z adresem URL i plikami bezpiecznymi znakami base64, więc można go wydrukować:Aby zaszyfrować lub odszyfrować wiadomości, utwórz
Fernet()
wystąpienie z podanym kluczem i wywołajFernet.encrypt()
lubFernet.decrypt()
, zarówno wiadomość w postaci zwykłego tekstu do zaszyfrowania, jak i zaszyfrowany token sąbytes
obiektami.encrypt()
adecrypt()
funkcje wyglądałyby następująco:Próbny:
Fernet z hasłem - klucz pochodzący z hasła, nieco osłabia bezpieczeństwo
Możesz użyć hasła zamiast tajnego klucza, pod warunkiem, że używasz silnej metody wyprowadzania klucza . Następnie musisz uwzględnić sól i liczbę iteracji HMAC w wiadomości, więc zaszyfrowana wartość nie jest już zgodna z Fernetem bez uprzedniego oddzielenia soli, liczby i tokenu Ferneta:
Próbny:
Dołączenie soli do danych wyjściowych umożliwia użycie losowej wartości soli, co z kolei gwarantuje, że zaszyfrowane dane wyjściowe będą w pełni losowe, niezależnie od ponownego użycia hasła lub powtórzenia wiadomości. Uwzględnienie liczby iteracji zapewnia, że możesz dostosować się do wzrostu wydajności procesora w czasie bez utraty możliwości odszyfrowania starszych wiadomości.
Samo hasło może być równie bezpieczne, jak 32-bajtowy losowy klucz Fernet, pod warunkiem że wygenerujesz odpowiednio losowe hasło z puli o podobnej wielkości. 32 bajty to 256 ^ 32 liczby kluczy, więc jeśli używasz alfabetu składającego się z 74 znaków (26 górnych, 26 dolnych, 10 cyfr i 12 możliwych symboli), to Twoje hasło powinno mieć co najmniej
math.ceil(math.log(256 ** 32, 74))
== 42 znaki. Jednak dobrze dobrana większa liczba iteracji HMAC może nieco złagodzić brak entropii, ponieważ sprawia to, że atak brutalny jest znacznie droższy.Po prostu wiedz, że wybranie krótszego, ale wciąż rozsądnie bezpiecznego hasła nie zepsuje tego schematu, po prostu zmniejszy liczbę możliwych wartości, które atakujący musiałby przeszukać. upewnij się, że wybrałeś wystarczająco silne hasło dla swoich wymagań bezpieczeństwa .
Alternatywy
Niewyraźne
Alternatywą nie jest szyfrowanie . Nie ulegaj pokusie, aby po prostu użyć szyfru o niskim poziomie bezpieczeństwa lub własnej implementacji, powiedzmy Vignere. W tych podejściach nie ma zabezpieczeń, ale może dać niedoświadczonemu programistowi, któremu powierzono zadanie utrzymania twojego kodu w przyszłości, iluzję bezpieczeństwa, która jest gorsza niż brak bezpieczeństwa.
Jeśli potrzebujesz tylko niejasności, po prostu base64 dane; w przypadku wymagań dotyczących bezpieczeństwa adresów URL
base64.urlsafe_b64encode()
funkcja jest w porządku. Nie używaj tutaj hasła, po prostu zakoduj i gotowe. Co najwyżej dodaj trochę kompresji (na przykładzlib
):To zmienia się
b'Hello world!'
wb'eNrzSM3JyVcozy_KSVEEAB0JBF4='
.Tylko uczciwość
Jeśli potrzebujesz tylko sposobu, aby upewnić się, że dane mogą być niezmienione po wysłaniu do niezaufanego klienta i odebraniu z powrotem, to chcesz podpisać dane, możesz użyć do tego
hmac
biblioteki za pomocą SHA1 (nadal uważany za bezpieczny do podpisywania HMAC ) lub lepszy:Użyj tego do podpisania danych, a następnie dołącz podpis do danych i wyślij go do klienta. Po otrzymaniu danych podziel je i podpis, a następnie zweryfikuj. Ustawiłem domyślny algorytm na SHA256, więc będziesz potrzebować 32-bajtowego klucza:
Możesz zajrzeć do
itsdangerous
biblioteki , która pakuje to wszystko z serializacją i deserializacją w różnych formatach.Korzystanie z szyfrowania AES-GCM w celu zapewnienia szyfrowania i integralności
Fernet opiera się na AEC-CBC z podpisem HMAC, aby zapewnić integralność zaszyfrowanych danych; złośliwy napastnik nie może przesyłać do twojego systemu nonsensownych danych, aby Twoja usługa była zajęta działaniem w kółko ze złymi danymi wejściowymi, ponieważ szyfrogram jest podpisany.
Galois / Licznik szyfr blokowy tryb wytwarza szyfrogram i tag służyć temu samemu celowi, więc może być używany, aby służyć tym samym celom. Wadą jest to, że w przeciwieństwie do Ferneta nie ma łatwego w użyciu uniwersalnego przepisu do ponownego wykorzystania na innych platformach. AES-GCM również nie używa dopełnienia, więc ten zaszyfrowany tekst jest zgodny z długością wiadomości wejściowej (podczas gdy Fernet / AES-CBC szyfruje wiadomości do bloków o stałej długości, nieco zaciemniając długość wiadomości).
AES256-GCM przyjmuje zwykły 32-bajtowy sekret jako klucz:
następnie użyj
Dodałem sygnaturę czasową, aby obsługiwać te same przypadki użycia, które obsługuje Fernet.
Inne podejścia na tej stronie, w Pythonie 3
AES CFB - jak CBC, ale bez potrzeby stosowania podkładek
Jest to podejście, które stosuje All Іѕ Vаиітy , aczkolwiek niepoprawne. To jest
cryptography
wersja, ale zauważ, że dołączam IV do zaszyfrowanego tekstu , nie powinien być przechowywany jako globalny (ponowne użycie IV osłabia bezpieczeństwo klucza, a przechowywanie go jako modułu globalnego oznacza, że zostanie on ponownie wygenerowany następne wywołanie Pythona, uniemożliwiające odszyfrowanie całego tekstu zaszyfrowanego):Brakuje dodatkowego opancerzenia podpisu HMAC i nie ma znacznika czasu; musiałbyś je dodać samodzielnie.
Powyższe pokazuje również, jak łatwo jest niepoprawnie łączyć podstawowe elementy kryptograficzne; Wszystkie niepoprawne obchodzenie się z wartością IV przez Vаиітy może prowadzić do naruszenia danych lub nieczytelności wszystkich zaszyfrowanych wiadomości z powodu utraty IV. Korzystanie z Ferneta chroni Cię przed takimi błędami.
AES EBC - niezabezpieczone
Jeśli wcześniej zaimplementowałeś szyfrowanie AES ECB i nadal potrzebujesz go obsługiwać w Pythonie 3, możesz to zrobić
cryptography
również z . Obowiązują te same zastrzeżenia, EBC nie jest wystarczająco bezpieczny dla rzeczywistych zastosowań . Ponowna implementacja tej odpowiedzi dla Pythona 3, dodając automatyczną obsługę wypełnienia:Ponownie, brakuje podpisu HMAC i i tak nie powinieneś używać EBC. Powyższe ma na celu jedynie zilustrowanie, że
cryptography
poradzi sobie z typowymi elementami kryptograficznymi, nawet tymi, których w rzeczywistości nie powinieneś używać.źródło
Element „encoded_c” wspomniany w odpowiedzi szyfru Vigenere @ smehmood powinien mieć wartość „key_c”.
Oto działające funkcje kodowania / dekodowania.
Zastrzeżenie: jak sugerują komentarze, nie należy tego używać do ochrony danych w prawdziwej aplikacji, chyba że przeczytasz to i nie masz nic przeciwko rozmowie z prawnikami:
Co jest nie tak z szyfrowaniem XOR?
źródło
encodedmsg = encode('mypassword', 'this is the message éçàèç"')
print encodedmsg
print decode('mypassword', encodedmsg)
działa dobrze.Oto Python 3 wersja funkcji z @qneill jest odpowiedź :
Dodatkowe kodowanie / dekodowanie jest potrzebne, ponieważ Python 3 podzielił ciągi / tablice bajtów na dwie różne koncepcje i zaktualizował ich interfejsy API, aby to odzwierciedlić.
źródło
.encode()).decode()
. w powrocieencode()
i.decode()
w drugim wierszu wdecode()
.Zastrzeżenie: jak wspomniano w komentarzach, nie należy tego używać do ochrony danych w prawdziwej aplikacji.
Co jest nie tak z szyfrowaniem XOR?
/crypto/56281/breaking-a-xor-cipher-of-known-key-length
https://github.com/hellman/xortool
Jak już wspomniano, biblioteka PyCrypto zawiera zestaw szyfrów. „Szyfr” XOR może być użyty do wykonania brudnej roboty, jeśli nie chcesz tego robić samodzielnie:
Szyfr działa w następujący sposób bez konieczności uzupełniania tekstu jawnego:
Kredyt dla https://stackoverflow.com/a/2490376/241294 za funkcje kodowania / dekodowania base64 (jestem nowicjuszem w Pythonie).
źródło
sudo pip3 install pycrypto
.Oto implementacja bezpiecznego szyfrowania i deszyfrowania adresów URL przy użyciu AES (PyCrypto) i base64.
Jeśli napotkasz jakiś problem, taki jak ten https://bugs.python.org/issue4329 (
TypeError: character mapping must return integer, None or unicode
), użyjstr(cipher)
podczas dekodowania w następujący sposób:Test:
źródło
TypeError: Object type <class 'str'> cannot be passed to C code
.b'...'
, zredagowałem odpowiedź na przyszłość!Działające funkcje kodujące / dekodujące w pythonie3 (bardzo niewiele zaadaptowane z odpowiedzi qneilla):
źródło
Dzięki za kilka świetnych odpowiedzi. Nie ma nic oryginalnego do dodania, ale oto kilka stopniowych przeróbek odpowiedzi qneilla przy użyciu przydatnych funkcji Pythona. Mam nadzieję, że zgadzasz się, że upraszczają i wyjaśniają kod.
źródło
Jeśli chcesz być bezpieczny, możesz użyć Ferneta, który jest bezpieczny pod względem kryptograficznym. Możesz użyć statycznej „soli”, jeśli nie chcesz jej przechowywać osobno - stracisz jedynie słownik i zapobiegniesz atakowi tęczy. Wybrałem to, ponieważ mogę wybierać długie lub krótkie hasła ”, co nie jest takie łatwe w przypadku AES.
Jeśli to zbyt skomplikowane, ktoś zasugerował simplecrypt
źródło
Ktokolwiek tu przybył (i hojniejszy), wydawał się szukać jednowierszowych z niewielką konfiguracją, których inne odpowiedzi nie zapewniają. Dlatego przedstawiam base64.
Teraz pamiętaj, że jest to tylko podstawowe zaciemnianie i jest w ** ŻADNYM ŻADNYM SPOSOBIE BEZPIECZEŃSTWA ** , ale oto kilka linijek:
Kilka uwag:
bytes()
ibytes::decode()
=
znakami. Ludzie tacy jak ja absolutnie dekodują je w konsoli javascript, kiedy widzimy je na stronach internetowych. To tak proste, jakbtoa(string)
(js)Teraz, jeśli to, czego chciałeś, nie wymagało nawet żadnego klucza, ale tylko trochę zaciemnienia, możesz ponownie po prostu użyć base64, bez żadnego rodzaju klucza:
źródło
Fernet(key).encrypt(message)
jest tylko jednym wyrażeniem, tak jak wywołanie base64.key
całkowicie. Mnóstwo twórców zamiar skopiować i wkleić z przepełnienie stosu bez zwracania uwagi i będzie zakładać klucz jako tajne. Jeśli musisz go uwzględnić, przynajmniej nie używaj go i ostrzegaj lub zgłaszaj wyjątek, jeśli mimo to jest używany. Nie lekceważ głupoty kultury kopiowania i wklejania oraz swoich obowiązków dostarczania rozsądnych funkcji.Podam 4 rozwiązania:
1) Korzystanie z szyfrowania Fernet z
cryptography
bibliotekąOto rozwiązanie wykorzystujące pakiet
cryptography
, który możesz zainstalować jak zwykle za pomocąpip install cryptography
:Możesz dostosować się za pomocą własnej soli, liczby iteracji itp. Ten kod nie jest bardzo odległy od odpowiedzi @ HCLivess, ale celem jest posiadanie gotowych do użycia
encrypt
idecrypt
funkcji. Źródło: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet .Uwaga: użyj
.encode()
i.decode()
wszędzie, jeśli chcesz ciągów'John Doe'
zamiast bajtów, takich jakb'John Doe'
.2) Proste szyfrowanie AES z
Crypto
bibliotekąDziała to z Pythonem 3:
Uwaga: możesz usunąć,
base64.b64encode
a.b64decode
jeśli nie chcesz, aby dane wyjściowe były czytelne dla tekstu i / lub jeśli i tak chcesz zapisać zaszyfrowany tekst na dysk jako plik binarny.3) AES wykorzystujący lepszą funkcję wyprowadzania klucza hasła i możliwość sprawdzenia, czy wprowadzono nieprawidłowe hasło, w
Crypto
biblioteceRozwiązanie 2) z „trybem CFB” AES jest w porządku, ale ma dwie wady: fakt, że
SHA256(password)
można go łatwo zmodyfikować za pomocą tabeli przeglądowej oraz że nie ma możliwości sprawdzenia, czy wprowadzono nieprawidłowe hasło. Można to tutaj rozwiązać przez użycie AES w „trybie GCM”, jak omówiono w AES: jak wykryć, że wprowadzono złe hasło? i czy ta metoda powiedzenia „Podane hasło jest nieprawidłowe” jest bezpieczna? :4) Korzystanie z RC4 (bez biblioteki)
Na podstawie https://github.com/bozhu/RC4-Python/blob/master/rc4.py .
(Nieaktualne od ostatnich zmian, ale zachowane do przyszłego użytku): Miałem problemy z używaniem systemu Windows + Python 3.6 + wszystkie odpowiedzi dotyczące
pycrypto
(niemożliwepip install pycrypto
w systemie Windows) lubpycryptodome
(odpowiedzi tutajfrom Crypto.Cipher import XOR
nie powiodły się, ponieważXOR
nie są obsługiwane przez topycrypto
rozwidlenie); i rozwiązania wykorzystujące... AES
również zawiodłyTypeError: Object type <class 'str'> cannot be passed to C code
). Bibliotekasimple-crypt
mapycrypto
również zależność, więc nie jest to opcja.źródło
password_encrypt()
.To działa, ale długość hasła powinna być dokładnie
8
. Jest to proste i wymaga pyDes .WYNIK:
źródło
Inna implementacja kodu @qneill, która zawiera sumę kontrolną CRC oryginalnej wiadomości, zgłasza wyjątek, jeśli sprawdzenie nie powiedzie się:
źródło
Możesz użyć AES do zaszyfrowania ciągu za pomocą hasła. Jednak będziesz chciał wybrać wystarczająco silne hasło, aby ludzie nie mogli łatwo odgadnąć, co to jest (przepraszam, nie mogę na to poradzić. Jestem niedoszłym słabym zabezpieczeniem).
AES jest silny i ma dobry rozmiar klucza, ale jest również łatwy w użyciu z PyCrypto.
źródło
Biblioteki zewnętrzne zapewniają algorytmy szyfrowania tajnego klucza.
Na przykład
Cypher
moduł w PyCrypto oferuje wybór wielu algorytmów szyfrowania:Crypto.Cipher.AES
Crypto.Cipher.ARC2
Crypto.Cipher.ARC4
Crypto.Cipher.Blowfish
Crypto.Cipher.CAST
Crypto.Cipher.DES
Crypto.Cipher.DES3
Crypto.Cipher.IDEA
Crypto.Cipher.RC5
Crypto.Cipher.XOR
MeTooCrypto jest
Python
opakowaniem dla OpenSSL i zapewnia (między innymi) w pełni funkcjonalną bibliotekę kryptograficzną ogólnego przeznaczenia. Zawarte są symetryczne szyfry (takie jak AES).źródło
jeśli chcesz mieć bezpieczne szyfrowanie:
w przypadku Pythona 2 powinieneś użyć keyczar http://www.keyczar.org/
dla pythona 3, dopóki keyczar nie będzie dostępny, napisałem simple-crypt http://pypi.python.org/pypi/simple-crypt
w obu przypadkach będą one wzmacniane kluczem, co czyni je bezpieczniejszymi niż większość innych odpowiedzi tutaj. a ponieważ są tak łatwe w użyciu, możesz chcieć ich używać nawet wtedy, gdy bezpieczeństwo nie jest krytyczne ...
źródło
Tak więc, ponieważ nic krytycznego dla misji nie jest kodowane , a chcesz tylko zaszyfrować w celu zaciemnienia .
Pozwólcie, że przedstawię szyfr Cezara
Szyfr Cezara lub przesunięcie Cezara jest jedną z najprostszych i najbardziej znanych technik szyfrowania. Jest to rodzaj szyfru podstawieniowego, w którym każda litera w tekście jawnym jest zastępowana literą o określoną liczbę pozycji w dół alfabetu. Na przykład, przy przesunięciu w lewo o 3, D zostanie zastąpione przez A, E stanie się B i tak dalej.
Przykładowy kod w celach informacyjnych:
Zalety: spełnia Twoje wymagania, jest prosty i zajmuje się kodowaniem.
Wada: może zostać złamany przez proste algorytmy brutalnej siły (jest bardzo mało prawdopodobne, aby ktokolwiek próbował przejść przez wszystkie dodatkowe wyniki).
źródło
Dodanie jeszcze jednego kodu z dekodowaniem i kodowaniem w celach informacyjnych
źródło