2016-07-05 60 views
1

所以我使用this SO answer的代碼創建一個雙向字母數字加密函數。Python unhexlify十六進制到alpha轉換失敗

基本上,功能是這樣的:

from Crypto import Random 
from Crypto.Cipher import AES 

from binascii import hexlify 
from binascii import unhexlify 

def encrypt_password(self, password): 
    key = current_app.config['VAULT_KEY'] 
    iv = Random.new().read(AES.block_size) 
    cipher = AES.new(key.strip("\'"), AES.MODE_CFB, iv) 
    self.password_encrypted = hexlify(iv + cipher.encrypt(password)) 

def decrypt_password(self): 
    key = current_app.config['VAULT_KEY'] 
    encrypted = unhexlify(self.password_encrypted) 
    cipher = AES.new(key.strip("\'"), AES.MODE_CFB, encrypted[:AES.block_size]) 
    return cipher.decrypt(encrypted)[AES.block_size:] 

這些功能進行交互瓦特/,節省的encrypt_password結果的數據庫對象;解密,使用decrypt_password。 (不言自明。)

我被陷在這條線:

encrypted = unhexlify(self.password_encrypted) 

不知何故,Python會告訴我,self.password_encrypted不是一個十六進制數字。我不知道b/c上發生了什麼,它以十六進制數字形式保存到對象中。

順便說一句,字符串表示形式是:'\x[decimal numbers]',我也覺得很奇怪。它不應該是十六進制數字嗎?

回溯如下:

Traceback (most recent call last): 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 2000, in __call__ 
    return self.wsgi_app(environ, start_response) 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1991, in wsgi_app 
    response = self.make_response(self.handle_exception(e)) 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1567, in handle_exception 
    reraise(exc_type, exc_value, tb) 
    File "/<>/venv/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise 
    raise value 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1988, in wsgi_app 
    response = self.full_dispatch_request() 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1641, in full_dispatch_request 
    rv = self.handle_user_exception(e) 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1544, in handle_user_exception 
    reraise(exc_type, exc_value, tb) 
    File "/<>/venv/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise 
    raise value 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1639, in full_dispatch_request 
    rv = self.dispatch_request() 
    File "/<>/venv/lib/python3.5/site-packages/flask/app.py", line 1625, in dispatch_request 
    return self.view_functions[rule.endpoint](**req.view_args) 
    File "/<>/app/public/views.py", line 64, in test_queue 
    return u.decrypt_password() 
    File "/<>/app/models.py", line 80, in decrypt_password 
    encrypted = unhexlify(self.password_encrypted) 
binascii.Error: Non-hexadecimal digit found 
+0

不加密密碼。使用隨機鹽在HMAC上迭代大約100毫秒的時間(鹽需要與散列一起保存)。使用諸如password_hash,PBKDF2,Bcrypt和類似函數的函數。關鍵是要讓攻擊者花費大量時間通過強力查找密碼。 請參閱OWASP(Open Web Application Security Project)[密碼存儲備忘單](https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet#Leverage_an_adaptive_one-way_function)。 – zaph

+0

請參閱Security Stackexchange上的[如何安全散列密碼,理論](http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846)。 – zaph

+0

@zaph我知道密碼的雙向字母數字加密架構的安全風險,我知道密碼應該是哈希值。但是,這是一個獨特的案例。該機器需要能夠輸入純文本密碼以實現自動化。如果您有設計方法,請告訴我。 – franklin

回答

1

好了,所以我做了一些修改,您發佈的文件...

from Crypto import Random 
from Crypto.Cipher import AES 

from binascii import hexlify, unhexlify 

import hashlib 
from sys import stdout as puts 

class AESCipher: 

     def __init__(self, key): 
      self.key = key 

     def encrypt_password(self, password): 
     iv = Random.new().read(AES.block_size) 
     cipher = AES.new(self.key, AES.MODE_CFB, iv) 
     self.password_encrypted = hexlify(iv + cipher.encrypt(password)) 
     return self.password_encrypted 

     def decrypt_password(self): 
      decrypted = unhexlify(self.password_encrypted) 
      cipher = AES.new(self.key, AES.MODE_CFB, decrypted[:AES.block_size]) 
      return cipher.decrypt(decrypted)[AES.block_size:] 


############################################################################# 
       """sample purposes only""" 

"""Here's an example, you don't have to use stdout or the block size for encyrption 
    I decided to use the regular base 16 block size and for 'puts' I came from a 
    ruby background""" 

retrive_password = AESCipher(hashlib.sha256("mylittlepony").digest()) 

puts.write(("\n"*3) + retrieve_password.encrypt_password("agenericpassword") + ("\n" *3)) 

puts.flush() 

puts.write(retrive_password.decrypt_password() + ("\n" *3)) 

puts.flush(() 

它可能有一些與你的環境的關鍵變量,確保它符合16,24或32字節的構造。爲AES初始化第一個參數。

至於 '\ X {0-9A-FA-F} {0-9A-FA-F}' 格式,以我的理解,是一個字符串格式的十六進制輸出

+0

謝謝我將編輯評論,我忘了把它放在字符串中 – akiespenc