How to encode text to base64 in python - python

I am trying to encode a text string to base64.
i tried doing this :
name = "your name"
print('encoding %s in base64 yields = %s\n'%(name,name.encode('base64','strict')))
But this gives me the following error:
LookupError: 'base64' is not a text encoding; use codecs.encode() to handle arbitrary codecs
How do I go about doing this ? ( using Python 3.4)

Remember to import base64 and that b64encode takes bytes as an argument.
import base64
b = base64.b64encode(bytes('your string', 'utf-8')) # bytes
base64_str = b.decode('utf-8') # convert bytes to string

It turns out that this is important enough to get it's own module...
import base64
base64.b64encode(b'your name') # b'eW91ciBuYW1l'
base64.b64encode('your name'.encode('ascii')) # b'eW91ciBuYW1l'

For py3, base64 encode and decode string:
import base64
def b64e(s):
return base64.b64encode(s.encode()).decode()
def b64d(s):
return base64.b64decode(s).decode()

1) This works without imports in Python 2:
>>>
>>> 'Some text'.encode('base64')
'U29tZSB0ZXh0\n'
>>>
>>> 'U29tZSB0ZXh0\n'.decode('base64')
'Some text'
>>>
>>> 'U29tZSB0ZXh0'.decode('base64')
'Some text'
>>>
(although this doesn't work in Python3 )
2) In Python 3 you'd have to import base64 and do base64.b64decode('...')
- will work in Python 2 too.

To compatibility with both py2 and py3
import six
import base64
def b64encode(source):
if six.PY3:
source = source.encode('utf-8')
content = base64.b64encode(source).decode('utf-8')

It looks it's essential to call decode() function to make use of actual string data even after calling base64.b64decode over base64 encoded string. Because never forget it always return bytes literals.
import base64
conv_bytes = bytes('your string', 'utf-8')
print(conv_bytes) # b'your string'
encoded_str = base64.b64encode(conv_bytes)
print(encoded_str) # b'eW91ciBzdHJpbmc='
print(base64.b64decode(encoded_str)) # b'your string'
print(base64.b64decode(encoded_str).decode()) # your string

Whilst you can of course use the base64 module, you can also to use the codecs module (referred to in your error message) for binary encodings (meaning non-standard & non-text encodings).
For example:
import codecs
my_bytes = b"Hello World!"
codecs.encode(my_bytes, "base64")
codecs.encode(my_bytes, "hex")
codecs.encode(my_bytes, "zip")
codecs.encode(my_bytes, "bz2")
This can come in useful for large data as you can chain them to get compressed and json-serializable values:
my_large_bytes = my_bytes * 10000
codecs.decode(
codecs.encode(
codecs.encode(
my_large_bytes,
"zip"
),
"base64"),
"utf8"
)
Refs:
https://docs.python.org/3/library/codecs.html#binary-transforms
https://docs.python.org/3/library/codecs.html#standard-encodings
https://docs.python.org/3/library/codecs.html#text-encodings

Use the below code:
import base64
#Taking input through the terminal.
welcomeInput= raw_input("Enter 1 to convert String to Base64, 2 to convert Base64 to String: ")
if(int(welcomeInput)==1 or int(welcomeInput)==2):
#Code to Convert String to Base 64.
if int(welcomeInput)==1:
inputString= raw_input("Enter the String to be converted to Base64:")
base64Value = base64.b64encode(inputString.encode())
print "Base64 Value = " + base64Value
#Code to Convert Base 64 to String.
elif int(welcomeInput)==2:
inputString= raw_input("Enter the Base64 value to be converted to String:")
stringValue = base64.b64decode(inputString).decode('utf-8')
print "Base64 Value = " + stringValue
else:
print "Please enter a valid value."

