2009-06-19 9 views
26

Tworzę program w języku Python, który będzie dystrybuowany do użytkowników Windows za pośrednictwem instalatora.Jak zrobić PGP w Pythonie (generowanie kluczy, szyfrowanie/odszyfrowywanie)

Program musi być w stanie pobrać plik codziennie szyfrowany przy użyciu klucza publicznego użytkownika, a następnie odszyfrować go.

Muszę więc znaleźć bibliotekę Pythona, która umożliwi generowanie publicznych i prywatnych kluczy PGP, a także odszyfrować pliki zaszyfrowane za pomocą klucza publicznego.

Czy to coś, co zrobi pyCrypto (dokumentacja jest mglista)? Czy istnieją inne czyste biblioteki Pythona? Co powiesz na samodzielne narzędzie wiersza poleceń w dowolnym języku?

Wszystko, co widziałem do tej pory, to GNUPG, ale zainstalowanie go w systemie Windows powoduje wyprowadzanie plików do rejestru i umieszczanie plików DLL wszędzie, a następnie muszę się martwić, czy użytkownik już je zainstalował, jak wykonać kopię zapasową istniejących kluczy itp. Wolałbym mieć bibliotekę Pythona lub narzędzie wiersza poleceń i samodzielnie zarządzać kluczami.

Aktualizacja: pyME może działać, ale nie jest kompatybilny z Pythonem 2.4, którego muszę użyć.

Odpowiedz

24

Nie potrzebujesz PyCrypto lub PyMe, mimo że te pakiety mogą być - będziesz miał różnego rodzaju problemy z budowaniem pod Windows. Zamiast tego, dlaczego nie ominąć dziur w króliczku i zrobić to, co zrobiłem? Użyj gnupg 1.4.9. Nie musisz wykonywać pełnej instalacji na komputerach użytkowników końcowych - wystarczy gpg.exe i iconv.dll z dystrybucji są wystarczające, a wystarczy mieć je gdzieś w ścieżce lub uzyskać dostęp z kodu Pythona przy użyciu pełnej nazwy ścieżki. Żadne zmiany w rejestrze nie są potrzebne, a wszystko (pliki wykonywalne i pliki danych) może być ograniczone do jednego folderu, jeśli chcesz.

Istnieje moduł GPG.py, który został pierwotnie napisany przez Andrew Kuchling, ulepszony przez Richarda Jonesa i ulepszony przez Steve Traugotta. Jest dostępny pod numerem here, ale nie jest odpowiedni dla systemu Windows, ponieważ korzysta z niego os.fork(). Chociaż pierwotnie część PyCrypto, jest całkowicie niezależna od innych części PyCrypto i potrzebuje tylko gpg.exe/iconv.dll, aby pracować.

Mam wersję (gnupg.py) pochodzącą z Traugott's GPG.py, która korzysta z modułu subprocess. To działa dobrze pod Windows, przynajmniej dla moich celów - używam go wykonać następujące czynności:

  • Zarządzanie kluczami - generacji, lista, eksport itp
  • klucze Import z zewnętrznego źródła (np otrzymał klucze publiczne od spółki partnerskiej)
  • szyfrowania i deszyfrowania danych
  • podpisania i weryfikacji podpisów

moduł mam nie jest idealne, aby pokazać w tej chwili, ponieważ zawiera kilka innych rzeczy, które nie powinny być ther e - co oznacza, że ​​nie mogę tego zwolnić w tej chwili.W pewnym momencie, być może w ciągu najbliższych kilku tygodni, mam nadzieję, że będę w stanie go posprzątać, dodać więcej testów jednostkowych (na przykład nie mam żadnych testów jednostkowych do podpisu/weryfikacji) i zwolnić go (albo oryginalna licencja PyCrypto lub podobna licencja handlowa). Jeśli nie możesz się doczekać, idź z modułem Traugotta i zmodyfikuj go samemu - praca z modułem subprocess nie była zbyt wielka.

To podejście było znacznie mniej bolesne niż pozostałe (na przykład SWIG opartych roztwory lub roztwory, które wymagają budynek z MinGW/MSYS), które uważane i eksperymentowali z. Użyłem tego samego (gpg.exe/iconv.dll) podejścia z systemami napisanymi w innych językach, np. C#, z równie bezbolesnymi wynikami.

P.S. Działa z Pythonem 2.4, a także z Pythonem w wersji 2.5 i nowszych. Nie testowałem z innymi wersjami, chociaż nie przewiduję żadnych problemów.

