2017-02-05 298 views
-1

我正在嘗試使用Python密碼庫和RSA加密和解密密碼。密鑰生成正常工作,加密工作,但是當它涉及到解密的密碼,我碰到這樣的追蹤錯誤消息:RSA「長度必須等於密鑰大小」錯誤

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

我的加密和解密代碼如下所示:

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) 

當我運行此腳本錯誤發生:

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) 

我的堆棧跟蹤表明,錯誤來自解密函數,但我無法看到的錯誤是在函數的n的定義。

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

你爲什麼加密密碼,因爲取決於un使用,這可能是一個非常不安全的做法。 – zaph

+0

這不是我的服務密碼,我正在加密(我正在使用哈希+鹽)這是另一個用例,我想對我的用戶在其個人帳戶中輸入的數據進行加密。我有一個非常具體的架構。 – mandok

+0

注意:僅使用哈希函數是不夠的,僅僅添加鹽對提高安全性沒有多大作用。相反,用隨機鹽迭代HMAC約100ms持續時間,然後用散列表保存鹽。使用諸如「PBKDF2」(又名'Rfc2898DeriveBytes'),'password_hash' /'password_verify','Bcrypt'和類似函數的函數。關鍵是要讓攻擊者花費大量時間通過強力查找密碼。保護您的用戶非常重要,請使用安全的密碼方法。 – zaph

回答

2

什麼似乎是在你的代碼的問題是以下行:

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

現在 - 如果我理解的Python正確的 - 字符串存儲在使用特定編碼的字節(這肯定的是Python 2的情況下,當使用str時,可能也適用於Python 3)。

這意味着base64字符串是也是的一個字節字符串,並且isinstance(cipher_pass, bytes)返回true。但這意味着base64解碼不會被觸發,這意味着您的密文太大,並且在解密過程中會失敗。

如果您需要文本界面,總是要解碼base64是最好的選擇。

相關問題