Base64 encoding is a process of converting binary data to an ASCII
string format by converting that binary data into a 6-bit character
representation. The Base64 method of encoding is used when binary
data, such as images or video, is transmitted over systems that are
designed to transmit data in a plain-text (ASCII) format.
Follow this link for further details about understanding and working of base64 encoding.
For those who want to implement base64 encoding from scratch for the sake of understanding, here's the code that encodes the string to base64.
encoder.py
#!/usr/bin/env python3.10
class Base64Encoder:
#base64Encoding maps integer to the encoded text since its a list here the index act as the key
base64Encoding:list = None
#data must be type of str or bytes
def encode(data)->str:
#data = data.encode("UTF-8")
if not isinstance(data, str) and not isinstance(data, bytes):
raise AttributeError(f"Expected {type('')} or {type(b'')} but found {type(data)}")
if isinstance(data, str):
data = data.encode("ascii")
if Base64Encoder.base64Encoding == None:
#construction base64Encoding
Base64Encoder.base64Encoding = list()
#mapping A-Z
for key in range(0, 26):
Base64Encoder.base64Encoding.append(chr(key + 65))
#mapping a-z
for key in range(0, 26):
Base64Encoder.base64Encoding.append(chr(key + 97))
#mapping 0-9
for key in range(0, 10):
Base64Encoder.base64Encoding.append(chr(key + 48))
#mapping +
Base64Encoder.base64Encoding.append('+')
#mapping /
Base64Encoder.base64Encoding.append('/')
if len(data) == 0:
return ""
length=len(data)
bytes_to_append = -(length%3)+(3 if length%3 != 0 else 0)
#print(f"{bytes_to_append=}")
binary_list = []
for s in data:
ascii_value = s
binary = f"{ascii_value:08b}"
#binary = bin(ascii_value)[2:]
#print(s, binary, type(binary))
for bit in binary:
binary_list.append(bit)
length=len(binary_list)
bits_to_append = -(length%6) + (6 if length%6 != 0 else 0)
binary_list.extend([0]*bits_to_append)
#print(f"{binary_list=}")
base64 = []
value = 0
for index, bit in enumerate(reversed(binary_list)):
#print (f"{bit=}")
#converting block of 6 bits to integer value
value += ( 2**(index%6) if bit=='1' else 0)
#print(f"{value=}")
#print(bit, end = '')
if (index+1)%6 == 0:
base64.append(Base64Encoder.base64Encoding[value])
#print(' ', end="")
#resetting value
value = 0
pass
#print()
#padding if there is less bytes and returning the result
return ''.join(reversed(base64))+''.join(['=']*bytes_to_append)
testEncoder.py
#!/usr/bin/env python3.10
from encoder import Base64Encoder
if __name__ == "__main__":
print(Base64Encoder.encode("Hello"))
print(Base64Encoder.encode("1 2 10 13 -7"))
print(Base64Encoder.encode("A"))
with open("image.jpg", "rb") as file_data:
print(Base64Encoder.encode(file_data.read()))
Output:
$ ./testEncoder.py
SGVsbG8=
MSAyIDEwIDEzIC03
QQ==

Related

Python Json Loads Extra data: line 1 column 237

