【问题标题】:Using supplied key to encrypt text python使用提供的密钥加密文本 python
【发布时间】:2020-08-15 08:00:57
【问题描述】:

如何使用自己的密钥进行加密?

我已经在网上搜索过了。 如何使用自己的密钥进行加密? 我更喜欢在 python 中 密码学。它不断弹出错误Fernet key must be 32 url-safe base64-encoded bytesTypeError: a bytes-like object is required, not 'str'。我正在尝试创建一个私有变量函数。我是python新手。

这是我未完成的代码。感谢您的帮助。

from cryptography.fernet import Fernet
import inspect
import hashlib
import base64     #Fernet key must be 32 url-safe base64-encoded bytes

def encode(key, string):
    encoded_chars = []
    for i in xrange(len(string)):
        key_c = key[i % len(key)]
        encoded_c = chr(ord(string[i]) + ord(key_c) % 256)
        encoded_chars.append(encoded_c)
    encoded_string = "".join(encoded_chars)
    return base64.urlsafe_b64encode(encoded_string)

class private:
    class sec_storage:
        data = dict()
        hashed_data = dict()
    class var:
        def create(var,value):
            # creates key based on caller
            key = hashlib.sha224(str(inspect.stack()).encode()).hexdigest()
            cipher_suite = Fernet(base64.b64encode(key))   #Fernet key must be 32 url-safe base64-encoded bytes
            # encrypts using key
            encoded_text = cipher_suite.encrypt(value)
            # prepares storage
            hashed_var = hashlib.sha224("plus".join(list(var.encode(),key[:12])).hexdigest())
            hashed_value = hashlib.sha224(value.encode()).hexdigest()[12:30]
            private.sec_storage.data[hashed_var] = encoded_text
            private.sec_storage.hashed_data[hashed_var] = hashed_value

        def read(var):
            # creates key based on caller
            key = hashlib.sha224(str(inspect.stack()).encode()).hexdigest()
            cipher_suite = Fernet(base64.b64encode(key))     #Fernet key must be 32 url-safe base64-encoded bytes
            # retrieve var
            hashed_varname = hashlib.sha224("plus".join(list(var.encode(),key[:12])).hexdigest())
            try:
                hashed_var = private.sec_storage.data[hashed_varname]
            except NameError:
                raise NameError("Requested variable not found")
            # decrypts using key
            decoded_text = cipher_suite.decrypt(hashed_var)
            hashed_value = hashlib.sha224(decoded_text.encode()).hexdigest()[12:30]
            # checks if password is correct
            if private.sec_storage.hashed_data[hashed_varname] != hashed_value:
                raise ValueError("Value not as requested")
            return decoded_text
private.var.create("myvar","Hello World!")
print(private.var.read("myvar"))
print(sec_storage.data)

如你所见cipher_suite = Fernet(base64.b64encode(key)) #Fernet key must be 32 url-safe base64-encoded

我该如何解决?

【问题讨论】:

  • Fernet 密钥必须是 32 个 url 安全的 base64 编码字节:SHA 224 创建一个 28 字节的散列,由于 hexdigest() 而返回为十六进制字符串,因此为 56字节大小,而不是所需的 32 字节。 需要一个类似字节的对象,而不是'str'b64encode() 需要一个类似字节的对象而不是字符串。建议: (1) 使用os.urandom() 可以很容易地创建一个随机字节序列,它返回一个类似字节的对象。 (2) 对于 url 安全字符串,您必须使用 urlsafe_b64encode()。备注:如果哈希应该作为字节类对象返回,请使用digest() 而不是hexdigest()
  • 如果您想保留您的密钥生成方法,必须对十六进制字符串进行编码,并且只能使用 32 个字节的结果,例如key = hashlib.sha224(...).hexdigest().encode('utf8')[:32].
  • 这些东西结合起来可以得到一个很好的答案 Topaco。我很乐意支持诸如此类的答案,即使它们不包含(完整的)代码修复。
  • 调用hexdigest 来生成足够长的密钥会使字符串的长度加倍,但会大大降低每字节的熵。现在只有 2**4 (16) 个值,而不是 2**8 (256) 个值。由于 Fernet 使用前 128 位作为 AES 密钥,第二个 128 作为 HMAC 密钥,因此您将有效密钥空间从 2**128 减少到 2**64,这非常非常糟糕。再加上它是当前堆栈的哈希值,生成的密钥将非常危险。

标签: python encryption fernet


【解决方案1】:

这里的主要问题是 Fernet 需要一个 url 安全的 base64 编码字符串,该字符串解码为 32 个字节。这种结构的安全性依赖于这 32 个字节包含足够的熵,使得攻击者无法猜测它。

在您的示例中,您使用的是堆栈跟踪的 SHA224 哈希。有几个问题在起作用:

  • 224 位/每字节 8 位 = 28 字节,这不是足够长的输出。
  • 散列堆栈跟踪不是派生密钥的安全方法。
  • 当它应该使用 urlsafe_b64encode 时,您已经通过 vanilla base64 进行编码。

一般来说,最好使用Fernet.generate_key() 生成您的 Fernet 密钥,但这需要您将密钥存储在某个地方以备后用。如果您想从密码之类的内容生成密钥,文档中有一个示例 (https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多