Skip to main content

A simple, silly library to generate combinations

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crackie-1.0.3.tar.gz (3.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

crackie-1.0.3-py3-none-any.whl (4.1 kB view details)

Uploaded Python 3

File details

Details for the file crackie-1.0.3.tar.gz.

File metadata

  • Download URL: crackie-1.0.3.tar.gz
  • Upload date:
  • Size: 3.6 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for crackie-1.0.3.tar.gz
Algorithm Hash digest
SHA256 ff850b4b0efc34bcc078524583eeecd231c4d413de39f04f10856b4d550ab228
MD5 603ad605cec7dd61b374621ead541a78
BLAKE2b-256 79afab64ef1db80a4ff469927cd0baad0dea1407326ef2b0f33d32920e8d4621

See more details on using hashes here.

File details

Details for the file crackie-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: crackie-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 4.1 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for crackie-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 0307b6e695b7705a9b4d008c50c42ce4d1bf8d4c7ad066f9a494c40219944736
MD5 43201a2570dd98ed4bf392c6bf1a9c91
BLAKE2b-256 6e092934ec3d63f659debff9d8cf72cf8116bccd922f77f1497c5ce38bb844e2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page