Python script to convert hexadecimal to decimal - python

I've written the python script below to convert hexadecimal to decimal.
It seems to work fine, at least as long as the hexadecimal has less then 8 characters .
What did I do wrong ? Tnx !
""" converts hexidecimal to decimal"""
def HextoDec (string):
ret = 0
for i in string :
hex = "0123456789ABCDEF"
value= hex.index(i) # 0 to 15
index = string.index(i)
power = (len(string) -(index+1)) #power of 16
ret += (value*16**power)
return ret
print(HextoDec("BAABFC7DE"))

The problem is this line:
index = string.index(i)
index() returns the position of the first match. If the hex number contains any duplicate characters, you'll get the wrong index for all the repeats.
Instead of searching for the index, get it directly when you're iterating:
for index, i in enumerate(string):

There is a much easier way to convert hexadecimal to decimal without the use of a custom function - just use the built-in int() function like so:
int("BAABFC7DE", base=16) #replace BAABFC7DE with any hex code you want
But if you do want to use a custom function, then Barmar's answer is the best.

As Barmar pointed out. The issued is with the line
index = string.index(i)
Which returns first match. Try this:
def HextoDec (string):
ret = 0
for i,d in enumerate(string) :
hex = "0123456789ABCDEF"
value= hex.index(d) # 0 to 15
#index = string.index(i)
power = (len(string) -(i+1)) #power of 16
ret += (value*16**power)
return ret

Related

How to take an arbitrary sequence of bits from a byte array and turn it into an integer in Python?

I am looking for a python equivalent of https://www.npmjs.com/package/bit-sequence.
That is to say, I need a function which takes some 'bytes', some 'start' value corresponding to an integer bit index to start extraction (not byte index), and some 'length' value to correspond to the amount of bits to extract from the bytes array
Here's an answer, with the example from the page you linked:
def bitSequence(bytes, start, length):
# Converting the bytes array into one long bit string
binstring = "".join([bin(byte)[2:].zfill(8) for byte in bytes])
# Converting the required part of the bitstring to a base 10 int
ret_byte = int("0b"+binstring[start:start+length], 2)
return ret_byte
example=[ 0b00010101, 0b10101000, 0b00000000, 0b00000000 ]
print(bitSequence(example , 7, 11))
1696
I think that solves your problem, for more information about bit manipulation in python take a look at this link ->https://realpython.com/python-bitwise-operators/#bit-strings-in-python
def bytes_extraction(bytes, start, length):
bytes = bin(bytes)
result = bytes[start:start+length]
result = int(result, 2)
return result
bits = 0b101010
response = bytes_extraction(bytes=bits , start=2, length=4)
print(response)

int(), can't convert non-string with explicit base in python

there are two things I can't understand:
1-What does "non-string - with explicit base" means? is it like pointers?
2 How to solve it?
you can check the code and the error it appears on line 25 here. (it is clickable)
Error message:
dec_list.append(int(rmsg[x],2))
TypeError: int() can't convert non-string with explicit base
It's obvious I'm not a python guy but I'm trying to do smth from time to time.
my aaaa.txt file contains
01110001010100010101010001010101011001010110110101010101010101000001010110010101010000010101001001010010110101
local_file=open('aaaa.txt' , 'r', encoding = 'utf-8')
#1st checkpoint open and read the file
a=local_file.read()
n=10
i=0
msg=list() #create a blank list for lsb first
rmsg=list() #create a blank list for msb first
asciimsg=list() #create a blank list for decoded ASCII character
def swap(num):
str_num = str(num)
str_swapped = str_num[-1] +str_num[-2] + str_num[2:-2] + str_num[1] + str_num[0]
return int(str_swapped)
while (n<=len(a)):
# 3th cp: gets the 7 bit, lsb first in the aaaa.txt, one by one till the end
msg.append(a[i+1:n-2])
rmsg.append(swap(a[i+1:n-2]))
n=n+10
i=i+10
print('lsb first binary:')
print(msg)
print('msb first binary(ASCII):')
print(rmsg)
dec_list=list()
for x in range(len(rmsg)):
dec_list.append(int(rmsg[x],2)) #4th checkpoint: convert to decimal
print('ASCII in decimal:')
print(dec_list)
for z in dec_list:
asciimsg.append(chr(z)) #5th cp: use the chr function to convert to ascii
print(asciimsg)
shortmsg=""
for t in asciimsg:
shortmsg=shortmsg+t
print(shortmsg) #6th cp: printing the decoded msg
int is not a str, so convert it to a string first:
dec_list.append(int(str(rmsg[x]), 2))
It is much more Pythonic to use a list comprehension instead of a for-loop like that, though:
dec_list = [int(str(c), 2) for c in rmsg]
int() is a method used in python to convert numbers in the form of strings to integers, for example: "2" is a string, int("2") = 2 so now 2 is an integer, same for your case but the base case is that the initial form of the message is neither an integer nor a string so first you need to convert the message to a string using str(message) and then int(message), also put as int(str(message)).

Converting OID of public key,etc in HEX data to the dot format

