【问题标题】:Fernet Invalid Token Error for Password Manager密码管理器的 Fernet 令牌无效错误
【发布时间】:2020-07-04 18:38:31
【问题描述】:

我目前正在尝试使用密码学模块在 Python 中制作一个自定义的小密码管理器。用主密码加密似乎没问题,但解密它会导致 2 个错误:

代码如下:

import os
import base64
import pickle
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

logins = {}
masterpass = bytes(input('Unlock login ring with master password: '), 'utf-8')

def newLogin(email, username, password):
    logins['{}:{}'.format(email, username)] = password

def loadLogins():
    salt = os.urandom(16)
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100000,
        backend=default_backend()
    )

    key = base64.urlsafe_b64encode(kdf.derive(masterpass))

    f = Fernet(key)

    file = open('keyring.keys', 'rb')

    token = f.decrypt(file.read())

    print(file.read())

    file.close()
    

def saveLogins():
    salt = os.urandom(16)
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100000,
        backend=default_backend()
    )

    key = base64.urlsafe_b64encode(kdf.derive(masterpass))

    f = Fernet(key)

    logs = ['{}'.format(x) for x in logins]
    pasw = ['{}'.format(logins[y]) for y in logins]

    keys = []

    for i in range(len(logins)):
        keys += logs[i] + ':' + pasw[i] + ';'

    print(''.join(keys))

    keyring = f.encrypt(bytes(''.join(keys), 'utf-8'))

    file = open('keyring.keys', 'wb')

    pickle.dump(keyring, file)

    file.close()

我的代码的工作方式是您最初必须给它一个主密码。然后它将该主密码存储为字节对象。接下来,您可以将登录名添加/更新到登录名字典。然后,使用 Fernet 密码配方 (Using passwords with Fernet (cryptography module)),我将主密码转换为 Fernet 密钥,用于加密和解密文件的登录信息。如上所述,加密工作正常,但解密总是会导致错误。我的解密功能有问题吗?或者我如何实现密码加密/解密?

谢谢。

【问题讨论】:

    标签: python python-3.x file encryption cryptography


    【解决方案1】:

    抱歉,犯了愚蠢的错误。解决方案是生成一个 os.urandom 盐,并将其用作推导密钥的文字(又称“幻数”)。另外,我只需要派生一次密钥,而不是在每个函数中。

    我还需要在要写入的文件上调用 pickle.load。这是一个可行的解决方案:

    import base64
    import pickle
    from cryptography.fernet import Fernet
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
    
    logins = {}
    masterpass = bytes(input('Unlock login ring with master password: '), 'utf-8')
    
    # Derive key from master password
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=b'\xaab\xc0\xe0+\xc8\xb29\xc5\xe9\xbb\xfb\xaa\xb6\xab\xa7',
        iterations=100000,
        backend=default_backend()
    )
    
    key = base64.urlsafe_b64encode(kdf.derive(masterpass))
    
    f = Fernet(key)
    
    
    # Add or update login information in
    # the logins dictionary.
    def setLogin(website, email, username, password):
        logins[website] = '{}:{}:{}'.format(email, username, password)
    
    
    # Load and decrypt the logins and
    # return them in string format.
    def loadLogins():
        file = open('keyring.keys', 'rb')
    
        token = f.decrypt( pickle.load(file) )
    
        file.close()
    
        return token.decode('utf-8')
    
    
    # Separate and load logins into the
    # logins dictionary.
    def parseLogins(strLogins):
        individual_logins = strLogins.split(';')
    
        for i in range(len(individual_logins)):
            if (individual_logins[i] != ''):
                website, email, username, password = individual_logins[i].split(':')
    
                setLogin(website, email, username, password)
        
        print(individual_logins)
    
    
    # Encrypt and save logins in a bytes file 
    # using the master password.
    def saveLogins():
        logs = ['{}'.format(x) for x in logins]
        pasw = ['{}'.format(logins[y]) for y in logins]
    
        keys = []
    
        for i in range(len(logins)):
            keys += logs[i] + ':' + pasw[i] + ';'
    
        print(''.join(keys))
    
        keyring = f.encrypt(bytes(''.join(keys), 'utf-8'))
    
        file = open('keyring.keys', 'wb')
    
        pickle.dump(keyring, file)
    
        print(keyring)
    
        file.close()
    
    
    # Display all login information.
    def showLogins():
        for i in logins:
            info = logins[i].split(':')
            
            website = i
            email = info[0]
            username = info[1]
            password = info[2]
            
            print(f'\nWebsite: {website}\nEmail: {email}\nUsername: {username}\nPassword: {password}\n')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 1970-01-01
      • 1970-01-01
      • 2019-04-11
      • 2018-09-30
      • 2012-12-10
      • 2020-05-09
      相关资源
      最近更新 更多