Python - convert function parameter input to hex - python

I have a python function called read_memory that has one parameter that is called addr. I want to implement a way to convert the addr to HEX value. It sounds simple but the user can enter either a string/int in the parameter:
read_memory(0x106940)
read_memory('0x106940')
read_memory(106940) #this is an int
read_memory('106940')
The result should all be 0x106940. I have the following code but it does not work as expected:
def read_memory(addr):
hex_addr = str(addr)
if('0x' not in hex_addr):
hex_addr = '0x' + hex_addr
return hex_addr
The results are:
read_memory(0x106940) -> 0x1075520
read_memory('0x106940') -> 0x106940
read_memory(106940) -> 0x106940
read_memory('106940') -> 0x106940
Any help is appreciate.

I don't think it is such a great idea to have your function accept int
in base 10 and int in base 16 indiscriminately; this will hurt you
down the road. The following treats proposal treats the input as it is,
instead of "as it should be".
You could use a try except block to control the flow:
def read_memory(addr):
try:
return hex(addr)
except TypeError:
str_addr = str(addr)
if('0x' != str_addr[:2]):
hex_addr = '0x' + str_addr
else:
hex_addr = str_addr
return hex_addr
print(read_memory(0x106940)) # a hex (int base 16)
print(read_memory('0x106940')) # a string representing a hex
print(read_memory(106940)) # an integer (int base 10)
print(read_memory('106940')) # a string representing a hex
The results are:
0x106940
0x106940
0x1a1bc # <-- this is the hex value of integer 106940
0x106940

Related

"int() can't convert non-string with explicit base" but it is a string

I'm trying to convert some hex input into decimal RGB. Apologies if the code is bad, I'm new at python but I'm getting the error in the title even tho the input is a string? (I already printed the stuff to be converted into decimal before converting and they are all string)
v1 = input("Enter the first pixel value: ")
v2 = input("Enter the second pixel value: ")
#px_to_gen = input ("Enter the number of pixels to generate in between: ")
#group (r g b) values of v1 & v2 in a list
v1_ls = ["".join((v1[2],v1[3])),"".join((v1[4],v1[5])),"".join((v1[6],v1[7]))]
v2_ls = ["".join((v2[2],v2[3])),"".join((v2[4],v2[5])),"".join((v2[6],v2[7]))]
print(v1_ls)
print(v2_ls)
#convert values in v1_ls & v2_ls to decimal
i = 0
while (i <= 2):
v1_ls[i] = int(v1_ls[i], 16)
v2_ls[i] = int(v2_ls[i], 16)
print(v1_ls)
print(v2_ls)
I assume you're facing this error: TypeError: int() can't convert non-string with explicit base
This is because you're trying to convert a list directly to integer with base conversion.
To fix this you can try below code, (converting into string first).
v1_ls[i] = int(str(v1_ls[i]), 16)
v2_ls[i] = int(str(v2_ls[i]), 16)
But please remember that you need to fix a big issue with your while loop - it'll go in a infinite loop.

how to convert integer to binary for serial port

I am trying to send a value over serial port. I am unsure how to convert it into the correct format. I tried bin() for binary and format() but it didn't work.
result = 2
ser.open()
ser.write(b'1')
time.sleep(3)
ser.write(result) # wrong format
ser.write("{0:b}".format(result)) # TypeError: unicode strings
# are not supported, please
# encode to bytes: '10'
The first write operation sends '1' as binary string. Now I want the variable to be send as binary string as well.
write() requires a bytes object.
>>> help(serial.Serial.write)
Help on function write in module serial.serialwin32:
write(self, data)
Output the given byte string over the serial port.
To convert an integer to bytes, call int.to_bytes().
>>> result = 2
>>> b = result.to_bytes(4, 'little')
>>> b
b'\x02\x00\x00\x00'
>>> # to convert back to an integer
>>> int.from_bytes(b, 'little')
2
Like this :
import binascii
def write(num):
pack = binascii.unlexlify("%04X"%num)
ser.write(pack)
Important point: Which number system used on device (8,16,32,64 bit) ?
8 Bit = 1 Byte(0-255)
16Bit = 2 Byte(0-65535)
32Bit = 4 Byte(like upside)(0-4294967295)
All ranges are UNSIGNED(look up), but float
got extra definition !
You can't type binary 1 value with keyboard :
binascii.unlexlify("%01X"%1) so equal to \x01 (of course you can use struct package)
write() method accepts a string parameter. You can convert result to string with str() builtin function like this.
result = str(result)
Python 2:
result = 2
ser.open()
ser.write(b'1')
time.sleep(3)
ser.write(str(result))
Python 3:
You have to encode string in bytes.
result = 2
ser.open()
ser.write(b'1')
time.sleep(3)
ser.write(str(result).encode('utf-8'))

Hex To Int In Python No Int Constructor