+0

Dzięki, że brzmi idealnie. Nie miałem pojęcia, że ​​mogę wyciągnąć exe z gpg. Gdzie będzie umieścić brelok? Czy ta metoda spowoduje jakiekolwiek problemy, jeśli użytkownik ma już zainstalowany gpg? Czy jest szansa, że ​​zobaczę, jak twój kod generuje klucze i importuje klucze? – Greg

+0

Pamiętaj również, aby zaktualizować nas tutaj, gdy zwolnisz swój ostatni kod. – Greg

+0

Po wywołaniu gpg, określ ścieżkę, w której chcesz umieścić breloczki za pomocą argumentu --homedir. (Jest to już zrobione dla ciebie przy użyciu modułu Traugotta - istnieje klasa GPG, której konstruktor przyjmuje parametr gnupghome, który możesz ustawić w tym katalogu.) Pubring.gpg, secring.gpg i trustdb.gpg są tworzone w folderze określonym przez - -homedir. Nie wierzę, że spowoduje to problem, jeśli użytkownik ma już zainstalowaną gpg - argument --homedir powinien zastąpić dowolne wartości w rejestrze. –

6

PyCrypto obsługuje PGP - choć należy go przetestować, aby upewnić się, że działa zgodnie ze specyfikacją.

Chociaż dokumentacja jest trudne do zdobycia, jeśli spojrzeć przez Util/test.py (skrypt testowy moduł), można znaleźć prymitywny przykład wsparcie PGP:

if verbose: print ' PGP mode:', 
obj1=ciph.new(password, ciph.MODE_PGP, IV) 
obj2=ciph.new(password, ciph.MODE_PGP, IV) 
start=time.time() 
ciphertext=obj1.encrypt(str) 
plaintext=obj2.decrypt(ciphertext) 
end=time.time() 
if (plaintext!=str): 
    die('Error in resulting plaintext from PGP mode') 
print_timing(256, end-start, verbose) 
del obj1, obj2 

Futhermore, PublicKey/pubkey.py przewiduje następujące odpowiednich metod:

def encrypt(self, plaintext, K) 
def decrypt(self, ciphertext): 
def sign(self, M, K): 
def verify (self, M, signature): 
def can_sign (self): 
    """can_sign() : bool 
    Return a Boolean value recording whether this algorithm can 
    generate signatures. (This does not imply that this 
    particular key object has the private information required to 
    to generate a signature.) 
    """ 
    return 1 
+2

Nie widzę sposobu na wygenerowanie kluczy lub zaakceptowanie klucza publicznego innej strony do szyfrowania danych. Jakieś pomysły? – Greg

+3

Nie, MODE_PGP w PyCrypto jest starszym, eksperymentalnym kodem, który prawdopodobnie nigdy nie działał poprawnie. (Zobacz https://bugs.launchpad.net/pycrypto/+bug/996814). Nie używaj go. Wkrótce usuniemy go z PyCrypto. – dlitz

+1

Co więc sugerujesz, @dlitz? – raylu

2

PyMe rości pełną kompatybilność z Python 2.4, cytuję:

Najnowsza wersja PyMe (od tego pisania ) to v0.8.0. Jego binarny dystrybucja Debiana został skompilowany z SWIG v1.3.33 i GCC v4.2.3 dla gpgme v1.1.6 i Python v2.3.5, v2.4.4 i v2.5.2 (przewidzianego w „” niestabilnej dystrybucji u czas). Jego binarna dystrybucja dla Windows został skompilowany z SWIG v1.3.29 i MinGW v4.1 dla gpgme v1.1.6 i Python v2.5.2 (chociaż sama binarny dostać zainstalowany i działa poprawnie w v2.4.2 jak dobrze) .

Nie jestem pewien, dlaczego mówisz "to nie wydaje się być zgodne z Pythonem 2.4, którego muszę użyć" - szczegóły proszę?

I tak, istnieje jako opakowanie semi-Pythonic (SWIGd) na GPGME - jest to popularny sposób na rozbudowę rozszerzeń Pythona, gdy masz bibliotekę C, która w zasadzie wykonuje to zadanie.

PyPgp ma znacznie prostsze podejście - dlatego jest to pojedynczy, prosty skrypt w języku Python: w zasadzie nie robi nic więcej, jak tylko "wypakować" do poleceń PGP wiersza poleceń. Na przykład, odszyfrowanie tylko:

def decrypt(data): 
    "Decrypt a string - if you have the right key." 
    pw,pr = os.popen2('pgpv -f') 
    pw.write(data) 
    pw.close() 
    ptext = pr.read() 
    return ptext 

tj, zapisz zaszyfrowany tekst cyphertext do standardowego wejścia pgpv -f, odczytaj standardowe wyjście pgpv jako odszyfrowany tekst jawny.

PyPgp to także bardzo stary projekt, choć jego prostota oznacza, że ​​praca z nowoczesnym Pythonem (np. Podproces zamiast teraz przestarzałego os.popen2) nie byłaby trudna. Ale nadal potrzebujesz zainstalować PGP, a PyPgp niczego nie zrobi ;-).

