读取Fernet密钥导致ValueError:Fernet密钥必须是32个URL安全的base64编码的字节 [英] Read Fernet Key Causes ValueError: Fernet key must be 32 url-safe base64-encoded bytes

查看:232
本文介绍了读取Fernet密钥导致ValueError:Fernet密钥必须是32个URL安全的base64编码的字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此功能中,我试图从文件中读取Fernet密钥,或者如果文件中不包含密钥,则创建一个.从cryptography.fernet中的

In this function I am trying to read a Fernet key from a file, or create one if the file doesn't contain a key.

from cryptography.fernet import Fernet
import csv


with open("Keys.txt","rU") as csvfile:
    reader=csv.reader(csvfile)
    KeyFound=0
    print(KeyFound)
    for row in reader:
        try:
            print(row[0])
        except IndexError:
            continue
        if len(row[0])>4:
            print("KEY FOUND")
            KeyFound=1
            print(KeyFound)
            Key=row[0]
            print(Key)
            print(KeyFound)
        else:
            pass
if KeyFound==0:
    Key = Fernet.generate_key()
    print(Key)
    print("Created Key")
    csvfile.close()
#Writing Key to textfile
with open("Keys.txt", "w+") as csvfile:
    headers = ['key']
    writer=csv.DictWriter(csvfile, fieldnames=headers)
    writer.writeheader()
    writer.writerow({'key': Key})
    csvfile.close()
print(Key)
Ecy = Fernet(Key)

我在读取文件时遇到困难.读取文件后,密钥的读取方式为:

I am having difficulty reading the file. When the file is read the key is read in as:

b'nNjpIl9Ax2LRtm-p6ryCRZ8lRsL0DtuY0f9JeAe2wG0='

但是我收到此错误:

ValueError: Fernet key must be 32 url-safe base64-encoded bytes.

在这一行:

Ecy = Fernet(Key)

任何帮助将不胜感激.

推荐答案

这里的问题是密钥是如何写入文件的.

The problem here is how the key is being written to the file.

Fernet.generate_key()返回一个 bytes 实例:

>>> key = Fernet.generate_key()
>>> key
b'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='

密钥正按原样写入文件中

The key is being written to the file as is:

>>> with open('keys.csv', 'w+') as f:
...     headers = ['key']
...     writer = csv.DictWriter(f, fieldnames=headers)
...     writer.writeheader()
...     writer.writerow({'key': key})
... 
49
>>> 

如果我们查看文件,则可以看到内容不是我们期望的-表示已将python字节串写入文件的 b :

If we look in the file, we can see the contents aren't what we expect - the b that indicates a python bytestring has been written to the file:

$  cat keys.csv 
key
b'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='

csv.writer 在尚未为字符串的任何值上调用 str .如果在 bytes 实例上调用 str ,则会得到字节实例的字符串化的 repr ,而不是 bytes 实例,这就是您想要的 * .

csv.writer calls str on any values that aren't already strings. If str is called on a bytes instance you get the stringified repr of the bytes instances rather than the decoded value of the bytes instance, which is what you want*.

>>> str(key)
"b'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='"  # <- note the extra quotes...
>>> key.decode('utf-8')
'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='

因此解决方案是在 csv.writer 之前调用 bytes 实例的 decode 方法收到.

So the solution is to call the bytes instance's decode method before csv.writer receives it.

>>> with open('keys.csv', 'w+') as f:
...     headers = ['key']
...     writer = csv.DictWriter(f, fieldnames=headers)
...     writer.writeheader()
...     writer.writerow({'key': key.decode('utf-8')})
... 
46
>>>

这为我们提供了所需的文件内容:

This gives us the file contents that we want:

$  cat keys.csv 
key
ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg=

其余代码按预期工作:

>>> with open('keys.csv') as f:
...     reader = csv.reader(f)
...     next(reader)      # <- skip the header row
...     for row in reader:
...         csv_key = row[0]
...         print(Fernet(csv_key))
... 
['key']                   # <- the headers are printed as a side effect of skipping
<cryptography.fernet.Fernet object at 0x7f3ad62fd4e0>

一个调试技巧.使用 print()调试代码时,有时最好打印对象的 repr ,而不是在对象上调用 str 的结果(这是 print()做).如果对象是字符串,则尤其如此.例如:

One debugging tip. When using print() to debug your code, it's sometimes better to print an object's repr, rather than the result of calling str on the object (which is what print() does). This is especially the case if the object is a string. For example:

>>> bad_key = str(key)
>>> print(bad_key)                                
b'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='      # <- Looks ok...
>>> print(repr(bad_key))
"b'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='"    # <- See the problem
>>> 
>>> good_str = 'foo'
>>> bad_str = 'foo '
>>> print(bad_str)
foo                             # <- looks like good_str
>>> print(repr(bad_str))
'foo '                          # <- see the trailing space 

* 如果您使用 -b 标志调用Python- python -b myscript.py -Python将发出 BytesWarning他是您第一次尝试在 bytes 实例上调用 str 时.如果使用 -bb 标志,则会引发异常.

* If you call Python with the -b flag - python -b myscript.py - Python will emit a BytesWarning he first time you try to call str on a bytes instance. If the -bb flag is used, an exception will be raised.

这篇关于读取Fernet密钥导致ValueError:Fernet密钥必须是32个URL安全的base64编码的字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