Compare commits
No commits in common. "master" and "curses-stopwatch" have entirely different histories.
master
...
curses-sto
|
@ -0,0 +1,4 @@
|
||||||
|
# Things i would like to add to this repository
|
||||||
|
Caesar-encryption, decryption, brute force
|
||||||
|
calculate determinante (german, idk the english word) of a matrix
|
||||||
|
|
27
TODO.norg
27
TODO.norg
|
@ -1,27 +0,0 @@
|
||||||
This is a list of tasks that would be cool to add.
|
|
||||||
|
|
||||||
* Tasks
|
|
||||||
** Basic
|
|
||||||
*** Files
|
|
||||||
- (-) Hex dumper
|
|
||||||
- (x) Dump basic files with format
|
|
||||||
- (x) Dump basic files with chars
|
|
||||||
- (x) Be able to dump larger files or put out an error
|
|
||||||
- (x) Stop reading when read gets blocked /somehow/
|
|
||||||
Simple syscall
|
|
||||||
- (x) Wait for new input when the file is lazy
|
|
||||||
- (x) Install script to system
|
|
||||||
Using update-alternatives is the most handy
|
|
||||||
- (x) Accept input from stdin when no file is given
|
|
||||||
- (x) Print error when no file and stdin is given
|
|
||||||
- ( ) Process only first N or last N Bytes
|
|
||||||
- ( ) Write a complete task for this stuff
|
|
||||||
*** Networking
|
|
||||||
- ( ) Mini curl
|
|
||||||
*** Packaging
|
|
||||||
- ( ) Installing a package to your system
|
|
||||||
- ( ) Building a library
|
|
||||||
|
|
||||||
** Cryptography
|
|
||||||
*** Signature
|
|
||||||
- ( ) Check a signature with OpenSSL
|
|
489
Tasks.md
489
Tasks.md
|
@ -1,489 +0,0 @@
|
||||||
# Tasks for beginners
|
|
||||||
|
|
||||||
This document contains some tasks for Python beginners. It does not aim to teach general
|
|
||||||
programming techniques, only how to use Python. I try to avoid unrealistic tasks.
|
|
||||||
|
|
||||||
In case you have somehow gotten this document from another source,
|
|
||||||
[this](https://git.cscherr.de/PlexSheep/py-basic/src/branch/master/Tasks.md) is the original
|
|
||||||
source, where the links should hopefully work. If something does not work feel free to contact
|
|
||||||
me at [software@cscherr.de](mailto:admin@cscherr.de).
|
|
||||||
|
|
||||||
## MD5 Hashchecker
|
|
||||||
|
|
||||||
### A. 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`.
|
|
||||||
- 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.
|
|
||||||
- When printing your results, the result may be interpreted as data for characters.
|
|
||||||
You want the numeric value of the result in Hexadecimal.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>Solution</summary>
|
|
||||||
|
|
||||||
The MD5 hash of `foobar19` is `fa5c65d5438f849387d3fdda2be4dd65`.
|
|
||||||
|
|
||||||
[Example Code](src/md5.py)
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### B. 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`
|
|
||||||
2. `foobar000001`
|
|
||||||
3. `foobar000002`
|
|
||||||
...
|
|
||||||
999998. `foobar999998`
|
|
||||||
999999. `foobar999999`
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Hash all these with the MD5 hashing algorithm.
|
|
||||||
3. Find the exact numbers, how many of these hashes start with `00`
|
|
||||||
4. **Bonus**:
|
|
||||||
1. If MD5 was a good / perfect Hashing algorithm (it is definitely not),
|
|
||||||
how many matches for a `00` prefix should exist? Why?
|
|
||||||
2. How many matches for $0$ to $50000$? How many matches for $0$ to $50.000.000$?
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Testvectors</summary>
|
|
||||||
|
|
||||||
Last 5 Matches
|
|
||||||
|
|
||||||
```text
|
|
||||||
999384 | 009671fd23fa783df1fff63516e5d115
|
|
||||||
999751 | 00ec2ade58f75c44b7300294497f7fb1
|
|
||||||
999844 | 009cfd7949b577a3311d9db3ee49c15d
|
|
||||||
999852 | 006fe04f7d3f710f93d3e6324506154a
|
|
||||||
999902 | 00c063364ddffa1bdf338dfcf0319424
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
<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>
|
|
||||||
<summary>Solution</summary>
|
|
||||||
|
|
||||||
There are 3889 hashes for `foobar000000` to `foobar999999` that produce an MD5 Hash that starts
|
|
||||||
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>
|
|
||||||
|
|
||||||
### C. 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 produces an MD5 hash 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>
|
|
||||||
|
|
||||||
## Super basic web server
|
|
||||||
|
|
||||||
Difficulty: 3/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>
|
|
||||||
|
|
||||||
## Random Password generator
|
|
||||||
|
|
||||||
Difficulty: 2/5
|
|
||||||
|
|
||||||
1. Generate a string of 16 random alphanumeric characters.
|
|
||||||
2. When starting your script, take a number for a CLI Argument. Generate a random string of this
|
|
||||||
length.
|
|
||||||
3. **Bonus**
|
|
||||||
- How many possible strings consisting of 16 alphanumeric characters can exist?
|
|
||||||
- Add the possibility for a second argument `-v` that indicates your script should be more
|
|
||||||
verbose.
|
|
||||||
- print the security bits ($log_2(L)$ where $L$ is the total number of possibilities) when the
|
|
||||||
`-v` flag is applied
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ python ./randomString.py 60
|
|
||||||
n51uxDLu3BnxZ1D00gYKYRcG2jh1Y6uulHgrJ0TK3w5FtWl6wm8U0azNtxw0
|
|
||||||
# ^^^^ the above is 60 characters ^^^^
|
|
||||||
```
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Hints</summary>
|
|
||||||
|
|
||||||
- Use `random.choice` to generate a random character
|
|
||||||
- build your own alphabet string
|
|
||||||
- Use `sys.argv` to access the CLI Arguments
|
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>Solution</summary>
|
|
||||||
|
|
||||||
Take a look at the provided Code Example.
|
|
||||||
|
|
||||||
[Code Example](src/randomString.py)
|
|
||||||
|
|
||||||
**Bonus**
|
|
||||||
|
|
||||||
There are 62 alphanumeric characters (A-Z), (a-z), (0-9).
|
|
||||||
|
|
||||||
With $N$ characters, there are $62^N$ possible variants.
|
|
||||||
For $N=16$ that's $62^{16} = 47.672.401.706.823.533.450.263.330.816$ possible variants.
|
|
||||||
|
|
||||||
Security people measure security in Bits ($2^x$). You can calculate the bits of security with the
|
|
||||||
logarithm base 2.
|
|
||||||
|
|
||||||
$S = log_2(62^N)$.
|
|
||||||
|
|
||||||
We can immediately see that longer passwords are *exponentially* more secure than
|
|
||||||
more complex passwords (passwords that make use of complicated characters). For each bit, the
|
|
||||||
security of the password is doubled.
|
|
||||||
|
|
||||||
For our example of $N=16$ we can calculate the security of the password like this:
|
|
||||||
|
|
||||||
$S=log_2(62^{16}) \approx 95.27$
|
|
||||||
|
|
||||||
That number of security bits is pretty good for passwords. However it does not cost you anything to
|
|
||||||
just make your passwords longer than that, and give attackers no chance to break them by brute
|
|
||||||
force.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## String Parsing with Regular Expressions
|
|
||||||
|
|
||||||
Difficulty: 2/5
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Text</summary>
|
|
||||||
|
|
||||||
The text is large, read it [here](data/metasyntactic.md) and find the raw text for your program
|
|
||||||
[here](https://git.cscherr.de/PlexSheep/py-basic/raw/branch/master/data/metasyntactic.md).
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
1. Use a regular expression (regex) to find all words that start with a lowercase character with a
|
|
||||||
following vowel character, in which no 'x', z' or 'y' follows the vowel in the given Text.
|
|
||||||
It is not allowed to store the text in source code, you must load it from an outside source,
|
|
||||||
such as a file.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
| Original | is Match? |
|
|
||||||
|----------|-----------|
|
|
||||||
| foo | yes |
|
|
||||||
| foobar | yes |
|
|
||||||
| tayfoo | no |
|
|
||||||
| baz | no |
|
|
||||||
| qux | no |
|
|
||||||
| Foo | no |
|
|
||||||
| bAR | yes |
|
|
||||||
| far | yes |
|
|
||||||
|
|
||||||
A hint that you don't want to miss:
|
|
||||||
|
|
||||||
Use [regex101.com](https://regex101.com) if you are not already a REGEX expert.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Hints</summary>
|
|
||||||
|
|
||||||
- use `open()` to open your file for reading.
|
|
||||||
- use the `read()` method to read the file out.
|
|
||||||
- Use the `re` library
|
|
||||||
- Use `\b` to match a word boundary
|
|
||||||
- Use ranges `[5-9]`
|
|
||||||
- You can set a higher precedence by putting things in braces `(ABC)`.
|
|
||||||
- You can connect two expressions with `A|B` to use either `A` or `B`
|
|
||||||
- Use global mode.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>Solution</summary>
|
|
||||||
|
|
||||||
There should be $374$ matches.
|
|
||||||
|
|
||||||
A regex that matches the requirements is `\b[a-z][AEIOUaeiou]([a-w]|[A-W])`.
|
|
||||||
|
|
||||||
[Code Example](src/tasks/regex.py)
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Primitive Cryptography
|
|
||||||
|
|
||||||
This section covers some ancient and / or primitive methods of Cryptography.
|
|
||||||
These are relatively easy to code and give a basic understanding of used
|
|
||||||
concepts.
|
|
||||||
|
|
||||||
### A. The Caesar Cipher
|
|
||||||
|
|
||||||
Difficulty: 2/5
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Text</summary>
|
|
||||||
|
|
||||||
```text
|
|
||||||
Gxhobf bl t kxytvmhk, tgw lhfxmbfxl kxwtvmhk, bg max mktwbmbhg hy Obf (pabva bmlxey wxkboxl ykhf
|
|
||||||
Lmxobx). Bm bl ghm t kxpkbmx unm t vhgmbgntmbhg tgw xqmxglbhg hy Obf. Ftgr vehgxl tgw wxkbotmboxl
|
|
||||||
xqblm, lhfx oxkr vexoxk—unm ghgx tkx Obf. Gxhobf bl unbem yhk nlxkl pah ptgm max zhhw itkml hy
|
|
||||||
Obf, tgw fhkx.
|
|
||||||
````
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
1. The text above has been cyphered with the Caesar cipher, a timeless,
|
|
||||||
classical algorithm that abstracts the meaning of text away and arguably
|
|
||||||
an early form of encryption. Your task is to decipher it back into readable
|
|
||||||
text.
|
|
||||||
2. **Bonus**
|
|
||||||
- What if you didn't just try all possible combinations? How could you find
|
|
||||||
the key without trying until you find it?
|
|
||||||
|
|
||||||
**The cipher**
|
|
||||||
|
|
||||||
For the Caesar cipher, all letters are shifted by the value of the key.
|
|
||||||
|
|
||||||
**Examples**
|
|
||||||
|
|
||||||
`foo Bar` becomes `gpp Cbs` when shifted by $1$.
|
|
||||||
|
|
||||||
Try to find out the rest for yourself.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Hints</summary>
|
|
||||||
|
|
||||||
- You can use the `ascii` codes of the letters to your advantage.
|
|
||||||
- You need to distinguish between lower and upper case.
|
|
||||||
- To roll back from back from a too high index back into the range of real
|
|
||||||
letters. To do that you can use the modulo operation, which computes the
|
|
||||||
remainder of a division by x. This is actually finite field arithmetic,
|
|
||||||
but don't get so deep into the math.
|
|
||||||
- It is handy to have a command line argument for key and source text.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>Solution</summary>
|
|
||||||
|
|
||||||
I ciphered the text with the key $19$. The original, deciphered text is:
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Text</summary>
|
|
||||||
|
|
||||||
```text
|
|
||||||
Neovim is a refactor, and sometimes redactor, in the tradition of Vim (which itself derives from
|
|
||||||
Stevie). It is not a rewrite but a continuation and extension of Vim. Many clones and derivatives
|
|
||||||
exist, some very clever—but none are Vim. Neovim is built for users who want the good parts of
|
|
||||||
Vim, and more.
|
|
||||||
````
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
To decipher, you just apply the shifting of number backwards, or with the key
|
|
||||||
$-19$ (that's the same thing!).
|
|
||||||
|
|
||||||
[Code Example](src/caesar.py)
|
|
||||||
|
|
||||||
**Bonus**
|
|
||||||
One other way you could try to *recover* the key with is by statistical
|
|
||||||
analysis. Western languages (like English, German, etc.) have some letters,
|
|
||||||
words, combinations of letters, that are more common than others. These follow
|
|
||||||
a [statistical distribution](https://en.wikipedia.org/wiki/Letter_frequency).
|
|
||||||
The letter that is by far the most common in English is `e`.
|
|
||||||
|
|
||||||
With this information, you could count the occurrences for each letter and find
|
|
||||||
that the graph of frequencies looks the same -- only shifted by a couple
|
|
||||||
letters. That difference is your key.
|
|
||||||
|
|
||||||
Another way to try to recover the key is by looking at obvious words. The second
|
|
||||||
word in the cipher text is a single `t`. How many (common) words do you know
|
|
||||||
that only have one letter? I only know `a`. If we calculate the difference,
|
|
||||||
again, we get $19$, which is the key.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Making a Hexeditor
|
|
||||||
|
|
||||||
In this section, we're building a little hexeditor. You will be able to install
|
|
||||||
it on your system and use it instead of the `hexdump` and `xxd` built into most
|
|
||||||
Linux distributions.
|
|
||||||
|
|
||||||
Hexdumping is actually really simple, all you have to do is read a file and
|
|
||||||
print it's direct content interpreted as numbers in hexadecimal. Apply some
|
|
||||||
fancy string formatting and we're done!
|
|
||||||
|
|
||||||
The editing part is a lot harder. It requires us to build a functioning TUI -
|
|
||||||
Terminal User Interface, as working with command line arguments or regular
|
|
||||||
reading from stdin won't help us much for editing a file. (if that's your thing,
|
|
||||||
use `ed`.).
|
|
||||||
|
|
||||||
Note: If you're looking for a great, fully featured hexeditor, I'd recommend
|
|
||||||
`bvi` ("binary vi"), which is packaged by most distributions.
|
|
||||||
|
|
||||||
-> `apt-get install bvi` <-
|
|
||||||
|
|
||||||
Note: I have no Idea how to install a python script as executable on windows, I
|
|
||||||
don't like windows either, so no support for installing stuff on windows.
|
|
||||||
|
|
||||||
### A. Hexdumper
|
|
||||||
Difficulty: 3/5
|
|
||||||
|
|
||||||
1. Dump the data of [data/metasyntactic.md](./data/metasyntactic.md) -- In
|
|
||||||
Hexadecimal.
|
|
||||||
2. Make the dumped Bytes look pretty, something like the example below:
|
|
||||||
3. Make use of command line arguments to add a help option (triggered with `-h` or
|
|
||||||
`--help`) and a `-C` or `--chars` option that adds another section that
|
|
||||||
prints the bytes interpreted as text. Those bytes that have no text
|
|
||||||
representation should be displayed as `.`. You may use the `argparse` library
|
|
||||||
to work with the arguments.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Hexdump Example Display</summary>
|
|
||||||
|
|
||||||
`data/metasyntactic.md` should look like this when hexdumped:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Line Data
|
|
||||||
=================================================
|
|
||||||
0000000 | 6f4e 6574 203a 6854 7369 6920 2073 6874
|
|
||||||
0000010 | 2065 6957 696b 6570 6964 2061 6170 6567
|
|
||||||
0000020 | 6620 726f 6d20 7465 7361 6e79 6174 7463
|
|
||||||
0000030 | 6369 7620 7261 6169 6c62 7365 6920 206e
|
|
||||||
0000040 | 6e45 6c67 7369 2c68 3220 3230 2d33 3930
|
|
||||||
0000050 | 302d 2e35 4620 6e69 2064 6874 0a65 7075
|
|
||||||
0000060 | 7420 206f 6164 6574 6f20 6972 6967 616e
|
|
||||||
0000070 | 206c 685b 7265 5d65 6828 7474 7370 2f3a
|
|
||||||
0000080 | 652f 2e6e 6977 696b 6570 6964 2e61 726f
|
|
||||||
0000090 | 2f67 6977 696b 4d2f 7465 7361 6e79 6174
|
|
||||||
00000a0 | 7463 6369 765f 7261 6169 6c62 2965 0a2e
|
|
||||||
00000b0 | 230a 4d20 7465 7361 6e79 6174 7463 6369
|
|
||||||
00000c0 | 7620 7261 6169 6c62 0a65 230a 2023 6f54
|
|
||||||
00000d0 | 6c6f 0a73 460a 6f72 206d 6957 696b 6570
|
|
||||||
00000e0 | 6964 2c61 7420 6568 6620 6572 2065 6e65
|
|
||||||
00000f0 | 7963 6c63 706f 6465 6169 540a 6968 2073
|
|
||||||
0000100 | 7261 6974 6c63 2065 7369 6120 6f62 7475
|
|
||||||
0000110 | 6d20 7465 7361 6e79 6174 7463 6369 7620
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
And like this when hexdumped with `-C`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Line Data Text
|
|
||||||
======================================================================
|
|
||||||
0000000 | 6f4e 6574 203a 6854 7369 6920 2073 6874 |Note: This is th|
|
|
||||||
0000010 | 2065 6957 696b 6570 6964 2061 6170 6567 |e Wikipedia page|
|
|
||||||
0000020 | 6620 726f 6d20 7465 7361 6e79 6174 7463 | for metasyntact|
|
|
||||||
0000030 | 6369 7620 7261 6169 6c62 7365 6920 206e |ic variables in |
|
|
||||||
0000040 | 6e45 6c67 7369 2c68 3220 3230 2d33 3930 |English, 2023-09|
|
|
||||||
0000050 | 302d 2e35 4620 6e69 2064 6874 0a65 7075 |-05. Find the.up|
|
|
||||||
0000060 | 7420 206f 6164 6574 6f20 6972 6967 616e | to date origina|
|
|
||||||
0000070 | 206c 685b 7265 5d65 6828 7474 7370 2f3a |l [here](https:/|
|
|
||||||
0000080 | 652f 2e6e 6977 696b 6570 6964 2e61 726f |/en.wikipedia.or|
|
|
||||||
0000090 | 2f67 6977 696b 4d2f 7465 7361 6e79 6174 |g/wiki/Metasynta|
|
|
||||||
00000a0 | 7463 6369 765f 7261 6169 6c62 2965 0a2e |ctic_variable)..|
|
|
||||||
00000b0 | 230a 4d20 7465 7361 6e79 6174 7463 6369 |.# Metasyntactic|
|
|
||||||
00000c0 | 7620 7261 6169 6c62 0a65 230a 2023 6f54 | variable..## To|
|
|
||||||
00000d0 | 6c6f 0a73 460a 6f72 206d 6957 696b 6570 |ols..From Wikipe|
|
|
||||||
00000e0 | 6964 2c61 7420 6568 6620 6572 2065 6e65 |dia, the free en|
|
|
||||||
00000f0 | 7963 6c63 706f 6465 6169 540a 6968 2073 |cyclopedia.This |
|
|
||||||
...
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Hints</summary>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Solution</summary>
|
|
||||||
|
|
||||||
[Code Example](./src/hexdumper.py)
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### B. Packaging your hexdumper
|
|
||||||
|
|
||||||
1. Install `pip`, on debian based systems you can do that with `apt-get install
|
|
||||||
python3-pip`.
|
|
|
@ -1,167 +0,0 @@
|
||||||
Note: This is the Wikipedia page for metasyntactic variables in English, 2023-09-05. Find the
|
|
||||||
up to date original [here](https://en.wikipedia.org/wiki/Metasyntactic_variable).
|
|
||||||
|
|
||||||
# Metasyntactic variable
|
|
||||||
|
|
||||||
## Tools
|
|
||||||
|
|
||||||
From Wikipedia, the free encyclopedia
|
|
||||||
This article is about metasyntactic variables in computer science and programming. For metasyntactic
|
|
||||||
variables as used in formal logic, see Metavariable (logic). For usage in spoken languages, see
|
|
||||||
Placeholder name.
|
|
||||||
|
|
||||||
A metasyntactic variable is a specific word or set of words identified as a placeholder in computer
|
|
||||||
science and specifically computer programming. These words are commonly found in source code and are
|
|
||||||
intended to be modified or substituted before real-world usage. For example, foo and bar are used in
|
|
||||||
over 330 Internet Engineering Task Force Requests for Comments, the documents which define
|
|
||||||
foundational internet technologies like HTTP (web), TCP/IP, and email protocols.[1][2]
|
|
||||||
|
|
||||||
By mathematical analogy, a metasyntactic variable is a word that is a variable for other words,
|
|
||||||
just as in algebra letters are used as variables for numbers.[1]
|
|
||||||
|
|
||||||
Metasyntactic variables are used to name entities such as variables, functions, and commands whose
|
|
||||||
exact identity is unimportant and serve only to demonstrate a concept, which is useful for teaching
|
|
||||||
programming.
|
|
||||||
Common metasyntactic variables
|
|
||||||
|
|
||||||
Due to English being the foundation-language, or lingua franca, of most computer programming
|
|
||||||
languages, these variables are commonly seen even in programs and examples of programs written for other spoken-language audiences.
|
|
||||||
|
|
||||||
The typical names may depend however on the subculture that has developed around a given programming
|
|
||||||
language.
|
|
||||||
|
|
||||||
## General usage
|
|
||||||
|
|
||||||
Metasyntactic variables used commonly across all programming languages include foobar, foo, bar,
|
|
||||||
baz, qux, quux, corge, grault, garply, waldo, fred, plugh, xyzzy, and thud; several of these words
|
|
||||||
are references to the game Colossal Cave Adventure.[1][3]
|
|
||||||
|
|
||||||
A complete reference can be found in a MIT Press book titled The Hacker's Dictionary.
|
|
||||||
|
|
||||||
## Japanese
|
|
||||||
|
|
||||||
In Japanese, the words hoge (ほげ)[4] and fuga (ふが) are commonly used, with other common words
|
|
||||||
and variants being piyo (ぴよ), hogera (ほげら), and hogehoge (ほげほげ).[5][circular reference]
|
|
||||||
The origin of hoge as a metasyntactic variable is not known, but it is believed to date to the early
|
|
||||||
1980s.[5]
|
|
||||||
|
|
||||||
## French
|
|
||||||
|
|
||||||
In France, the word toto is widely used, with variants tata, titi, tutu as related placeholders.
|
|
||||||
One commonly-raised source for the use of toto is a reference to the stock character used to tell
|
|
||||||
jokes with Tête à Toto.[citation needed]
|
|
||||||
|
|
||||||
## Turkish
|
|
||||||
|
|
||||||
In Turkey, the words hede and hödö (usually spelt hodo due to ASCII-only naming constraints of
|
|
||||||
programming languages) are well-known metasyntactic variables stemmed from popular humorous cartoon
|
|
||||||
magazines of the 90's like LeMan. The words don't mean anything, and specifically used in place of
|
|
||||||
things that don't mean anything. The terms have been popularized to the masses by the actor and
|
|
||||||
stand-up comedian Cem Yılmaz in the late 90's and early 2000's.[6]
|
|
||||||
|
|
||||||
## Usage examples
|
|
||||||
A screenshot of a metasyntactic variable FOO assigned and echoed in an interactive shell session.
|
|
||||||
|
|
||||||
## C
|
|
||||||
See also: C programming language
|
|
||||||
|
|
||||||
In the following example the function name foo and the variable name bar are both metasyntactic
|
|
||||||
variables. Lines beginning with // are comments.
|
|
||||||
|
|
||||||
```c
|
|
||||||
// The function named foo
|
|
||||||
int foo(void)
|
|
||||||
{
|
|
||||||
// Declare the variable bar and set the value to 1
|
|
||||||
int bar = 1;
|
|
||||||
|
|
||||||
return bar;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## C++
|
|
||||||
See also: C++
|
|
||||||
|
|
||||||
Function prototypes with examples of different argument passing mechanisms:[7]
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void Foo(Fruit bar);
|
|
||||||
void Foo(Fruit* bar);
|
|
||||||
void Foo(const Fruit& bar);
|
|
||||||
|
|
||||||
Example showing the function overloading capabilities of the C++ language
|
|
||||||
|
|
||||||
void Foo(int bar);
|
|
||||||
void Foo(int bar, int baz);
|
|
||||||
void Foo(int bar, int baz, int qux);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Python
|
|
||||||
|
|
||||||
Spam, ham, and eggs are the principal metasyntactic variables used in the Python programming
|
|
||||||
language.[8] This is a reference to the famous comedy sketch, "Spam", by Monty Python, the eponym
|
|
||||||
of the language.[9] In the following example spam, ham, and eggs are metasyntactic variables and
|
|
||||||
lines beginning with # are comments.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Define a function named spam
|
|
||||||
def spam():
|
|
||||||
|
|
||||||
# Define the variable ham
|
|
||||||
ham = "Hello World!"
|
|
||||||
|
|
||||||
# Define the variable eggs
|
|
||||||
eggs = 1
|
|
||||||
|
|
||||||
return
|
|
||||||
```
|
|
||||||
|
|
||||||
## IETF Requests for Comments
|
|
||||||
|
|
||||||
Both the IETF RFCs and computer programming languages are rendered in plain text, making it
|
|
||||||
necessary to distinguish metasyntactic variables by a naming convention, since it would not be
|
|
||||||
obvious from context.
|
|
||||||
|
|
||||||
Here is an example from the official IETF document explaining the e-mail protocols (from RFC 772 -
|
|
||||||
cited in RFC 3092):
|
|
||||||
|
|
||||||
```text
|
|
||||||
All is well; now the recipients can be specified.
|
|
||||||
|
|
||||||
S: MRCP TO:<Foo@Y> <CRLF>
|
|
||||||
R: 200 OK
|
|
||||||
|
|
||||||
S: MRCP TO:<Raboof@Y> <CRLF>
|
|
||||||
R: 553 No such user here
|
|
||||||
|
|
||||||
S: MRCP TO:<bar@Y> <CRLF>
|
|
||||||
R: 200 OK
|
|
||||||
|
|
||||||
S: MRCP TO:<@Y,@X,fubar@Z> <CRLF>
|
|
||||||
R: 200 OK
|
|
||||||
|
|
||||||
Note that the failure of "Raboof" has no effect on the storage of
|
|
||||||
mail for "Foo", "bar" or the mail to be forwarded to "fubar@Z"
|
|
||||||
through host "X".
|
|
||||||
```
|
|
||||||
|
|
||||||
(The documentation for texinfo emphasizes the distinction between metavariables and mere variables
|
|
||||||
used in a programming language being documented in some texinfo file as: "Use the @var command to
|
|
||||||
indicate metasyntactic variables. A metasyntactic variable is something that stands for another
|
|
||||||
piece of text. For example, you should use a metasyntactic variable in the documentation of a
|
|
||||||
function to describe the arguments that are passed to that function. Do not use @var for the names
|
|
||||||
of particular variables in programming languages. These are specific names from a program, so
|
|
||||||
@code is correct for them."[10])
|
|
||||||
|
|
||||||
Another point reflected in the above example is the convention that a metavariable is to be
|
|
||||||
uniformly substituted with the same instance in all its appearances in a given schema. This is in
|
|
||||||
contrast with nonterminal symbols in formal grammars where the nonterminals on the right of a
|
|
||||||
production can be substituted by different instances.[11]
|
|
||||||
Example data
|
|
||||||
SQL
|
|
||||||
|
|
||||||
It is common to use the name ACME in example SQL Databases and as placeholder company-name for the
|
|
||||||
purpose of teaching. The term 'ACME Database' is commonly used to mean a training or example-only
|
|
||||||
set of database data used solely for training or testing. ACME is also commonly used in
|
|
||||||
documentation which shows SQL usage examples, a common practice with in many educational texts as
|
|
||||||
well as technical documentation from companies such as Microsoft and Oracle.[12][13][14]
|
|
|
@ -1,46 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def internal(text: str, key: int) -> str:
|
|
||||||
cyphertext: str = ""
|
|
||||||
for c in text:
|
|
||||||
if ord(c) >= 65 and ord(c) <= 90: # uppercase letters
|
|
||||||
ci = ord(c) - ord('A')
|
|
||||||
add = ord('A')
|
|
||||||
#print(f"{c} is uppercase")
|
|
||||||
elif ord(c) >= 97 and ord(c) <= 122: # uppercase letters
|
|
||||||
ci = ord(c) - ord('a')
|
|
||||||
add = ord('a')
|
|
||||||
#print(f"{c} is lowercase")
|
|
||||||
else:
|
|
||||||
#print(f"not a letter: {c} ({ord(c)})")
|
|
||||||
# character is not a letter, just skip it
|
|
||||||
cyphertext += c
|
|
||||||
continue
|
|
||||||
ci += key
|
|
||||||
ci %= 26 # only 23 letters in the alphabet
|
|
||||||
#print(f"ci for {c}: {ci}")
|
|
||||||
cyphertext += chr(ci + add)
|
|
||||||
|
|
||||||
return cyphertext
|
|
||||||
|
|
||||||
|
|
||||||
if len(sys.argv) <= 2 or len(sys.argv) >= 5:
|
|
||||||
print("Takes two arguments: <SOURCE> <KEY> [-e]")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
source: str = sys.argv[1]
|
|
||||||
target: str = ""
|
|
||||||
key = int(sys.argv[2])
|
|
||||||
|
|
||||||
if len(sys.argv) >= 4 and sys.argv[3] == "-e":
|
|
||||||
print("encrypting...")
|
|
||||||
target = internal(source, -key)
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
print("decrypting...")
|
|
||||||
target = internal(source, key)
|
|
||||||
|
|
||||||
print("=" * 80)
|
|
||||||
print("%s" % target)
|
|
|
@ -1,9 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import sys
|
|
||||||
def fib(n):
|
|
||||||
fibs = [0, 1]
|
|
||||||
for i in range(2, n+1):
|
|
||||||
fibs.append(fibs[i-1] + fibs[i-2])
|
|
||||||
print(fibs)
|
|
||||||
return fibs[n]
|
|
||||||
fib(int(sys.argv[1]))
|
|
|
@ -1,9 +0,0 @@
|
||||||
import sys
|
|
||||||
def small_gaussian_sum(n: int) -> int:
|
|
||||||
return int((n**2 + n) / 2)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
if sys.argv.__len__() < 2:
|
|
||||||
print("provide a natural number as arg")
|
|
||||||
else:
|
|
||||||
print(small_gaussian_sum(int(sys.argv[1])))
|
|
|
@ -1,34 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def greek(path: str):
|
|
||||||
"""replace all semicolons in the given file with Greek question marks"""
|
|
||||||
contents: str = ""
|
|
||||||
with open(path, "r") as file:
|
|
||||||
contents = file.read()
|
|
||||||
contents = contents.replace(";", "\u037e")
|
|
||||||
with open(path, "w") as file:
|
|
||||||
file.write(contents)
|
|
||||||
file.flush()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""
|
|
||||||
Turn all semicolons ';' of the target files into Greek question marks ';'.
|
|
||||||
|
|
||||||
For compilers and interpreters, this is a completely different character,
|
|
||||||
but to humans, it looks the same. The Rust compiler is smart enough to warn
|
|
||||||
us that it only looks like a semicolon. Use more Rust.
|
|
||||||
"""
|
|
||||||
if sys.argv.__len__() < 2:
|
|
||||||
print("provide filepaths as arguments")
|
|
||||||
|
|
||||||
paths: list[str] = []
|
|
||||||
for index, arg in enumerate(sys.argv):
|
|
||||||
if os.path.exists(arg) and os.path.isfile(arg) and index > 0:
|
|
||||||
paths.append(arg)
|
|
||||||
|
|
||||||
for path in paths:
|
|
||||||
greek(path)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
156
src/hexdumper.py
156
src/hexdumper.py
|
@ -1,156 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import io
|
|
||||||
import fcntl # only for non blocking IO, if you dont know what it is, you can ignore it or study up
|
|
||||||
import select # to check if the file has data
|
|
||||||
|
|
||||||
# 2**30 bytes aka 1 Mebibyte
|
|
||||||
MAX_SIZE: int = 0x100000
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def humanbytes(B):
|
|
||||||
"""Return the given bytes as a human friendly KB, MB, GB, or TB string."""
|
|
||||||
B = float(B)
|
|
||||||
KB = float(1024)
|
|
||||||
MB = float(KB ** 2) # 1,048,576
|
|
||||||
GB = float(KB ** 3) # 1,073,741,824
|
|
||||||
TB = float(KB ** 4) # 1,099,511,627,776
|
|
||||||
|
|
||||||
if B < KB:
|
|
||||||
return '{0} {1}'.format(B,'Bytes' if 0 == B > 1 else 'Byte')
|
|
||||||
elif KB <= B < MB:
|
|
||||||
return '{0:.2f} KB'.format(B / KB)
|
|
||||||
elif MB <= B < GB:
|
|
||||||
return '{0:.2f} MB'.format(B / MB)
|
|
||||||
elif GB <= B < TB:
|
|
||||||
return '{0:.2f} GB'.format(B / GB)
|
|
||||||
elif TB <= B:
|
|
||||||
return '{0:.2f} TB'.format(B / TB)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Dump a file"""
|
|
||||||
# arg parsing
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
prog="hd",
|
|
||||||
description="Dumps data as hex"
|
|
||||||
)
|
|
||||||
parser.add_argument("file", nargs='?', type=argparse.FileType('rb'), default=sys.stdin)
|
|
||||||
parser.add_argument("-c", "--chars", action="store_true")
|
|
||||||
parser.add_argument("-f", "--force", action="store_true") # ignore set limits
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# open file
|
|
||||||
try:
|
|
||||||
# Tl;Dr, use this unless you want to do some lower level stuff
|
|
||||||
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|
||||||
#file = open(args.file, "rb")
|
|
||||||
|
|
||||||
|
|
||||||
# the above is sufficient for most regular uses
|
|
||||||
#
|
|
||||||
# some "files" are "lazy" and block the reading process until they have
|
|
||||||
# content, like network connections, fifos, sockets, and so on.
|
|
||||||
|
|
||||||
# the following is a lower level approach to handling these. We
|
|
||||||
# basically call a part of the libc, telling it to open the file
|
|
||||||
# nonblocking. If something blocks, it will simply refuse.
|
|
||||||
#
|
|
||||||
# as far as i know, this only works on UNIX (like) systems. Windows
|
|
||||||
# is the only major exception.
|
|
||||||
|
|
||||||
# make a syscall that will open our file in readonly mode, nonblocking.
|
|
||||||
# if it did not exist and we write to it, it would be created with the
|
|
||||||
# perms: 644 (like `chmod 644 myfile`)
|
|
||||||
fd = args.file.fileno()
|
|
||||||
# now we make the fd into the high level python class `file`
|
|
||||||
file = os.fdopen(fd, "rb")
|
|
||||||
# i read somewhere that file.readline() does not work like this, but as
|
|
||||||
# we are reading binary data anyways, I don't care.
|
|
||||||
# check if the file is readable
|
|
||||||
if not select.select([file, ], [], [], 0.0)[0]:
|
|
||||||
print("no data from stdin, are you trying to dump a file?")
|
|
||||||
parser.print_usage()
|
|
||||||
sys.exit(1)
|
|
||||||
if not file.peek(1):
|
|
||||||
print("File is blocked, trying to wait...")
|
|
||||||
file = open(args.file, "rb")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Could not open file '{args.file}': {e}")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# check if the file has a reasonable size to dump
|
|
||||||
try:
|
|
||||||
file.seek(0, os.SEEK_END)
|
|
||||||
flen = file.tell()
|
|
||||||
file.seek(0, os.SEEK_SET)
|
|
||||||
except io.UnsupportedOperation:
|
|
||||||
# some kinds of "files" like stdin are not seekable
|
|
||||||
flen = 0
|
|
||||||
if 0 != flen > MAX_SIZE:
|
|
||||||
print(f"""The file you are trying to dump is larger than 1M.\n\
|
|
||||||
Actual size: {humanbytes(flen)}\nrefusing to dump""")
|
|
||||||
if (0 != flen > MAX_SIZE) and not args.force:
|
|
||||||
print(f"The file you are trying to dump is larger than {humanbytes(MAX_SIZE)}.\n\n\
|
|
||||||
Actual size: {humanbytes(flen)}\n\nrefusing to dump. You can force dump the file with --force.")
|
|
||||||
sys.exit(2)
|
|
||||||
# print header
|
|
||||||
if args.chars:
|
|
||||||
print("Line Data Text")
|
|
||||||
print('=' * 68)
|
|
||||||
else:
|
|
||||||
print(f"Line Data")
|
|
||||||
print('=' * 48)
|
|
||||||
|
|
||||||
# every line should contain 16 bytes, so we need a loop that get's 16 bytes
|
|
||||||
# and then works with them
|
|
||||||
next: bytes = bytes(16)
|
|
||||||
index: int = 0
|
|
||||||
while len(next) == 16:
|
|
||||||
next = file.read(16)
|
|
||||||
if len(next) == 0:
|
|
||||||
# no data left to read
|
|
||||||
break
|
|
||||||
|
|
||||||
line: str = f"{index:07x} | "
|
|
||||||
|
|
||||||
# actual hexdumping
|
|
||||||
for i in range(16):
|
|
||||||
if i % 2 == 0:
|
|
||||||
if len(next) > i+1:
|
|
||||||
line += f"{next[i]:02x}{next[i+1]:02x} "
|
|
||||||
elif len(next) > i:
|
|
||||||
line += f"{next[i]:02x} "
|
|
||||||
else:
|
|
||||||
line += " "
|
|
||||||
else: continue
|
|
||||||
|
|
||||||
# if chars is enabled, print chars
|
|
||||||
if args.chars:
|
|
||||||
line += "| "
|
|
||||||
for b in next:
|
|
||||||
# special case for newline
|
|
||||||
if b == 0x0a:
|
|
||||||
line+= '' # official unicode symbol representing newlines
|
|
||||||
# only print regular characters
|
|
||||||
elif b > 0x20 and b < 0x7e:
|
|
||||||
line += chr(b)
|
|
||||||
elif b == 0x20:
|
|
||||||
line += '\u2420'
|
|
||||||
else:
|
|
||||||
line += '.'
|
|
||||||
|
|
||||||
print(line)
|
|
||||||
index += 16
|
|
||||||
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# when called directly (like executed from shell)
|
|
||||||
try:
|
|
||||||
main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
# no need for an exception when the user presses ctrl c.
|
|
||||||
sys.exit(0)
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import hashlib
|
|
||||||
import sys
|
|
||||||
to_hash = "foobar19"
|
|
||||||
hashed = hashlib.md5(to_hash.encode())
|
|
||||||
print(hashed.digest().hex())
|
|
|
@ -1,19 +0,0 @@
|
||||||
#!/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)
|
|
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import hashlib
|
|
||||||
BASE: str = "foobar"
|
|
||||||
MAX = 1000000
|
|
||||||
SEARCH = "00"
|
|
||||||
|
|
||||||
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[:2]:
|
|
||||||
count += 1
|
|
||||||
print("%06d | %s" % (i, res))
|
|
||||||
|
|
||||||
|
|
||||||
print(f"\nFound %d digests matching the search" % count)
|
|
|
@ -1,23 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import http.server
|
|
||||||
import io
|
|
||||||
|
|
||||||
TEXT = "Python is not so hard"
|
|
||||||
|
|
||||||
class MyHandler(http.server.SimpleHTTPRequestHandler):
|
|
||||||
def send_head(self) -> io.BytesIO:
|
|
||||||
body = TEXT.encode()
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "text/html; charset=utf-8")
|
|
||||||
self.send_header("Content-Length", str(len(body)))
|
|
||||||
self.end_headers()
|
|
||||||
|
|
||||||
return io.BytesIO(body)
|
|
||||||
|
|
||||||
address = ("127.0.0.1", 8080)
|
|
||||||
srv = http.server.HTTPServer(address, MyHandler)
|
|
||||||
srv.serve_forever()
|
|
||||||
|
|
||||||
# To query your web server go to http://localhost:8080
|
|
||||||
# OR from CLI and with headers:
|
|
||||||
# $ curl localhost:8080 -v
|
|
|
@ -7,7 +7,7 @@ import time
|
||||||
def report_progress(filename, progress):
|
def report_progress(filename, progress):
|
||||||
"""progress: 0-10"""
|
"""progress: 0-10"""
|
||||||
stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
|
stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
|
||||||
stdscr.addstr(1, 0, "Total progress: [{1:20}] {0}%".format(progress * 5, "#" * progress))
|
stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress))
|
||||||
stdscr.refresh()
|
stdscr.refresh()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -16,7 +16,7 @@ if __name__ == "__main__":
|
||||||
curses.cbreak()
|
curses.cbreak()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for i in range(20):
|
for i in range(10):
|
||||||
report_progress("file_{0}.txt".format(i), i+1)
|
report_progress("file_{0}.txt".format(i), i+1)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import math
|
|
||||||
import sys
|
|
||||||
|
|
||||||
alphabet = string.ascii_lowercase
|
|
||||||
alphabet += string.ascii_uppercase
|
|
||||||
alphabet += "0123456789"
|
|
||||||
|
|
||||||
def get_random_string(length):
|
def get_random_string(length):
|
||||||
# choose from all lowercase letter
|
# choose from all lowercase letter
|
||||||
result_str = ''.join(random.choice(alphabet) for i in range(length))
|
letters = string.ascii_lowercase
|
||||||
|
result_str = ''.join(random.choice(letters) for i in range(length))
|
||||||
return result_str
|
return result_str
|
||||||
|
|
||||||
print(get_random_string(int(sys.argv[1])))
|
print(get_random_string(20))
|
||||||
if len(sys.argv) >= 3 and sys.argv[2] == "-v":
|
|
||||||
security = math.log2(len(alphabet)**int(sys.argv[1]))
|
|
||||||
print(f"The alphabets size is {len(alphabet)}")
|
|
||||||
print(f"Security bits: {security}")
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
|
||||||
print("takes only a file path as argument")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
textfile = open(sys.argv[1])
|
|
||||||
text = textfile.read()
|
|
||||||
|
|
||||||
regex = r"\b[a-z][AEIOUaeiou]([a-w]|[A-W])"
|
|
||||||
matches = re.finditer(regex, text, re.MULTILINE)
|
|
||||||
counter = 0
|
|
||||||
for i, match in enumerate(matches, start=1):
|
|
||||||
print(f"{i:03} | \"{match}\"")
|
|
||||||
counter += 1
|
|
||||||
print(f"found {counter}.")
|
|
|
@ -1 +0,0 @@
|
||||||
terminaltexteffects==0.11.0
|
|
|
@ -1,20 +0,0 @@
|
||||||
from terminaltexteffects.effects.effect_burn import Burn
|
|
||||||
text = """
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
"""
|
|
||||||
effect = Burn(text)
|
|
||||||
with effect.terminal_output() as terminal:
|
|
||||||
for frame in effect:
|
|
||||||
terminal.print(frame)
|
|
||||||
|
|
Loading…
Reference in New Issue