Hello guys,
I have CV1 RSA certificates that are slightly modified.So, I dont want to use asn1wrap to parse a 'der' file as it makes it too complex sometimes,instead as tags are already fixed for a CV1 certificate i can parse the HEX data of this 'der' file by converting the binary data to hex and extracting the required range of data.
However for representation i want the OID to be in the dot format
eg : ABSOLUTE OID 1.3.6.33.4.11.5318.2888.18.10377.5
i can extract the hex string for this from the whole hex data as :
'060D2B0621040BA946964812D10905'
any python3 function that can directly do this conversion. Or can anyone help out with the logic to convert the same.
Found an answer for anyone who's interested. Without using the pyasn1 or asn1crypto i did not find any package to convert the hexadecimal value to OID notation.
So i browsed around and made a mix of code from other languages and created one in python.
def notation_OID(oidhex_string):
''' Input is a hex string and as one byte is 2 charecters i take an
empty list and insert 2 characters per element of the list.
So for a string 'DEADBEEF' it would be ['DE','AD','BE,'EF']. '''
hex_list = []
for char in range(0,len(oidhex_string),2):
hex_list.append(oidhex_string[char]+oidhex_string[char+1])
''' I have deleted the first two element of the list as my hex string
includes the standard OID tag '06' and the OID length '0D'.
These values are not required for the calculation as i've used
absolute OID and not using any ASN.1 modules. Can be removed if you
have only the data part of the OID in hex string. '''
del hex_list[0]
del hex_list[0]
# An empty string to append the value of the OID in standard notation after
# processing each element of the list.
OID_str = ''
# Convert the list with hex data in str format to int format for
# calculations.
for element in range(len(hex_list)):
hex_list[element] = int(hex_list[element],16)
# Convert the OID to its standard notation. Sourced from code in other
# languages and adapted for python.
# The first two digits of the OID are calculated differently from the rest.
x = int(hex_list[0] / 40)
y = int(hex_list[0] % 40)
if x > 2:
y += (x-2)*40
x = 2;
OID_str += str(x)+'.'+str(y)
val = 0
for byte in range(1,len(hex_list)):
val = ((val<<7) | ((hex_list[byte] & 0x7F)))
if (hex_list[byte] & 0x80) != 0x80:
OID_str += "."+str(val)
val = 0
# print the OID in dot notation.
print (OID_str)
notation_OID('060D2B0621040BA946964812D10905')
Hope this helps... cHEErs !

Reading binary file into different hex "types" (8bit, 16bit, 32bit, ...)

I have a file which contains binary data. The content of this file is just one long line.
Example: 010101000011101010101
Originaly the content was an array of c++ objects with the following data types:
// Care pseudo code, just for visualisation
int64 var1;
int32 var2[50];
int08 var3;
I want to skip var1 and var3 and only extract the values of var2 into some readable decimal values. My idea was to read the file byte by byte and convert them into hex values. In the next step I though I could "combine" (append) 4 of those hex values to get one int32 value.
Example: 0x10 0xAA 0x00 0x50 -> 0x10AA0050
My code so far:
def append_hex(a, b):
return (a << 4) | b
with open("file.dat", "rb") as f:
counter = 0
tickdifcounter = 0
current_byte=" "
while True:
if (counter >= 8) and (counter < 208):
tickdifcounter+=1
if (tickdifcounter <= 4):
current_byte = append_hex(current_byte, f.read(1))
if (not current_byte):
break
val = ord(current_byte)
if (tickdifcounter > 4):
print hex(val)
tickdifcounter = 0
current_byte=""
counter+=1
if(counter == 209): #209 bytes = int64 + (int32*50) + int08
counter = 0
print
Now I have the problem that my append_hex is not working because the variables are strings so the bitshift is not working.
I am new to python so please give me hints when I can do something in a better way.
You can use struct module for reading binary files.
This can help you Reading a binary file into a struct in Python
A character can be converted to a int using the ord(x) method. In order to get the integer value of a multi-byte number, bitshift left. For example, from a earlier project:
def parseNumber(string, index):
return ord(string[index])<<24 + ord(string[index+1])<<16 + \
ord(string[index+2])<<8+ord(string[index+3])
Note this code assumes big-endian system, you will need to reverse the index for parsing little-endian code.
If you know exaclty what the size of the struct is going to be, (or can easily calculate it based on the size of the file) you are probably better of using the "struct" module.

How can I convert a byte array to an integer more elegantly in Python

I'm receiving a byte array via serial communication and converting part of the byte array to an integer. The code is as follows:
data = conn.recv(40)
print(data)
command = data[0:7]
if(command == b'FORWARD' and data[7] == 3):
value = 0
counter = 8
while (data[counter] != 4):
value = value * 10 + int(data[counter] - 48)
counter = counter + 1
In short, I unpack the bytearray data starting at location 8 and going until I hit a delimiter of b'\x03'. So I'm unpacking an integer of from 1 to 3 digits, and putting the numeric value into value.
This brute force method works. But is there a more elegant way to do it in Python? I'm new to the language and would like to learn better ways of doing some of these things.
You can find the delimiter, convert the substring of the bytearray to str and then int. Here's a little function to do that:
def intToDelim( ba, delim ):
i=ba.find( delim )
return int(str(ba[0:i]))
which you can invoke with
value = intToDelim( data[8:], b'\x04' )
(or with b'\x03' if that's your delimiter). This works in Python 2.7 and should work with little or no change in Python 3.

Categories