This should cover most of the python api you'll commonly use when solving cryptography problems (except
pycryptodome but we don't need to worry about that for now)
I would recommend having the python REPL open (type
python in the command line) and following along with the code examples
# The bytes type is usually defined like this my_bytes = b"this is not a string, but a bytes object!" list(my_bytes) # converts my_bytes to a list of numbers bytes(my_list) # converts a list of numbers to a bytes object
A Bytes object is really just a list of numbers, and you can see that by running
list(b"my bytes") or
b"my bytes". There is one important detail, which is that a number in a byte array is always between 0 and 255, which is 2**8-1. For details, wait til cpsc 121!
- You get bytes objects from reading stuff (ie
open("data","rb").read()) or converting from other data formats (hex, base64)
- You usually want to work with the list of numbers (because you can then map and iterate over it easily)
- You want to convert your final result to a bytes object to print it (because python will then format it nicely for you)
chr(x) # converts a decimal number x between 0 and 255 to it's character ord(c) # converts a character c to it's corresponding byte number ord("a") == 97 chr(97) == "a"
Since all bytes are numbers and we sometimes want bytes to represent characters instead of random numbers, some smart people figured out the ascii table and that's what
Very similar to
"my string".encode() # converts from a string to bytes b"my bytes".decode() # converts from bytes to a string
These can be thought of as shorthand for calling
chr on each character/number in a string/bytes.
Your best friends will probably be good ol' for loops
For the imperatively minded, this will print the numbers in the array, so
for b in b"my bytes": print(b)
For the functionally minded (and those who took 110), python does have maps and filters and such
list(map(lambda x: x+1, b"my bytes"))
My preferred method is using python list comprehensions since they're basically less clunky maps
[x+1 for x in b"my bytes"]
If you've taken 121 you've seen it before, but it turns out that xor is actually quite important for various parts of cryptography. If you haven't taken 121, you'll want to understand how xor works so google "bitwise XOR". Good googling skills are important!
python has a xor operator,
x ^ y # this is x xor y # x and y have to be numbers
^ only operates on numbers, you have to use one of the above strategies for actually xoring your entire bytes object.
This might be a bit tricky if you haven't seen this type of interface before, but here's how you work with files in python
mode = "r" # Read my file as a big string mode = "rb" # Read my file as a big bytes object mode = "w" # Write strings to my file mode = "wb" # Write bytes to my file f = open("my_filename", mode) # Open "./my_filename" with the given mode # if you don't input a mode, the mode is assumed to be "r" # You have to give a filename that already exists to use either r or rb # But you can use w or wb with a file that doesnt exist, python will create the file for you # f is a file object, the functions you can call on it are: f.close() # Closes the file, must always be called or else bad things happen # ============================================= # if you opened as mode = "r" f.read() # Returns the entire contents of the file as a big string f.readlines() # Returns an array of strings where each string is a line from the file # ============================================= # if you opened as mode "rb" f.read() # Returns the entire contents of the file as a big bytes object # ============================================= # if you opened as mode "w" f.write(my_string) # Writes the string into the file # ============================================= # if you opened as mode "wb" f.write(my_bytes) # Writes the bytes into the file
This is only a basic summary, but hopefully it gives you the basic gist for how files work in python. You can read more about them here. If you're curious about why files work like this and why you need to seek around a file then wait til 313! You'll learn all about them there.
Did you know that you can automatically make any program write to a file instead of printing out it's results?
$ python my_script.py > result.txt
my_script.py prints out will be put into
result.txt instead of being shown on the terminal.
Here's some functions to get you started
def cons(x, xs): return [x] + xs def first(b): return b def rest(b): return b[1:] # <-- python slice notation def fn_for_bytes(b): if len(b) == 0: return # ... else: first_res = # ... fn_for_byte(first(b)) rest_res = # ... fn_for_bytes(rest(b)) result = # ... first_res, rest_res return result
(PS: Though all the code you'll be presented with will be in an imperative style, so you should get used to the whole imperative thing)