Python 3.8: Bytes to a list of hex - python-3.x

I'm currently banging by head bloody over this problem I have:
I have a method where I receive a byte input of a defined length of 8:
def ConvertToHexAndSend(serialnumber):
if len(serialnumber) != 8:
throw a good exception...
Some good converter code here..
The method shall then take the serialnumber and split it into a list with the size 4.
Example:
serialnumber = b'12345678'
Expected output:
[0x12, 0x34, 0x56, 0x78]
What I have tried so far:
new_list = list(serialnumber) # Gives a list of [49, 50, 51, 52, 53, 54, 55, 56] and then:
first byte = new_list[0] << 8 + new_list[1] # gives some riddish value
and
hex(serialnumber[0]) # Gives '0x32' string
and
first_byte = serialnumber[0] + serialnumber[1] # Gives int 99
But no success so far.. any idea?

You want something like:
result = list(bytes.fromhex(serialnumber.decode('ascii')))
Your bytes are represent a hex-string. So use the bytes.fromhex to read that (converting the bytes to str first), and you can use list to get a list of int objects from the new resulting bytes object

Related

Vala - Bytes convert to string?

I have a GLib.Bytes object.
I want to print it and use it as a string like this:
Bytes bytes = new Bytes({65, 66, 67});
print(bytes); // <-- ERROR
How can I convert it to string?
Get raw byte array uint8[] with Bytes.get_data() and cast it as string.
Example:
Bytes bytes = new Bytes({65, 66, 67});
string str = (string)bytes.get_data();
print(str);
Output:
ABC

Serial communication : Send a list from Python3 to Arduino

