2017-02-05 266 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是最好的选择。

相关问题