Reputation:
How do I encrypt with my own key?
I've searched over the net to do this. How do I encrypt with my own key? In python I prefer
cryptography though. It keeps popping out the error Fernet key must be 32 url-safe base64-encoded bytes
and TypeError: a bytes-like object is required, not 'str'
. I am trying to create a private variable function. I'm python new-comer.
Here is my uncompleted code. Thank you for your help.
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)
As you can see cipher_suite = Fernet(base64.b64encode(key)) #Fernet key must be 32 url-safe base64-encoded
How do I fix it?
Upvotes: 0
Views: 2038
Reputation: 14089
The primary issue here is that Fernet expects a url-safe base64 encoded string that decodes to 32 bytes. The security of this construction relies on those 32 bytes containing sufficient entropy such that an attacker can't feasibly guess it.
In your example you're using the SHA224 hash of a stack trace. There are a few issues at play:
urlsafe_b64encode
.In general it's best to generate your Fernet key with Fernet.generate_key()
, but that requires you to store the key somewhere for later use. If you want to generate a key from something like a password the documentation has an example (https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet).
Upvotes: 2