perfection of first tasks

This commit is contained in:
Christoph J. Scherr 2023-09-04 23:09:52 +02:00
parent f0ec2e26ce
commit 55ddaafdc7
4 changed files with 178 additions and 57 deletions

157
Tasks.md
View File

@ -1,38 +1,63 @@
# Tasks for beginners # Tasks for beginners
This document contains some tasks for Python beginners. It does not aim to teach general This document contains some tasks for Python beginners. It does not aim to teach general
programming techniques, only how to use Python. programming techniques, only how to use Python. I try to avoid unrealistic tasks.
## MD5 Hashchecker ## MD5 Hashchecker
- [ ] Hash `foobar19` with the md5 hashing algorithm
- Hints: ### Produce a single MD5 Hash
Difficulty: 1/5
1. Hash the string `foobar19` with the MD5 hashing algorithm.
<details>
<summary>Hints</summary>
- Use Pythons `hashlib`. - Use Pythons `hashlib`.
- Your hashing function does not take strings for input, only raw data (bytes). - Your hashing function does not take strings for input, only raw data (bytes).
- You need to explicitly tell your hash to actually process the input. - You need to explicitly tell your hash to actually process the input.
- When printing your results, the result may be interpreted as data for characters. - When printing your results, the result may be interpreted as data for characters.
You want the numeric value of the result in Hexadecimal. You want the numeric value of the result in Hexadecimal.
</details>
<details> <details>
<summary>Solution</summary> <summary>Solution</summary>
MD5 of `foobar19` is `fa5c65d5438f849387d3fdda2be4dd65`
The MD5 hash of `foobar19` is `fa5c65d5438f849387d3fdda2be4dd65`.
[Example Code](src/md5.py)
</details> </details>
- [ ] 1. rotate the base string `foobar` with numbers from 0 to 999999 like this:
### Hash multiple values and search for specific ones.
Difficulty: 2/5
1. Find a way to produce strings with the basis `foobar` with appended numbers from `000000` to
`999999`.
```text
1. `foobar000000` 1. `foobar000000`
2. `foobar000001` 2. `foobar000001`
3. `foobar000002` 3. `foobar000002`
... ...
999998. `foobar999998`
999999. `foobar999999` 999999. `foobar999999`
2. Get the MD5 hash value for each of those ```
3. How many of these start with `00`?
- Hints: 2. Hash all these with the MD5 hashing algorithm.
- Use a for loop to do the thing X times 3. Find the exact numbers, how many of these hashes start with `00`
- Use Pythons string formatting to put the numbers and string together 4. **Bonus**:
- Use Options for the `%d` Placeholder to get 0 to be displayed as `000000` 1. If MD5 was a good / perfect Hashing algorithm (it is definitely not),
- do the same hashing as in the previous task how many matches for a `00` prefix should exist? Why?
- After hashing, check if your current hash matches the search. 2. How many matches for $0$ to $50000$? How many matches for $0$ to $50.000.000$?
Print it if that is the case to see if the match is a false positive.
- Increment a number on each match. The value of that number after the loop is how many <details>
Hashes start with `00` for this task. <summary>Testvectors</summary>
- Testvectors, the last 5 matches:
Last 5 Matches
```text ```text
999384 | 009671fd23fa783df1fff63516e5d115 999384 | 009671fd23fa783df1fff63516e5d115
999751 | 00ec2ade58f75c44b7300294497f7fb1 999751 | 00ec2ade58f75c44b7300294497f7fb1
@ -40,18 +65,98 @@ programming techniques, only how to use Python.
999852 | 006fe04f7d3f710f93d3e6324506154a 999852 | 006fe04f7d3f710f93d3e6324506154a
999902 | 00c063364ddffa1bdf338dfcf0319424 999902 | 00c063364ddffa1bdf338dfcf0319424
``` ```
<details>
<summary>Solution</summary> </details>
3889 matches for the search parameters. <details>
<summary>Hints</summary>
- Use a for loop to do the thing X times
- Use Pythons string formatting to put the numbers and string together
- Use Options for the `%d` Placeholder to get $0$ to be displayed as `000000`
- After hashing, check if your current hash matches the search.
Print it if that is the case to see if the match is a false positive.
- Increment a number on each match. The value of that number after the loop is how many
Hashes start with `00` for this task.
</details> </details>
- [ ] Continuing from the previous task, what is the earliest value for `foobarXXXXXX` (where `X`
is a substitute for the iterating numbers) where the hash starts with `0000`?
- Hints:
- Stop on the earliest match.
<details> <details>
<summary>Solution</summary> <summary>Solution</summary>
021820 | 00001c9393b83c8da0db478687211d1d
There are 3889 hashes for `foobar000000` to `foobar999999` that start with `00`.
[Code Example](src/md5range.py)
**Bonus**
We want $N/16^2$ occurrences for an ideal hashing algorithm, where $N$ is the maximum of our range
$+ 1$.
$16^2$ comes from $2$ characters in a range of `0` to `e` (Hexadecimal).
We want the hashing algorithm to spread out as much as possible, no value should be more common
than any other value. This is essential for the security of the hashing algorithm.
| Value | Ideal Occurences |
|--------------|------------------|
| $1.000.000$ | $\approx 3906$ |
| $500.000$ | $\approx 1953$ |
| $50.000.000$ | $\approx 195312$ |
</details>
### Find earliest hash that fits criteria
Difficulty: 2/5
1. Find the earliest integer $X$ for `foobarXXXXXX` (where $X$ is an iterator as in the last
subtask) that starts with `2718`.
<details>
<summary>Hints</summary>
- You can reuse most code from the last subtask.
- Match against the new prefix, but stop when you find it.
- Display the index number in each loop iteration.
</details>
<details>
<summary>Solution</summary>
The first hash with prefix `2718` occurs at $i=70559$.
```text
070559 | 2718e5ee6d05091ce6dad023e55ee19c
```
[Code Example](src/md5range-4.py)
</details> </details>
## Super basic web server ## Super basic web server
- [ ] Make a webserver print "Schlangenjazz" when you connect to it
Difficulty: 2/5
1. Program a Python web server that writes "Python is not so hard" in your Browser (or in `cURL`).
Use `http.server`.
<details>
<summary>Hints</summary>
- Use `http.server.SimpleHTTPRequestHandler` and `io.BytesIO`.
- Define your own class that inherits `SimpleHTTPRequestHandler`.
- You don't need to implement `do_GET()`.
- Implement your own `send_head()` method. This is the method that writes your response (not
completely on it's own, but unless you feel like inspecting standard libraries, just do what
I'm saying.).
- `send_head()` should take no arguments (other than `self`) and return some readable buffer.
- Don't forget to set the headers for HTTP before sending the body.
- Your OS might block hosting to ports < 1000. Try to host your web server to `localhost:8080`.
</details>
<details>
<summary>Solution</summary>
Take a look at the provided Code Example.
[Code Example](src/miniweb.py)
</details>

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import hashlib import hashlib
import sys import sys
hashed = hashlib.md5(sys.argv[1].encode()) to_hash = "foobar19"
hashed = hashlib.md5(to_hash.encode())
print(hashed.digest().hex()) print(hashed.digest().hex())

19
src/md5range-4.py Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
import hashlib
BASE: str = "foobar"
MAX = 1000000
SEARCH = "2718"
count = 0
for i in range(0, MAX):
num: str = ("%06d" % i)
current = BASE + num
res = hashlib.md5(current.encode()).digest().hex()
if SEARCH == res[:4]:
count += 1
print("%06d | %s" % (i, res))
break
print(f"\nFound %d digests matching the search" % count)

View File

@ -2,10 +2,7 @@
import http.server import http.server
import io import io
TEXT = """Hello world! TEXT = "Python is not so hard"
If you're reading this, this web server is working!
"""
class MyHandler(http.server.SimpleHTTPRequestHandler): class MyHandler(http.server.SimpleHTTPRequestHandler):
def send_head(self) -> io.BytesIO: def send_head(self) -> io.BytesIO:
@ -20,4 +17,3 @@ class MyHandler(http.server.SimpleHTTPRequestHandler):
addtrss = ("127.0.0.1", 8080) addtrss = ("127.0.0.1", 8080)
srv = http.server.HTTPServer(addtrss, MyHandler) srv = http.server.HTTPServer(addtrss, MyHandler)
srv.serve_forever() srv.serve_forever()