I don't manage to deal with my problem even if I have read a lot about it on internet these last few days.
I try to communicate a variable length list from my Python3 program to my Arduino Leonardo.
Actually the length of these lists is variable but there are only three possible length :
first possibility : [0, 0, 1, 176, 1, 0, 0]
second possibility : [0, 1, 11, 255]
third possibility : [0, 2, 0]
(most of the values inside these lists are variables)
My Python3 code :
with Serial(port = port, baudrate=9600, timeout=1, writeTimeout=1) as port_serie :
if port_serie.isOpen() :
for value in Datas_To_Send : #Envoi des données
s = struct.pack('!{0}B'.format(len(Datas_To_Send)), *Datas_To_Send)
port_serie.write(s)
This code sends binary values like this one :
b'\x00\x00\x01\xb0\x01\x00\x00'
(the original list to send was : [0, 0, 1, 176, 1, 0, 0])
The problem is that I absolutely don't know how to find back my original list of values with my Arduino code...
My Arduino code (quite basic) :
void changeSettings() {
if ( Serial.available() > 0 ) {
int byte_read = Serial.read() ;
Serial.println(byte_read, DEC) ;
The output of this code is a pure conversion of each character from the ASCII to the Decimal...
Output (for the binary value I gave as example) :
98
39
92
120
48
48
92
120
48
48
92
120
48
49
92
120
98
48
92
120
48
49
92
120
48
48
92
120
48
48
39
10
Do you have any idea to find the first list back ?
Thank you
It seems you need to transmit either 7, 4 or 3 values, correct?
Are all the values under 256?
So, i would send 1 byte that is either 7, 4 or 3 followed by either 7, 4 or 3 bytes of the list's elements. If any item in your list is greater than 255 and less than 65,536 you'll need to send 2 bytes per element.
Well, I found the solution thanks to #MarkSetchel's and Olmagzar's (Discord user) tips.
Python3 code :
if Datas_To_Send :
long = len(Datas_To_Send)
Datas_To_Send.insert(0, long)
with Serial(port = '/dev/cu.usbmodem14101', baudrate=9600, timeout=1, writeTimeout=1) as port_serie :
if port_serie.isOpen() :
s = struct.pack('!{0}B'.format(len(Datas_To_Send)), *Datas_To_Send)
port_serie.write(s)
port_serie.close()
So I add list length directly at the first position of my list "Datas_To_Send".
Like that I just have to read it first on Arduino's side to know how many items I have to read.
Arduino code :
void changeSettings() {
if (Serial.available() > 0)
{
unsigned char len = Serial.read();
unsigned char Datas[len] ;
for (int i = 0; i < len - 1; i++)
{
unsigned char byte_read = Serial.read();
Datas[i] = byte_read ;
}
}
}

How do I convert a byte array with null terminating character to a String in Kotlin?

When I attempt to retrieve a value from the device via Bluetooth, it comes out in ASCII, as a null terminated big-endian value. The device software is written in C. I want to retrieve the decimal value, i.e. 0 instead of 48, 1 instead of 49, 9 instead of 57, etc.
#Throws(IOException::class)
fun receiveData(socket: BluetoothSocket ? ): Int {
val buffer = ByteArray(4)
val input = ByteArrayInputStream(buffer)
val inputStream = socket!!.inputStream
inputStream.read(buffer)
println("Value: " + input.read().toString()) // Value is 48 instead of 0, for example.
return input.read()
}
How can I retrieve the value I want?
It's easy to do with bufferedReader:
val buffer = ByteArray(4) { index -> (index + 48).toByte() } // 1
val input = ByteArrayInputStream(buffer)
println(input.bufferedReader().use { it.readText() }) // 2
// println(input.bufferedReader().use(BufferedReader::readText)) // 3
Will output "0123".
1. Just stubs the content of a socket using an init function that sets first element of the buffer to 48, second to 49, third to 50 and fourth to 51.
2. The default charset is UTF-8, that is a "superset" of ASCII.
3. It's just another style of calling { it.readText() }.
My function ultimately took the following form. This allowed me to retrieve all 5 digits in decimal form:
#Throws(IOException::class)
fun receiveData(socket: BluetoothSocket ? ): String {
val buffer = ByteArray(5)
(socket!!.inputStream).read(buffer)
println("Value: " + String(buffer))
return String(buffer)
}
For my particular problem, the input variable was being created before reading the data into the buffer. Since the read method is called for every index in the data, I was only getting the first digit.
See the Java method public int read() for an explanation:
Reads the next byte of data from this input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned.

How to find the biggest number in a string that contains not just numbers but words?

How to find the biggest number in a string that contains not just numbers but words?
For example:
String naa = "John 19, Reuben 21, sbu 6, Derick 33";
I need to be able to find the highest age no mater the names and ages entered.
I'm not sure what language you are trying to use but one way to do this in ruby for example would be
str = "John 19, Reuben 21, sbu 6, Derick 33;"
str.gsub(/\d+/).map { |i| i.to_i }.max
What this does is the following:
str.gsub(/\d+/)
Returns all the numbers as an enumerator
The map command then changes them all to integers and returns an Array with the integers.
Then we just call max on that array.
Java
String[] ss = "John 19, Reuben 21, sbu 6, Derick 33;".split("[^\\d]");
System.out.println(Arrays.asList(ss));
int max = Integer.MIN_VALUE;
for(String s:ss){
try{
if (Math.max(Integer.valueOf(s), max) != max){
max = Integer.valueOf(s);
}
}catch(NumberFormatException nfe){}
}
System.out.println(max);
Try this in java
Pattern p = Pattern.compile("[0-9]?[0-9]");
Matcher m = p.matcher(naa) ;
List<Integer> listInt = new ArrayList<Integer>();
while (m.find()) {
int age = Integer.parseInt(m.group());
listInt.add(age);
}
int max = Collections.max(listInt);
System.out.println( max);

How does ASN.1 encode an object identifier?

I am having trouble understanding the basic concepts of ASN.1.
If a type is an OID, does the corresponding number get actually encoded in the binary data?
For instance in this definition:
id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
Does the corresponding 1.3.6.1.5.5.7.48.1 get encoded in the binary exactly like this?
I am asking this because I am trying to understand a specific value I see in a DER file (a certificate), which is 04020500, and I am not sure how to interpret it.
Yes, the OID is encoded in the binary data. The OID 1.3.6.1.5.5.7.48.1 you mention becomes 2b 06 01 05 05 07 30 01 (the first two numbers are encoded in a single byte, all remaining numbers are encoded in a single bytes as well because they're all smaller than 128).
A nice description of OID encoding is found here.
But the best way to analyze your ASN.1 data is to paste in into an online decoder, e.g. http://lapo.it/asn1js/.
If all your digits are less than or equal to 127 then you are very lucky because they can be represented with a single octet each. The tricky part is when you have larger numbers which are common, such as 1.2.840.113549.1.1.5 (sha1WithRsaEncryption). These examples focus on decoding, but encoding is just the opposite.
1. First two 'digits' are represented with a single byte
You can decode by reading the first byte into an integer
var firstByteNumber = 42;
var firstDigit = firstByteNumber / 40;
var secondDigit = firstByteNumber % 40;
Produces the values
1.2
2. Subsequent bytes are represented using Variable Length Quantity, also called base 128.
VLQ has two forms,
Short Form - If the octet starts with 0, then it is simply represented using the remaining 7 bits.
Long Form - If the octet starts with a 1 (most significant bit), combine the next 7 bits of that octet plus the 7 bits of each subsequent octet until you come across an octet with a 0 as the most significant bit (this marks the last octet).
The value 840 would be represented with the following two bytes,
10000110
01001000
Combine to 00001101001000 and read as int.
Great resource for BER encoding, http://luca.ntop.org/Teaching/Appunti/asn1.html
The first octet has value 40 * value1 + value2. (This is unambiguous,
since value1 is limited to values 0, 1, and 2; value2 is limited to
the range 0 to 39 when value1 is 0 or 1; and, according to X.208, n is
always at least 2.)
The following octets, if any, encode value3, ...,
valuen. Each value is encoded base 128, most significant digit first,
with as few digits as possible, and the most significant bit of each
octet except the last in the value's encoding set to "1." Example: The
first octet of the BER encoding of RSA Data Security, Inc.'s object
identifier is 40 * 1 + 2 = 42 = 2a16. The encoding of 840 = 6 * 128 +
4816 is 86 48 and the encoding of 113549 = 6 * 1282 + 7716 * 128 + d16
is 86 f7 0d. This leads to the following BER encoding:
06 06 2a 86 48 86 f7 0d
Finally, here is a OID decoder I just wrote in Perl.
sub getOid {
my $bytes = shift;
#first 2 nodes are 'special';
use integer;
my $firstByte = shift #$bytes;
my $number = unpack "C", $firstByte;
my $nodeFirst = $number / 40;
my $nodeSecond = $number % 40;
my #oidDigits = ($nodeFirst, $nodeSecond);
while (#$bytes) {
my $num = convertFromVLQ($bytes);
push #oidDigits, $num;
}
return join '.', #oidDigits;
}
sub convertFromVLQ {
my $bytes = shift;
my $firstByte = shift #$bytes;
my $bitString = unpack "B*", $firstByte;
my $firstBit = substr $bitString, 0, 1;
my $remainingBits = substr $bitString, 1, 7;
my $remainingByte = pack "B*", '0' . $remainingBits;
my $remainingInt = unpack "C", $remainingByte;
if ($firstBit eq '0') {
return $remainingInt;
}
else {
my $bitBuilder = $remainingBits;
my $nextFirstBit = "1";
while ($nextFirstBit eq "1") {
my $nextByte = shift #$bytes;
my $nextBits = unpack "B*", $nextByte;
$nextFirstBit = substr $nextBits, 0, 1;
my $nextSevenBits = substr $nextBits, 1, 7;
$bitBuilder .= $nextSevenBits;
}
my $MAX_BITS = 32;
my $missingBits = $MAX_BITS - (length $bitBuilder);
my $padding = 0 x $missingBits;
$bitBuilder = $padding . $bitBuilder;
my $finalByte = pack "B*", $bitBuilder;
my $finalNumber = unpack "N", $finalByte;
return $finalNumber;
}
}
OID encoding for dummies :) :
each OID component is encoded to one or more bytes (octets)
OID encoding is just a concatenation of these OID component encodings
first two components are encoded in a special way (see below)
if OID component binary value has less than 7 bits, the encoding is just a single octet, holding the component value (note, most significant bit, leftmost, will always be 0)
otherwise, if it has 8 and more bits, the value is "spread" into multiple octets - split the binary representation into 7 bit chunks (from right), left-pad the first one with zeroes if needed, and form octets from these septets by adding most significant (left) bit 1, except from the last chunk, which will have bit 0 there.
first two components (X.Y) are encoded like it is a single component with a value 40*X + Y
This is a rewording of ITU-T recommendation X.690, chapter 8.19
This is a simplistic Python 3 implementation of the of above, resp. a string form of an object identifier into ASN.1 DER or BER form.
def encode_variable_length_quantity(v:int) -> list:
# Break it up in groups of 7 bits starting from the lowest significant bit
# For all the other groups of 7 bits than lowest one, set the MSB to 1
m = 0x00
output = []
while v >= 0x80:
output.insert(0, (v & 0x7f) | m)
v = v >> 7
m = 0x80
output.insert(0, v | m)
return output
def encode_oid_string(oid_str:str) -> tuple:
a = [int(x) for x in oid_str.split('.')]
oid = [a[0]*40 + a[1]] # First two items are coded by a1*40+a2
# A rest is Variable-length_quantity
for n in a[2:]:
oid.extend(encode_variable_length_quantity(n))
oid.insert(0, len(oid)) # Add a Length
oid.insert(0, 0x06) # Add a Type (0x06 for Object Identifier)
return tuple(oid)
if __name__ == '__main__':
oid = encode_oid_string("1.2.840.10045.3.1.7")
print(oid)

Resources