I' trying to add a variable that contain a json string like this
"dataId":"kldjscdlkAòLJD","devId":"315487259f5fc247","productKey":"wifvoilfrqeo6hvu","status":[{"code":"cur_current","4":"597","t":1668165392933,"value":597},{"code":"cur_power","t":1668165392933,"5":"1368","value":1368}]}
ro manage it as dictionary, but when i run
decryptedDataMap = json.loads(decryptedData)
where the variable decriptedData contain the json string (decrypted starting from and encrypted field into anothe json message), it fail with error:
a business exception has occurred,e:Extra data: line 1 column 237 (char 236)
The strange thing is that if I create a variable with the clear json string...like this
decryptedData_sample = '{"dataId":"AAXs6TJFw6K53Ex4Yp9C4wA","devId":"3074412170039f5fc247","productKey":"wifvoilfrqeo6hvu","status":[{"code":"cur_current","4":"438","t":1667861198521,"value":438},{"code":"cur_power","t":1667861198521,"5":"1010","value":1010}]}'
decryptedDataMap = json.loads(decryptedData_sample )
it work fine, but the variable populated my decripted function
# decrypt
def decrypt_by_aes(raw, key):
import base64
from Crypto.Cipher import AES
raw = base64.b64decode(raw)
key = str.encode(key[8:24])
cipher = AES.new(key, AES.MODE_ECB)
raw = cipher.decrypt(raw)
res_str = raw.decode('utf-8')
res_str = eval(repr(res_str).replace('\\r', ''))
res_str = eval(repr(res_str).replace('\\n', ''))
res_str = eval(repr(res_str).replace('\\f', ''))
return res_str
# handler message
def message_handler(payload):
print("payload:%s" % payload) #The payload that contain the encripted field
dataMap = json.loads(payload)
decryptContentDataStr = dataMap['data']
decryptedData = decrypt_by_aes(decryptContentDataStr, ACCESS_KEY)
print("\n DecrypredData: #" + decryptedData + "#") # No charatest at beginnig and at the end of the string
decryptedDataMap = json.loads(decryptedData) #Error
Can someone help me to understand where are my errors?
My expectation are that I ust be able to translate my json string to a dictionary.

Hashing salted string multiple times (custom password hashing)

I need to port old Python 2 code to Python 3 and I think I'm messing up with string encoding.
It's a custom password hasher.
I've tried different ways, unsuccessfully, obtaining only errors or wrong results.
This is the Python 2 code which needs to work with Python 3:
from hashlib import sha256
from base64 import b64encode
# 32 characters length string
SALT = "SQ7HqXQhrOIPEALbI7QhVjZ3DHJGhK18"
PLAIN_PASSWORD = "PLAIN_PASSWORD"
SALTED_PASSWORD = "%s{%s}" % (PLAIN_PASSWORD, SALT)
digest = ""
for i in range(100):
digest = sha256(digest + SALTED_PASSWORD).digest()
print b64encode(digest)
Output:
Yb0W9H+R7xQDStPfBjKMjFbe05jDPK6OXrdhVWCDJrU=
Operate on bytes from the beginning:
SALTED_PASSWORD = ("%s{%s}" % (PLAIN_PASSWORD, SALT)).encode()
digest = b""
for i in range(100):
digest = sha256(digest + SALTED_PASSWORD).digest()
print(b64encode(digest).decode())
# Yb0W9H+R7xQDStPfBjKMjFbe05jDPK6OXrdhVWCDJrU=
from hashlib import sha256
from base64 import b64encode
# 32 characters length string
SALT = b"SQ7HqXQhrOIPEALbI7QhVjZ3DHJGhK18"
PLAIN_PASSWORD = b"PLAIN_PASSWORD"
SALTED_PASSWORD = b"%s{%s}" % (PLAIN_PASSWORD, SALT)
digest = b""
for i in range(100):
digest = sha256(digest + SALTED_PASSWORD).digest()
print(b64encode(digest))

Convert base64-encoded string into hex int

I have a base64-encoded nonce as a 24-character string:
nonce = "azRzAi5rm1ry/l0drnz1vw=="
And I want a 16-byte int:
0x6b3473022e6b9b5af2fe5d1dae7cf5bf
My best attempt:
from base64 import b64decode
b64decode(nonce)
>> b'k4s\x02.k\x9bZ\xf2\xfe]\x1d\xae|\xf5\xbf'
How can I get an integer from the base64 string?
To get an integer from the string, you can do:
Code:
# Python 3
decoded = int.from_bytes(b64decode(nonce), 'big')
# Python 2
decoded = int(b64decode(nonce).encode('hex'), 16)
Test Code:
nonce = "azRzAi5rm1ry/l0drnz1vw=="
nonce_hex = 0x6b3473022e6b9b5af2fe5d1dae7cf5bf
from base64 import b64decode
decoded = int.from_bytes(b64decode(nonce), 'big')
# PY 2
# decoded = int(b64decode(nonce).encode('hex'), 16)
assert decoded == nonce_hex
print(hex(decoded))
Results:
0x6b3473022e6b9b5af2fe5d1dae7cf5bf
You can convert like this:
>>> import codecs
>>> decoded = base64.b64decode(nonce)
>>> b_string = codecs.encode(decoded, 'hex')
>>> b_string
b'6b3473022e6b9b5af2fe5d1dae7cf5bf'

