2016-03-17 16 views
5

Chúng tôi có mã, hoạt động cho python 2.BCrypt. Làm thế nào để lưu trữ muối với python3?

@password.setter 
def password(self, value): 
    self.salt = bcrypt.gensalt() 
    self.passwd = bcrypt.hashpw(value.encode('utf-8'), self.salt) 

def check_password(self, value): 
    return bcrypt.hashpw(value.encode('utf-8'), self.salt.encode('utf-8')) == self.passwd 

Tuy nhiên, khi tôi cố gắng chuyển nó sang python3, chúng ta gặp vấn đề sau:

Lỗi xảy ra trên một mức độ tài xế cassandra:

cassandra.cqlengine.ValidationError: passwd <class 'bytes'> is not a string 

Ok. Đúc muối và mật khẩu vào chuỗi:

@password.setter 
def password(self, value): 
    salt = bcrypt.gensalt() 
    self.salt = str(salt) 
    self.passwd = str(bcrypt.hashpw(value.encode('utf-8'), salt)) 

Bây giờ muối được lưu. Nhưng trong check_password, chúng tôi nhận được ValueError: Invalid salt. Nếu chúng ta thay đổi kiểm tra mã mật khẩu để:

def check_password(self, value): 
    return bcrypt.hashpw(value, self.salt) == self.passwd 

Chúng tôi nhận được lỗi TypeError: Unicode-objects must be encoded before hashing.

Nơi để đào?

UPD giá trị muối trong mật khẩu và kiểm tra mật khẩu vẻ giống nhau, ví dụ:

b'$2b$12$cb03angGsu91KLj7xoh3Zu'                   
b'$2b$12$cb03angGsu91KLj7xoh3Zu' 

Trả lời

7

Cập nhật

Tính đến phiên bản 3.1.0 bcrypt cung cấp các chức năng thuận tiện

checkpw(password, hashed_password) 

để thực hiện kiểm tra mật khẩu đối với ha đổ mật khẩu. Điều này nên được sử dụng thay vì:

bcrypt.hashpw(passwd_to_check, hashed_passwd) == hashed_passwd 

được hiển thị bên dưới. Vẫn không cần phải lưu trữ băm riêng biệt.


Trước hết, bạn không cần lưu trữ muối vì nó là một phần của hàm băm được tạo bởi bcrypt.hashpw(). Bạn chỉ cần lưu trữ băm. Ví dụ.

>>> salt = bcrypt.gensalt() 
>>> salt 
b'$2b$12$ge7ZjwywBd5r5KG.tcznne' 
>>> passwd = b'[email protected]' 
>>> hashed_passwd = bcrypt.hashpw(passwd, salt) 
b'$2b$12$ge7ZjwywBd5r5KG.tcznnez8pEYcE1QvKshpqh3rrmwNTQIaDWWvO' 
>>> hashed_passwd.startswith(salt) 
True 

Vì vậy, bạn có thể thấy rằng muối được bao gồm trong băm.

Bạn cũng có thể sử dụng bcrypt.hashpw() để kiểm tra xem một mật khẩu phù hợp với một mật khẩu băm:

>>> passwd_to_check = b'[email protected]' 
>>> matched = bcrypt.hashpw(passwd_to_check, hashed_passwd) == hashed_passwd 
>>> matched 
True 
>>> bcrypt.hashpw(b'thewrongpassword', hashed_passwd) == hashed_passwd 
False 

Không cần phải lưu trữ các muối riêng biệt.


Vì vậy, bạn có thể viết các setter như thế này (Python 3):

@password.setter 
def password(self, passwd): 
    if isinstance(passwd, str): 
     passwd = bytes(passwd, 'utf-8') 
    self.passwd = str(bcrypt.hashpw(passwd, bcrypt.gensalt()), 'utf8') 

Và kiểm tra như thế này:

def check_password(self, passwd_to_check): 
    if isinstance(passwd_to_check, str): 
     passwd_to_check = bytes(passwd_to_check, 'utf-8') 
    passwd = bytes(self.passwd, 'utf8') 
    return bcrypt.hashpw(passwd_to_check, passwd) == passwd 
+1

tôi nhìn thấy. Rắc rối là, đường đó chuyển thành chuỗi như '" b '$ 2b $ 12 $ 8YtRw4YT27XpnpSBVZ9KeOlwKXdFhEMjN1Mqee6ySc7.71D1GHRKe' "'. Thay vì str, chúng ta nên sử dụng 'bcrypt.hashpw (passwd, bcrypt.gensalt()).giải mã ('utf-8') '. –

+0

Tại sao bạn không sử dụng 'bcrypt.checkpw()'? Dường như giá trị băm thực tế là biến và không nhất thiết phải so sánh (mặc dù chúng có thể giống nhau trên cùng một lần chạy). – Shule

+1

@Shule: cảm ơn vì đã chỉ ra điều này, 'checkpw()' đã được thêm vào trong [phiên bản 3.1.0] (https://github.com/pyca/bcrypt/#310). Trước đó, khoảng thời gian mà câu trả lời này đã được đăng, cách kiểm tra mật khẩu như được trình bày ở trên. Tôi đã cập nhật câu trả lời gốc để khuyên bạn nên sử dụng chức năng mới. Không có vấn đề gì với việc thay đổi băm, bởi vì muối được lưu trữ với băm. Nếu bạn tạo ra một muối khác thì bạn sẽ nhận được một băm khác nhau, nhưng đó là một vấn đề khác. – mhawke

Các vấn đề liên quan