crackie
A simple, silly library to generate combinations.
I wrote this when I forgot part of a password, and decided to try run ~500,000 combinations on the parts I remembered. It worked! Also I decided to publish it because I had never created a Python package before, so this would learn me something.
Usage
Say you have forgotten a password, but remember the basics of it. For example, you remember that it was made up of two words, with some characters altered.
Let's see how to use this library to try all potential combinations:
# Of course we start with some imports.
# We'll be using `each_possible_combination`
from crackie import each_possible_combination
# And we'll use an external program to test each individual
# combination. We'll call this program with `Popen`.
from subprocess import Popen, DEVNULL
# I forgot my password! I remember it was made up of
# the words "verd" and "uberous". Not sure how I mixed up
# lower and upper case... oh, and there might have been
# some additional spicy characters. It could be `VERDUBEROUS`,
# `V3rd_ubEr0U5`, `v3rd ub3r0U5!`... something along those
# lines.
# This list of lists models the possibilities for each
# character in the password string. First there's a "V",
# not sure if big or small. Then the same with "E", but
# this could instead be a "3"? Etc.
variations = [
["V", "v"],
["E", "e", "3"],
["R", "r"],
["D", "d"],
["", "-", "_", " "],
["U", "u"],
["B", "b", "8"],
["E", "e", "3"],
["R", "r"],
["O", "o", "0"],
["U", "u"],
["S", "s", "5", "$"],
["", "!", "1"],
]
# Provide a way to test each individual combination. In this
# example we want to find out a gpg key, so here's some code
# to make that work. In your case it'll be completely different.
# Or not.
def try_password(password):
p = Popen(
['gpg', '--pinentry-mode', 'loopback', '--decrypt', '--passphrase', password, 'e2e_tests/tmp/cryptext'],
stderr=DEVNULL,
stdout=DEVNULL
)
p.wait()
return p.returncode == 0
# Some printing out to reassure us that the program
# is running. The `count` will increment as we go
# and be shown at the end.
count = 0
print("Testing combinations...")
# This is the actual search for combinations, using
# `each_possible_combination`.
for candidate in each_possible_combination(variations):
# Print out some dots to show progress
print(".", end="", flush=True)
count += 1
# Each variation is given as a list. We'll need it
# as a string.
candidate_string = ''.join(candidate)
# Finally, we check if the combination is good!
# If not, the loop will move on to the next one.
if try_password(candidate_string):
# On success, announce victory and exit.
print(f"\nFound the password: `{candidate_string}`. Tried {count} combinations");
break
Development
This project uses uv. End-to-end tests use Docker.
There is a Makefile with shortcuts to run the tests, as follows:
$ make # Runs pytests, doctests, and end-to-end tests
$ make test # Runs pytests and doctests
$ make test_e2e # Runs end-to-end tests
The so-called "e2e test" extracts the example shown above in this document, and runs it to make sure it reflects reality. It sets up a Docker container with the required tools (GnuPG) and an old-ish version of Python (to ensure compatibility). Perhaps overkill, but for some time the example had some mistakes and I wanted to ensure it didn't happen again.
Release files for crackie 1.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| crackie-1.0.3.tar.gz | 3.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| crackie-1.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 7.6 kB
Release files / crackie-1.0.3.tar.gz
| Download URL | crackie-1.0.3.tar.gz |
|---|---|
| Size | 3.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ff850b4b0efc34bcc078524583eeecd231c4d413de39f04f10856b4d550ab228
|
|
BLAKE2b-256 checksum How to use checksums |
79afab64ef1db80a4ff469927cd0baad0dea1407326ef2b0f33d32920e8d4621
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / crackie-1.0.3-py3-none-any.whl
| Download URL | crackie-1.0.3-py3-none-any.whl |
|---|---|
| Size | 4.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0307b6e695b7705a9b4d008c50c42ce4d1bf8d4c7ad066f9a494c40219944736
|
|
BLAKE2b-256 checksum How to use checksums |
6e092934ec3d63f659debff9d8cf72cf8116bccd922f77f1497c5ce38bb844e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|