Using AES Encrypt get raise TypeError("Only byte strings can be passed to C code")

i try to encrypt the text with python and then i execute my code i get an error :
import base64
import boto3
from Crypto.Cipher import AES
PAD = lambda s: s + (32 - len(s) % 32) * ' '
def get_arn(aws_data):
return 'arn:aws:kms:{region}:{account_number}:key/{key_id}'.format(**aws_data)
def encrypt_data(aws_data, plaintext_message):
kms_client = boto3.client(
'kms',
region_name=aws_data['region'])
data_key = kms_client.generate_data_key(
KeyId=aws_data['key_id'],
KeySpec='AES_256')
cipher_text_blob = data_key.get('CiphertextBlob')
plaintext_key = data_key.get('Plaintext')
# Note, does not use IV or specify mode... for demo purposes only.
cypher = AES.new(plaintext_key, AES.MODE_ECB)
encrypted_data = base64.b64encode(cypher.encrypt(PAD(plaintext_message)))
# Need to preserve both of these data elements
return encrypted_data, cipher_text_blob
def main():
# Add your account number / region / KMS Key ID here.
aws_data = {
'region': 'eu-west-1',
'account_number': '701177775058',
'key_id': 'd67e033d-83ac-4b5e-93d4-aa6cdc3e292e',
}
# And your super secret message to envelope encrypt...
plaintext = PAD('Hello, World!')
# Store encrypted_data & cipher_text_blob in your persistent storage. You will need them both later.
encrypted_data, cipher_text_blob = encrypt_data(aws_data, plaintext)
print(encrypted_data)
if __name__ == '__main__':
main()
i Get : raise TypeError("Only byte strings can be passed to C code")
TypeError: Only byte strings can be passed to C code
Maybe whom know why? and how can i fix it ? please suggest!
Writing #Jeronimo's comment as an answer here, I was stuck with this same problem too and this helped.
Append a .encode("utf-8") to whatever you are passing to cypher.encrypt() function.
cypher.encrypt(PAD(plaintext_message).encode("utf-8"))
Note: this seems to be for python 3.x. For 2.x this same solution may not work.

python how to convert str to unicode ( persion )?

this string is subject of a mail. I get this string by imaplib.
type of this string is "str".
thank you!
#-*- coding: utf-8 -*-
import imaplib
from email.parser import HeaderParser
conn = imaplib.IMAP4('imap.gmail.com')
conn.login('myuser', 'my_pass')
conn.select()
conn.search(None, 'ALL') # returns a nice list of messages...
data = conn.fetch(1, '(BODY[HEADER])')
header_data = data[1][0][1]
parser = HeaderParser()
msg = parser.parsestr(header_data)
print repr(msg['subject'].decode('utf-8'))
result:
u'=?UTF-8?B?V2VsY29tZSB0byBBdGxhc01haWw=?='
Use the decode_header and make_header functions from the email.header package to process the header, then convert the header object to unicode:
from email.header import make_header, decode_header
header = make_header(decode_header(msg['subject']))
unicode_header = unicode(header)
print repr(unicode_header) # prints: u'Welcome to AtlasMail'
The encoding of non ascii characterers in an e-mail subject is decribed at RFC-1342 -
as you can see there, your utf-8 bytes are, in this case, base 64 encoded.
SO, to actually read this, you could do something along:
import base64, quopri
try:
encoding, enc_type, subject = msg["subject"].split("?", 2)
except ValueError:
subject = msg["subject"].decode("utf-8")
enc_type = "N/A"
if enc_type == "B":
subject = base64.decodestring(subject).decode(encoding.lower())
elif enc_type == "Q":
subject = quopri.decodestring(subject).decode(encoding.lower())

Categories

Resources