Python - can someone tell me what these two lines do? - python

I'm trying to convert this Python code to C. But for the life of me, I can't figure out what this line here does. The rest of the program seems simple.
self.payload = "\x02\x00%s%s" % (
pack(">b", length),
"".join(random.choice(string.printable) for i in range(length)))
If anybody could give me a rough idea of what this is doing, it'd be much appreciated!

First line:
The correct translation of length = random.randint(18, 20) is int length = rand() % 3 + 18.
Now let's dissect the dense second line piece by piece.
"\x02\x00%s%s" % (x, y) means to substitute the format string with the given arguments (like sprintf()). In this case it means concatenating the bytes 0x02, 0x00 with two strings x and y to follow.
x = pack(">b", length) uses struct.pack(). In this case, it means to convert the integer value length into one byte representing its value. It's almost equivalent to using chr().
y = "".join(z) means to take each element in the list z (which must be a string) and concatenate them with "" (nothing) between them. (For example, "#".join(["a","b","c"]) --> "a#b#c".)
z = (random.choice(string.printable) for i in range(length)) returns a generator object. You can think of it as a list whose elements are computed on demand. In this case, it generates length elements where each element is one character randomly chosen from the string string.printable.
All in all, the second line yields a string that starts wxth 0x02 0x00, followed by (char)length, followed by length random characters each uniformly chosen from the set of chars string.printable.

Related

How to call an index value from an itertools permutation without converting it to a list?

