Compare commits
40 Commits
curses-sto
...
master
Author | SHA1 | Date |
---|---|---|
Christoph J. Scherr | f79b8b5d4d | |
Christoph J. Scherr | 4241cf5260 | |
Christoph J. Scherr | 564b0cd011 | |
Christoph J. Scherr | 95866bca81 | |
Christoph J. Scherr | a80c723a32 | |
Christoph J. Scherr | 3465c56c2e | |
Christoph J. Scherr | f12c1141eb | |
Christoph J. Scherr | 2e39e89f37 | |
Christoph J. Scherr | 502851d027 | |
Christoph J. Scherr | bc159a2d24 | |
Christoph J. Scherr | bf9a01d7ba | |
Christoph J. Scherr | 61dbf7a500 | |
Christoph J. Scherr | 778abfa7cc | |
Christoph J. Scherr | 8e31d1063f | |
Christoph J. Scherr | 883e9c94ec | |
Christoph J. Scherr | e296d8f97d | |
Christoph J. Scherr | afade771fa | |
Christoph J. Scherr | 06194f0903 | |
Christoph J. Scherr | 7d1c18101a | |
Christoph J. Scherr | 2e23190dfe | |
Christoph J. Scherr | 07f2a5d728 | |
Christoph J. Scherr | 0a7021255c | |
Christoph J. Scherr | d7dbefc851 | |
Christoph J. Scherr | 90535e3237 | |
Christoph J. Scherr | 25ddac10df | |
Christoph J. Scherr | 7f7cd3677d | |
Christoph J. Scherr | 0a8f6e5b53 | |
Christoph J. Scherr | 5ce6e095bc | |
Christoph J. Scherr | 55ddaafdc7 | |
Christoph J. Scherr | f0ec2e26ce | |
Christoph J. Scherr | 3106a55d8e | |
Christoph J. Scherr | 2297220759 | |
Christoph J. Scherr | fa615d8321 | |
Christoph J. Scherr | ecfc98be04 | |
Christoph J. Scherr | 426c456e1c | |
Christoph J. Scherr | 2d4141937a | |
Christoph J. Scherr | d3483e229e | |
Christoph J. Scherr | 207673382f | |
Christoph J. Scherr | 2c7f6fc759 | |
Christoph J. Scherr | 7c437fb759 |
4
TODO.md
4
TODO.md
|
@ -1,4 +0,0 @@
|
||||||
# Things i would like to add to this repository
|
|
||||||
Caesar-encryption, decryption, brute force
|
|
||||||
calculate determinante (german, idk the english word) of a matrix
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
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
|
|
@ -0,0 +1,489 @@
|
||||||
|
# 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`.
|
|
@ -0,0 +1,167 @@
|
||||||
|
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]
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/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)
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/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]))
|
|
@ -0,0 +1,9 @@
|
||||||
|
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])))
|
|
@ -0,0 +1,34 @@
|
||||||
|
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()
|
|
@ -0,0 +1,156 @@
|
||||||
|
#!/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)
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import hashlib
|
||||||
|
import sys
|
||||||
|
to_hash = "foobar19"
|
||||||
|
hashed = hashlib.md5(to_hash.encode())
|
||||||
|
print(hashed.digest().hex())
|
|
@ -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)
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/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)
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/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:10}] {0}%".format(progress * 10, "#" * progress))
|
stdscr.addstr(1, 0, "Total progress: [{1:20}] {0}%".format(progress * 5, "#" * 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(10):
|
for i in range(20):
|
||||||
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,12 +1,20 @@
|
||||||
#!/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
|
||||||
letters = string.ascii_lowercase
|
result_str = ''.join(random.choice(alphabet) for i in range(length))
|
||||||
result_str = ''.join(random.choice(letters) for i in range(length))
|
|
||||||
return result_str
|
return result_str
|
||||||
|
|
||||||
print(get_random_string(20))
|
print(get_random_string(int(sys.argv[1])))
|
||||||
|
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}")
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/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}.")
|
|
@ -0,0 +1 @@
|
||||||
|
terminaltexteffects==0.11.0
|
|
@ -0,0 +1,20 @@
|
||||||
|
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