I'm trying to turn a string representing a Hexidecimal number into an int in python without using the int constructor.
For example if I was given
hexstring = "802"
How would I get that to be
output = 2050
Without doing
int("802",16)
How would I go about this?
hexstring = "802"
L=len(hexstring)
def val(h_char):
# Note you need to extend this to make sure the lowercase hex digits are processed properly
return ord(h_char)- (55 if ord(h_char)>64 else 48)
def sumup(sum,idx):
global hexstring # global variables are not recommended
L=len(hexstring)
return sum + 16**idx*val(hexstring[L-idx-1])
output = reduce(lambda a,b:sumup(a,b),range(L),0))
Below is just an explanation of the above and doesn't add any value
Processes on a list of [0,1,2] produced by range(L).
For each idx from above list a function call is made as sumup(sum, idx)=sum+16^idx*h_digit_at_idx.(^ is ** is exp in above)
h_digit_at_idx = ord(h_char)- (55 if ord(h_char)>64 else 48)
ord(h_char) produces 48,49...57,65,66,67,68,69,70 for hex characters 0,1...10,A,B,C,D,E,F
ord(h_char)-(55 if ord(h_char)>64 else 48 produces 0,1...10,11,12,13,14,15 for respective chars.
Finally the last argument of the reduce function is 0(which is the initial sum to start with)

Converting a hex value of a string to an Ascii character with a hex value

Specifically in Python 2.4, which is unfortunately old, I need to convert a length into hex value. Length of 1 would be '\x00\x01' while a length of 65535 would be '\xFF\xFF'.
import struct
hexdict = {'0':'\x00\x00', '1':'\x00\x01', '2':'\x00\x02', '3':'\x00\x03', '4':'\x00\x04', '5':'\x00\x05', '6':'\x00\x06', '7':'\x00\x07', '8':'\x00\x08', '9':'\x00\x09', 'a':'\x00\x0a', 'b':'\x00\x0b', 'c':'\x00\x0c', 'd':'\x00\x0d', 'e':'\x00\x0e', 'f':'\x00\x0f'}
def convert(int_value): # Not in original request
encoded = format(int_value, 'x')
length = len(encoded)
encoded = encoded.zfill(length+length%2)
retval = encoded.decode('hex')
if x < 256:
retval = '\x00' + retval
return retval
for x in range(16):
print hexdict[str(hex(x)[-1])] # Original, terrible method
print convert(x) # Slightly better method
print struct.pack(">H", x) # Best method
Aside from having a dictionary like above, how can I convert an arbitrary number <= 65535 into this hex string representation, filling 2 bytes of space?
Thanks to Linuxios and an answer I found while waiting for that answer, I have found three methods to do this. Obviously, Linuxios' answer is the best, unless for some reason importing struct is not desired.
Using Python's built-in struct package:
import struct
struct.pack(">H", x)
For example, struct.pack(">H", 1) gives '\x00\x01' and struct.pack(">H", 65535) gives '\xff\xff'.

Get the big-endian byte sequence of integer in Python

Based on this post: How to return RSA key in jwks_uri endpoint for OpenID Connect Discovery
I need to base64url-encode the octet value of this two numbers:
n = 124692971944797177402996703053303877641609106436730124136075828918287037758927191447826707233876916396730936365584704201525802806009892366608834910101419219957891196104538322266555160652329444921468362525907130134965311064068870381940624996449410632960760491317833379253431879193412822078872504618021680609253
e = 65537
The "n" (modulus) parameter contains the modulus value for the RSA public key. It is represented as a Base64urlUInt-encoded value.
Note that implementers have found that some cryptographic libraries
prefix an extra zero-valued octet to the modulus representations they
return, for instance, returning 257 octets for a 2048-bit key, rather
than 256. Implementations using such libraries will need to take
care to omit the extra octet from the base64url-encoded
representation.
The "e" (exponent) parameter contains the exponent value for the RSA
public key. It is represented as a Base64urlUInt-encoded value.
For instance, when representing the value 65537, the octet sequence
to be base64url-encoded MUST consist of the three octets [1, 0, 1];
the resulting representation for this value is "AQAB".
For example, a valid encode should look like this: https://www.googleapis.com/oauth2/v3/certs
¿How could I do this in Python?
After searching the best way to tackle this problem, using pyjwkest seems to be a good one instead of creating my own function.
pip install pyjwkest
Then we use long_to_base64 function for this
>>> from jwkest import long_to_base64
>>> long_to_base64(65537)
'AQAB'
Unfortunately pack() doesn't support numbers that big, and int.to_bytes() is only supported in Python 3, so we'll have to pack them ourselves before encoding. Inspired by this post I came to a solution by converting to a hex string first:
import math
import base64
def Base64urlUInt(n):
# fromhex() needs an even number of hex characters,
# so when converting our number to hex we need to give it an even
# length. (2 characters per byte, 8 bits per byte)
length = int(math.ceil(n.bit_length() / 8.0)) * 2
fmt = '%%0%dx' % length
packed = bytearray.fromhex(fmt % n)
return base64.urlsafe_b64encode(packed).rstrip('=')
Resulting in:
n = 124692971944797177402996703053303877641609106436730124136075828918287037758927191447826707233876916396730936365584704201525802806009892366608834910101419219957891196104538322266555160652329444921468362525907130134965311064068870381940624996449410632960760491317833379253431879193412822078872504618021680609253
e = 65537
Base64urlUInt(n) == 'sZGVa39dSmJ5c7mbOsJZaq62MVjPD3xNPb-Aw3VJznk6piF5GGgdMoQmAjNmANVBBpPUyQU2SEHgXQvp6j52E662umdV2xU-1ETzn2dW23jtdTFPHRG4BFZz7m14MXX9i0QqgWVnTRy-DD5VITkFZvBqCEzWjT_y47DYD2Dod-U'
Base64urlUInt(e) == 'AQAB'
Here is a different bit of Python code for the task, taken from rsalette
def bytes_to_int(data):
"""Convert bytes to an integer"""
hexy = binascii.hexlify(data)
hexy = b'0'*(len(hexy)%2) + hexy
return int(hexy, 16)
def b64_to_int(data):
"""Convert urlsafe_b64encode(data) to an integer"""
return bytes_to_int(urlsafe_b64decode(data))
def int_to_bytes(integer):
hexy = as_binary('%x' % integer)
hexy = b'0'*(len(hexy)%2) + hexy
data = binascii.unhexlify(hexy)
return data
def int_to_b64(integer):
"""Convert an integer to urlsafe_b64encode() data"""
return urlsafe_b64encode(int_to_bytes(integer))
def as_binary(text):
return text.encode('latin1')

Categories

Resources