2017-02-05 8 views
-1

Ich versuche derzeit, Kennwörter mithilfe der Python-Kryptographie-Bibliothek und RSA zu verschlüsseln und zu entschlüsseln. Die Schlüsselgenerierung funktioniert gut, die Verschlüsselung funktioniert, aber wenn es um das Passwort zu Entschlüsseln kommt, ich bin mit dieser Zurückverfolgungsfehlermeldung konfrontiert:RSA "Länge muss Schlüsselgröße entsprechen" Fehler

raise ValueError("Ciphertext length must be equal to key size.") 

Meine Verschlüsselung und Entschlüsselung Code sieht wie folgt aus:

class AppCryptography(): 

    def generate_rsa_keypair(self, bits=4096): 
     return rsa.generate_private_key(
      public_exponent=65537, 
      key_size=bits, 
      backend=default_backend() 
     ) 

    def load_private_key(self, pem_file_path): 

     with open(pem_file_path, "rb") as key_file: 
      private_key = serialization.load_pem_private_key(
       key_file.read(), 
       password=None, 
       backend=default_backend() 
      ) 

     return private_key 

    def load_public_key(self, pem_file_path): 

     with open(pem_file_path, "rb") as key_file: 
      public_key = serialization.load_pem_public_key(
       key_file.read(), 
       backend=default_backend() 
      ) 

     return public_key 

    def encrypt_password(self, public_key, password): 
     password = bytes(password) if not isinstance(password, bytes) else password 
     public_key = public_key if isinstance(public_key, RSAPublicKey) else self.load_pem_public_key(
      public_key_pem_export=public_key 
     ) 

     cipher_pass = public_key.encrypt(
      password, 
      padding.OAEP(
       mgf=padding.MGF1(algorithm=hashes.SHA1()), 
       algorithm=hashes.SHA1(), 
       label=None 
      ) 
     ) 

     return str(base64.b64encode(cipher_pass)) 

    def decrypt(self, private_key, cipher_pass): 
     cipher_pass = base64.b64decode(cipher_pass) if not isinstance(cipher_pass, bytes) else cipher_pass 
     private_key = private_key if isinstance(private_key, RSAPrivateKey) else self.load_pem_private_key(
      private_key_pem_export=private_key 
     ) 

     plain_text_pass = private_key.decrypt(
      cipher_pass, 
      padding.OAEP(
       mgf=padding.MGF1(algorithm=hashes.SHA1()), 
       algorithm=hashes.SHA1(), 
       label=None 
      ) 
     ) 
     return str(plain_text_pass) 

Und der Fehler passiert, wenn ich dieses Skript ausführen:

crypter = AppCryptography() 

backend_public_key = crypter.load_public_key(dir_path + "/util/keys/backend_public_key.pem") 
frontend_private_key = crypter.load_private_key(dir_path + "/util/keys/frontend_private_key.pem") 

encrypted_password = crypter.encrypt_password(backend_public_key, password) 

signature = crypter.sign_data(frontend_private_key, password) 

backend_private_key = crypter.load_private_key(dir_path + "/util/keys/backend_private_key.pem") 
cleartext = crypter.decrypt(backend_private_key, encrypted_password) 

Meine stacktrace zeigen, dass der Fehler von der Entschlüsselungsfunktion kommt, aber ich bin nicht in der Lage zu sehen, wo der Fehler in der functio ist n Definition.

File "/Users/Me/anaconda/envs/flask_dream/lib/python2.7/site-packages/sqlalchemy/orm/state.py", line 411, in _initialize_instance 
    return manager.original_init(*mixed[1:], **kwargs) 
File "/Users/Me/anaconda/envs/flask_dream/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 650, in _declarative_constructor 
    setattr(self, k, kwargs[k]) 
File "/Users/Me/Desktop/Projects/Flask-Dream/project_app/models.py", line 114, in password 
    cleartext = crypter.decrypt(backend_private_key, encrypted_password) 
File "/Users/Me/Desktop/Projects/Flask-Dream/project_app/util/crypto.py", line 121, in decrypt 
    label=None 
File "/Users/Me/anaconda/envs/flask_dream/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 397, in decrypt 
    raise ValueError("Ciphertext length must be equal to key size.") 
+0

Warum sind Sie Verschlüsselungspasswörter, da abhängig von der Verwendung, die eine sehr unsichere Praxis sein kann. – zaph

+0

Es ist nicht mein Service-Passwort, das ich verschlüssle (ich verwende einen Hash + Salz dafür) Dies ist ein weiterer Anwendungsfall, in dem ich die Daten von meinen Benutzern in ihrem persönlichen Konto verschlüsselt verschlüsseln möchte. Ich habe eine sehr spezifische Architektur. – mandok

+0

Hinweis: Die Verwendung einer Hash-Funktion ist nicht ausreichend und nur das Hinzufügen eines Salzes trägt wenig zur Verbesserung der Sicherheit bei. Stattdessen iterieren Sie über eine HMAC mit einer zufälligen Salz für etwa 100ms Dauer und speichern Sie das Salz mit dem Hash. Verwenden Sie Funktionen wie 'PBKDF2' (aka' Rfc2898DeriveBytes'), 'password_hash' /' password_verify', 'BCrypt' und ähnliche Funktionen. Es geht darum, den Angreifer dazu zu bringen, viel Zeit mit der Suche nach Passwörtern zu verbringen. Schützen Sie Ihre Benutzer ist wichtig, bitte verwenden Sie sichere Passwort-Methoden. – zaph

Antwort

2

Was das Problem in Ihrem Code zu sein scheint, ist die folgende Zeile ein:

cipher_pass = base64.b64decode(cipher_pass) if not isinstance(cipher_pass, bytes) else cipher_pass 

jetzt - wenn ich Python richtig verstehen - Strings in Bytes mit einem bestimmten Codierung gespeichert werden (dies ist auf jeden Fall des Fall für Python 2, und kann auch für Python 3, wenn str verwendet wird).

Dies bedeutet, dass die Base64-Zeichenfolge ist auch eine Byte-Zeichenfolge, und isinstance(cipher_pass, bytes) gibt True zurück. Das bedeutet jedoch, dass die base64-Decodierung nicht ausgelöst wird, was wiederum bedeutet, dass Ihr Chiffretext zu groß ist und während der Entschlüsselung fehlschlägt.

Die Decodierung von base64 ist immer das Beste, wenn Sie eine Textschnittstelle benötigen.

Verwandte Themen