in attempt to make simple code to convert a hex string to base64:
my thought was: hex -> integer -> binary -> base64
so i wrote this little code:
import string
def bit(integer):
# To binary
return int(bin(integer))[2:]
#Hex multiply by 16 depending on position: 0xAB = A*(16**2) + B(16**1) = #10*16**2 + 11*16**1
#0x3a2f
#3*(16**2) + 7*(16**1) + 5
def removeletter(list):
#"abcdef" = "10 11 12 13 14 15"
for i, letter in enumerate(list):
if letter in hextable.keys():
list[i] = hextable[letter]
return list
def todecimal(h):
power = 0
l = [num for num in str(h)] #['3', 'a', '2', 'f']
l = removeletter(l)
l.reverse() #['f', '2', 'a', '3']
for i, n in enumerate(l):
number = int(n)
l[i] = number*(16**power)
power += 1
l.reverse()
return sum(l)
lowers = string.ascii_lowercase
hextable = {}
for number, letter in enumerate(lowers[:6]):
hextable[letter] = number + 10
in this little challenge i am doing, it says:
The string:
49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
Should produce:
SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t
ok,
print(bit(todecimal('49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d')))
this should get the binary of the hex string, which if I put through a binary to base64 converter, should return SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t. or so i thought.
└─$ python3 hextobase64.py
10010010010011101101101001000000110101101101001011011000110110001101001011011100110011100100000011110010110111101110101011100100010000001100010011100100110000101101001011011100010000001101100011010010110101101100101001000000110000100100000011100000110111101101001011100110110111101101110011011110111010101110011001000000110110101110101011100110110100001110010011011110110111101101101
after checking using a hex to binary converter, i can see that the binary is correct.
now, if if i put this through a binary to base64 converter, it should return SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t, right?
the thing is, this binary to base64 converter gave me kk7aQNbS2NjS3M5A8t7q5EDE5MLS3EDY0tbKQMJA4N7S5t7c3urmQNrq5tDk3t7a which is odd to me. so I must be doing something wrong. from my understanding, hexadecimal can be represented in binary, and so can base64. base64 takes the binary and groups the binary by 6 digits to produce its own representation. so obviously if I have the binary, it should be interchangeable, but something is wrong.
what am i doing wrong?
Related
I want to create a new binary file by using python according to the following format:
< Part1: 8 bytes > < Part2: 4 bytes > < Part3: 16 bytes>
so that i will write to any part some value and if this value is not the size of that part, then there will be a complement of zeros for that part.
I looking for the best way and the most efficient way to do it.
I read in the internet that I can do something like that:
f = open('file', 'w+b')
res = struct.pack(">l", 0000)
f.write(res)
but I don't sure that i can by this way to keep a place from the hand.
Let's start with some terminology when working with Python data before getting to your code to write a binary file.
Note: The experiments below are using the Python REPL
An integer in Python can be written as a denary/decimal number (e.g. 1)
>>> type(1)
<class 'int'>
It can also be written in hex by adding a leading 0x:
>>> 0x1
1
>>> type(0x1)
<class 'int'>
A hex integer's leading zeros have no effect. While in denary they give an error:
>>> x = 0x0001
>>> print(x)
1
>>> x = 0001
x = 0001
^^^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers
When writing to a binary file it is bytes that need to get written. If the content is an integer it can be converted to bytes with either the int.to_bytes functionality or the struct library functionality.
To convert 1 to bytes using int.to_bytes:
>>> int(1).to_bytes(length=1, byteorder='little')
b'\x01'
With a length of 1 the byte order (endianness) is not important. For numbers stored in more bytes it is important.
>>> int(1).to_bytes(length=4, byteorder='little')
b'\x01\x00\x00\x00'
>>> int(1).to_bytes(length=4, byteorder='big')
b'\x00\x00\x00\x01'
The same result can be achieved with the struct library:
>>> struct.pack('<l', 1)
b'\x01\x00\x00\x00'
>>> struct.pack('>l', 1)
b'\x00\x00\x00\x01'
The other common way to see values written is a hex string. The denary value of 1 could be written as 01000000 or 00000001 to represent 1 in different endian in 4 bytes.
>>> int(1).to_bytes(length=4, byteorder='big').hex()
'00000001'
>>> int(1).to_bytes(length=4, byteorder='little').hex()
'01000000'
In your question you have written 0000 for the value to be converted using struct and written to a file.
f = open('file', 'w+b')
res = struct.pack(">l", 0000)
f.write(res)
0000 will work but 0001 will give the SyntaxError: leading zeros in decimal integer literals are not permitted;
I think what you have in your question is the hex string representation of the value you want written.
If it is a hex string you are trying to input then the following will work:
f = open('file', 'w+b')
res = bytes.fromhex('0001')
f.write(res)
The other piece in your question was about making the values to certain byte length.
If your hex string represents the correct byte length then you are good.
However the example you gave was only 2 bytes long:
bytes.fromhex('0001')
b'\x00\x01'
len(bytes.fromhex('0001'))
2
And you wanted fields of either 4, 8, or 16 bytes long in which case the bytes have to be "padded` with bytes of zero value to get the correct number of bytes. e.g.
>>> bytes.fromhex('0001').rjust(4, b'\x00')
b'\x00\x00\x00\x01'
>>> bytes.fromhex('0001').rjust(8, b'\x00')
b'\x00\x00\x00\x00\x00\x00\x00\x01'
>>> bytes.fromhex('0001').rjust(16, b'\x00')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
If the hex string are in little endian format then ljust would be required:
bytes.fromhex('0100').ljust(4, b'\x00')
b'\x01\x00\x00\x00'
having a brain fart. But how do i decode a string that contains.
t = '%2Fdata%2F'
print(t.decode('utf8'))
'str' object has no attribute 'decode'
expecting /data/
2F is a hexadecimal number of / character. Python has chr function that returns a character representation by a decimal number.
So you need to get two symbols after %s and "decode" ("hex" -> chr(int("hex",16))) them into a character.
def decode_utf(string):
for i in range(string.count("%")):
tmp_index = string.index("%")
hex_chr = string[tmp_index:tmp_index + 3]
#replace only one characher at a time
string = string.replace(hex_chr, chr(int(hex_chr[1:],16)),1)
return string
print(decode_utf("%2Fdata%2F"))
#/data/
print(decode_utf("hello%20world%21"))
#hello world!
Edit 1:
The previous code breaks if there's %25 character, use the code below.
def decode_utf(string):
utf_characters = []
tmp_index = 0
for i in range(string.count("%")):
tmp_index = string.index("%",tmp_index)
hex_chr = string[tmp_index:tmp_index + 3]
if not hex_chr in utf_characters:
utf_characters.append(hex_chr)
tmp_index += 1
for hex_chr in utf_characters:
string = string.replace(hex_chr, chr(int(hex_chr[1:],16)))
return string
print(decode_utf("%25t%20e%21s%2ft%25"))
#%t e!s/t%
decimal = int(input("Enter the Decimal value :"))
def d_b(decimal,binary):
# function to convert decimal to binary
binary = binary + str(decimal % 2)
if decimal > 1:
d_b(decimal//2,binary)
else :
print (binary)
return (binary)
print ("Decimal to Binary : ", d_b(decimal,binary = ''))
Output for input 34:
010001
Decimal to Binary : None
The function prints the answer but doesn't return it and then starts going back to function and starts deleting characters one by one from the string and finally returns none instead of the binary string.
Correct Code :
decimal = int(input("Enter the Decimal value :"))
def d_b(decimal,binary):
# function to convert decimal to binary
if decimal > 0:
binary = d_b(int(decimal)//2,binary)
binary = binary + str(decimal % 2)
return (binary)
print ("Decimal to Binary :",d_b(decimal,binary = ''))
Try this, your welcome:
def d_b(decimal,binary):
# function to convert decimal to binary
binary = binary + str(decimal % 2)
if decimal > 1:
binary = d_b(int(decimal/2), binary) # <-- this is the line you should change
return binary
Or even shorter with the ternary operator:
return decimal > 1 ? d_b(int(decimal/2), binary): binary
I am trying to write an RSA code in python3. I need to turn user input strings (containing any characters, not only numbers) into integers to then encrypt them. What is the best way to turn a sting into an integer in Python 3.6 without 3-rd party modules?
how to encode a string to an integer is far from unique... there are many ways! this is one of them:
strg = 'user input'
i = int.from_bytes(strg.encode('utf-8'), byteorder='big')
the conversion in the other direction then is:
s = int.to_bytes(i, length=len(strg), byteorder='big').decode('utf-8')
and yes, you need to know the length of the resulting string before converting back. if length is too large, the string will be padded with chr(0) from the left (with byteorder='big'); if length is too small, int.to_bytes will raise an OverflowError: int too big to convert.
The #hiro protagonist's answer requires to know the length of the string. So I tried to find another solution and good answers here: Python3 convert Unicode String to int representation. I just summary here my favourite solutions:
def str2num(string):
return int(binascii.hexlify(string.encode("utf-8")), 16)
def num2str(number):
return binascii.unhexlify(format(number, "x").encode("utf-8")).decode("utf-8")
def numfy(s, max_code=0x110000):
# 0x110000 is max value of unicode character
number = 0
for e in [ord(c) for c in s]:
number = (number * max_code) + e
return number
def denumfy(number, max_code=0x110000):
l = []
while number != 0:
l.append(chr(number % max_code))
number = number // max_code
return ''.join(reversed(l))
Intersting: testing some cases shows me that
str2num(s) = numfy(s, max_code=256) if ord(s[i]) < 128
and
str2num(s) = int.from_bytes(s.encode('utf-8'), byteorder='big') (#hiro protagonist's answer)
I am currently writing a Python 3 program to convert decimal to binary among other things for a Uni assignment.
I've nailed everything except for this in the first stage (decimal to binary).
dec = int(input("Enter a number: "))
while dec > 0 or dec == 0:
if dec > 0:
rem = dec % 2
dec = dec // 2
print(rem, end = "")
The output gives the binary number correctly, however it is in reverse.
Can you please tell me how to reverse the output or reverse the conversion process or something to correct the output?
EDIT: I cannot use in-built functions such as bin(dec), etc.
Thanks!
The above code is not decimal to binary, instead it is an example of dividend/reminder. You can do that as follows:
dec, rem = divmod(dec, 2)
If you still want to convert decimal to binary do -
bin(dec)
Based on the comment, would this help?
def dec2bin(d):
s = ''
while d>0:
d,r = divmod(d, 2)
s += str(r)
return s[::-1]
>>> dec2bin(6)
'110'
python program to convert the given binary to decimal, octal and hexadecimal number and vice versa.
conversions of all bases with each other.
x = int(input("press 1 for dec to oct,bin,hex \n press 2 for bin to dec,hex,oct \n press 3 for oct to bin,hex,dec \n press 4 for hex to bin,dec,oct \n"))
if x is 1:
decimal =int(input('Enter the decimal number: '))
print(bin(decimal),"in binary.")
print(oct(decimal),"in octal.")
print(hex(decimal),"in hexadecimal.")
if x is 2:
binary = input("Enter number in Binary Format: ");
decimal = int(binary, 2);
print(binary,"in Decimal =",decimal);
print(binary,"in Hexadecimal =",hex(decimal));
print(binary,"in octal =",oct(decimal));
if x is 3:
octal = input("Enter number in Octal Format: ");
decimal = int(octal, 8);
print(octal,"in Decimal =",decimal);
print(octal,"in Hexadecimal =",hex(decimal));
print(octal,"in Binary =",bin(decimal));
if x is 4:
hex = input("Enter number in hexa-decimal Format: ");
decimal = int(hex, 16);
print(hex,"in Decimal =",decimal);
print(hex,"in octal =",oct(decimal));
print(hex,"in Binary =",bin(decimal));