+0

PyMe to był ten problem: http://stackoverflow.com/questions/1030297/how-to-make-a-pyme-python-library-run-in-python-2-4-on-windows – Greg

+0

Tak, roszczenie cytowany przeze mnie (w szczególności o Windows) jest nieuzasadniony (tylko w Windows, rozszerzenia muszą być kompilowane dla konkretnych wersji Pythona, więc jeden skompilowany dla wersji 2.5 nie będzie działał dla wersji 2.4). Wszystko czego potrzebujesz to rekompilacja (która wymaga MSVC 6.0). –

3

M2Crypto ma moduł PGP, ale nigdy nie próbowałem go używać. Jeśli spróbujesz i działa, proszę daj mi znać (jestem aktualnym opiekunem M2Crypto). Niektóre linki:

Aktualizacja: Moduł PGP nie dostarcza sposobów generowania kluczy, ale przypuszczalnie mogłyby one być tworzone przy niższym poziomie RSA , DSA itp. Modułów. Nie znam wnętrza PGP, więc musisz wykopać szczegóły. Ponadto, jeśli wiesz, jak je wygenerować za pomocą poleceń wiersza poleceń openssl, powinno być dość łatwo przekonwertować je na wywołania M2Crypto.

+0

Hmm, wyglądało to obiecująco, ale nie widzę sposobu generowania kluczy. – Greg

+0

Możliwe, że będziesz w stanie wygenerować klucze z niższym poziomem modułów RSA, DSA itp. –

2

Jak już zauważyliśmy, PyMe jest rozwiązaniem kanonicznym, ponieważ jest oparte na GpgME, który jest częścią ekosystemu GnuPG.

Dla Windows, zdecydowanie zaleca się stosowanie Gpg4win jako dystrybucji GnuPG, z dwóch powodów:

Jest on oparty na GnuPG 2, która, między innymi, obejmuje gpg2.exe, które mogą (wreszcie dodam:) uruchom gpg-agent.exe na żądanie (gpg v1.x nie może).

Po drugie, jest to jedyna oficjalna wersja systemu Windows stworzona przez programistów GnuPG. Na przykład. jest całkowicie przekompilowany od Linuksa do Windowsa, więc nie użyto ani joty niewolnego oprogramowania do jego przygotowania (dość ważne dla pakietu bezpieczeństwa :).

1

Po wielu kopaniu znalazłem pakiet, który zadziałał dla mnie. Chociaż mówi się, że obsługuje generowanie kluczy, nie przetestowałem go. Jednak udało mi się odszyfrować wiadomość, która została zaszyfrowana przy użyciu klucza publicznego GPG. Zaletą tego pakietu jest to, że nie wymaga pliku wykonywalnego GPG na komputerze i jest opartą na Pythonie implementacją OpenPGP (a nie otoką dookoła pliku wykonywalnego). Stworzyłem klucze prywatne i publiczne za pomocą GPG4win i kleopatra dla Windows Zobacz mój kod poniżej.

import pgpy 
emsg = pgpy.PGPMessage.from_file(<path to the file from the client that was encrypted using your public key>) 
key,_ = pgpy.PGPKey.from_file(<path to your private key>) 
with key.unlock(<your private key passpharase>): 
    print (key.decrypt(emsg).message) 

Mimo że pytanie jest bardzo stare. Mam nadzieję, że pomoże to przyszłym użytkownikom.

+0

Dziękuję za informacje. Czy to rzeczywiście może wykonać szyfrowanie przy użyciu klucza publicznego? Również link do pakietu może być pomocny. – lazyList

+0

@lazyList zobacz tutaj: https://github.com/SecurityInnovation/PGPy –

+0

Dziękujemy @Roee Anuar. Używałem go już do budowy programu ochrony hasłem opartego na PGP. Doceń pomoc. – lazyList