I need to create all combinations of these characters:
'0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM. '
That are 100 letters long, such as:
'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
I'm currently using this code:
import itertools
babel = itertools.product(k_c, repeat = 100)
This code works, but I need to be able to return the combination at a certain index, however itertools.product does not support indexing, turning the product into a list yields a MemoryError, and iterating through the product until I reaches a certain value takes too long for values over a billion.
Thanks for any help
With 64 characters and 100 letters there will be 64^100 combinations. For each value of the first letter, there will be 64^99 combinations of the remaining letters, then 64^98, 64^97, and so on.
This means that your Nth combination can be expressed as N in base 64 where each "digit" represents the index of the letter in the string.
An easy solution would be to build the string recursively by progressively determining the index of each position and getting the rest of the string with the remainder of N:
chars = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM. '
def comboNumber(n,size=100):
if size == 1: return chars[n]
return comboNumber(n//len(chars),size-1)+chars[n%len(chars)]
output:
c = comboNumber(123456789000000000000000000000000000000000000123456789)
print(c)
# 000000000000000000000000000000000000000000000000000000000000000000000059.90jDxZuy6drpQdWATyZ8007dNJs
c = comboNumber(1083232247617211325080159061900470944719547986644358934)
print(c)
# 0000000000000000000000000000000000000000000000000000000000000000000000Python.Person says Hello World
Conversely, if you want to know at which combination index a particular string is located, you can compute the base64 value by combining the character index (digit) at each position:
s = "Python.Person says Hello World" # leading zeroes are implied
i = 0
for c in s:
i = i*len(chars)+chars.index(c)
print(i) # 1083232247617211325080159061900470944719547986644358934
You are now this much closer to understanding base64 encoding which is the same thing applied to 24bit numbers coded over 4 characters (i.e 3 binary bytes --> 4 alphanumeric characters) or any variant thereof

How to compare specific items in a string python

E.g. in a given input the fourth digit must be one greater than the fifth digit
input = "5000-0000-0000"
if input[3] != input[5] + 1
return false
If you think about what input[3] and input[5] are, you will pretty quickly realize they are characters and not numbers that can be added or compared with mathematical operations (think about what would happen if you wrote input = "Andrew Francis").
You can see this by using print(type(input[3])).
Fortunately, if you have a string that contains only characters that make up a valid number, you can convert it to (for instance) an integer using the int() function. So, try print(type(int(input[3]))) and see what you get.

How do I get hex() to print the full hex value in Python?

Say I have 2 hex values that were taken in from keyboard input.
E.g. val1 = 0x000000 and val2 = 0xFF0000
and I do,
print(hex(val1))
print(hex(val2))
I get the right output for val2 but val1 is just 0x0, how do I get it to print the whole value?
By whole value, I mean, if the inputted value is 0x000000, I want to output the value as 0x000000 and not 0x0.
Use the format() built-in function to show the hex representation to the expected level of precision:
>>> format(53, '08x')
'00000035'
>>> format(1234567, '08x')
'0012d687'
The format code 08x means "eight lowercase hex digits padded with leading zeros".
You can pad the hex value to the specified number of digits by using the ljust method.
Whenever the string is less than the specified width, it'll append the specified filler character to extend it.
In your example example, hex(0x0).ljust(8, '0') == "0x000000".
Strings that are already long enough are preserved so that 0xFF0000 will still work.
print(hex(0x000000).ljust(8, '0')) # Prints 0x000000
print(hex(0xFF0000).ljust(8, '0')) # Prints 0xFF0000
A couple of important things to note that have bitten me in the past:
Make sure your width includes the length of the leading "0x"
This is because the ljust function operator operates on raw text and doesn't realize it's a hex string
If you give a width value shorter than you need, the strings won't be filled up enough and will have different lengths.
In other words len(hex(0xFF0000).ljust(4, '0')) != len(hex(0xFF0000).ljust(4, '0')) because you need a length of 8 characters to fit both cases
You say the user typed this input in on the keyboard. That means you already started with the strings you want, but you parsed integers out of the input and threw away the strings.
Don't do that. Keep the strings. Parse integers too if you need to do math, but keep the strings. Then you can just do
print(original_input)
without having to go through a reconstruction process and guess at how many leading zeros were originally input.

str_to_a32 - What does this function do?

I need to rewrite some Python script in Objective-C. It's not that hard since Python is easily readable but this piece of code struggles me a bit.
def str_to_a32(b):
if len(b) % 4:
# pad to multiple of 4
b += '\0' * (4 - len(b) % 4)
return struct.unpack('>%dI' % (len(b) / 4), b)
What is this function supposed to do?
I'm not positive, but I'm using the documentation to take a stab at it.
Looking at the docs, we're going to return a tuple based on the format string:
Unpack the string (presumably packed by pack(fmt, ...)) according to the given format. The result is a tuple even if it contains exactly one item. The string must contain exactly the amount of data required by the format (len(string) must equal calcsize(fmt)).
The item coming in (b) is probably a byte buffer (represented as a string) - looking at the examples they are represented the the \x escape, which consumes the next two characters as hex.
It appears the format string is
'>%dI' % (len(b) / 4)
The % and %d are going to put a number into the format string, so if the length of b is 32 the format string becomes
`>8I`
The first part of the format string is >, which the documentation says is setting the byte order to big-endian and size to standard.
The I says it will be an unsigned int with size 4 (docs), and the 8 in front of it means it will be repeated 8 times.
>IIIIIIII
So I think this is saying: take this byte buffer, make sure it's a multiple of 4 by appending as many 0x00s as is necessary, then unpack that into a tuple with as many unsigned integers as there are blocks of 4 bytes in the buffer.
Looks like it's supposed to take an input array of bytes represented as a string and unpack them as big-endian (the ">") unsigned ints (the 'I') The formatting codes are explaied in http://docs.python.org/2/library/struct.html
This takes a string and converts it into a tuple of Unsigned Integers. If you look at the python struct documentation you will see how it works. In a nutshell it handles conversions between Python values and C structs represented as Python strings for handling binary data stored in files (unceremoniously copied from the link provided).
In your case, the function takes a string, b and adds some extra characters to make sure that it is the standard size of the an unsigned int (see link), and then converts it into a tuple of integers using the big endian representation of the characters. This is the '>' part. The I part says to use unsigned integers

How to retain leading zeros of int variables?

Below is a section of code which is part of a functional decryption and encryption program.
while checkvar < maxvar: # is set to < as maxvar is 1 to high for the index of var
#output.append("%02d" % number)
i =ord(var[checkvar]) - 64 # Gets postional value of i
i = ("%02d" % i)
if (checkvar + 1) < maxvar:
j =ord(var[(checkvar + 1)]) - 64 # Gets postional value of i
j = ("%02d" % j)
i = str(i) + str(j) #'Adds' the string i and j to create a new i
li.append(int(i))
checkvar = checkvar + 2
print li
As you can see the two variables i and j are first treated as string to add a 0 in front of any single digit numbers (as string). These variables then are combined to make a four digit number (still as a string). Later in the program the number created are used in a pow() function, as ints remove any leading zeros.
My question: Is it possible to force python to keep the leading zero for ints? I have and continued to search online.
Edit
To help people I have included the encryption part of the program. This is where the problem lies. The variables created in the above code are passed through a pow() function. As this can't handle strings I have to convert the variables to ints where the leading zero is lost.
#a = li[]
b=int(17)#pulic = e
c=int(2773)#=n
lenli=int(len(li))
enchecker = int(0)
#encrpted list
enlist = []
while enchecker < lenli:
en = pow(li[enchecker],b,c)#encrpyt the message can only handle int
enlist.append(int(en))
enchecker = enchecker + 1
print enlist
Though the comments above are true regarding 1, 01, and 001, are all the same as an int, it can be very helpful in temporal modeling, or sequential movie making to maintain the leading zeros. I do it often to ensure movie clips are in proper order. The easy way to do that is using zfill() to ensure the str version of the number has at least the number of characters you tell it, and does so by filling in the left-side of the string "number" with zeros.
>>> x = int(1)
>>> NewStringVariable = str(x).zfill(3)
>>> print NewStringVariable
001
>>> NewStringVariable = str(x).zfill(5)
>>> print NewStringVariable
00001
The concept of leading zeros is a display concept, not a numerical one. You can put an infinite number of leading zeros on a number without changing its value. Since it's not a numeric concept, it's not stored with the number.
You have to decide how many zeros you want when you convert the number to a string. You could keep that number separately if you want.
I was getting date strings in the format of hhmmss coming from the serial line of my Arduino.
Suppose I got s = "122041"; this would be 12:20:41, however 9am would be 090000.
The statement print "%d" % (s) provokes a run time error because the 9 is not an octal number and is hence an illegal character.
To fix this problem:
print "%06d" % (int(s))
Try this:
number = 1
print("%02d" % (number,))
or:
print("{:02d}".format(number))
The explanation of "%02d":
% - This tells the interpreter that a variable should be inserted here.
02 - This tells the interpreter to expect the variable to be 2 in length.
d - This tells the interpreter to expect a number, or should we say a"'d’igit".

Categories