2017-02-05 4 views
-1

현재 파이썬 암호화 라이브러리 및 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

매우 안전하지 않은 사용법에 따라 암호화 암호가 사용되는 이유는 무엇입니까? – 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 2의 경우, 그리고 str이 사용되는 경우 Python 3의 경우도 가능).

즉, base64 문자열은 이고 바이트 문자열이며 isinstance(cipher_pass, bytes)은 true를 반환합니다. 하지만 base64 디코딩이 실행되지 않는다는 것을 의미합니다. 즉, 암호화 텍스트가 너무 커서 해독 중에 실패합니다.

텍스트 인터페이스가 필요한 경우 base64를 항상 디코딩하는 것이 가장 좋습니다.