Package: sillypass
sillypassIdeally, services would allow you to choose any arbitrary string of characters as your password. Unfortunately, though, some impose silly restrictions such as requiring at least one letter, one number, and one symbol, where the symbol must be one of!@#$^. Or they limit you to a small number of characters, such as 12 or even 8.sillypassis a Python package and command-line tool that generates random passwords meeting these silly restrictions.InstallationTo runsillypassas a command-line script, the recommended installation method is throughpipx:pipx install sillypass.To usesillypassas a package in your project, install it to your virtual environment withpip install sillypass. It will also be available as a command-line script in your virtual environment.Usage from the command lineYou can runsillypasswithout arguments to produce a decent general-purpose password. Or you can provide arguments to change the password length or require specific character groups (such as digits) to appear a minimum number of times. Runsillypass --helpfor a description of all available arguments.ExamplesWith no arguments,sillypassgenerates a password containing 24 characters chosen randomly from ASCII letters, digits, and punctuation characters. The resulting password is printed to standard output. For example:$ sillypass
<O^Ljc+[9#-a{(Lm-&c`;flZDoes your service require fewer characters?$ sillypass --length 12
UX\k#LMpqJDRDoes your service require at least one uppercase letter, one lowercase letter, and one digit?$ sillypass --min-upper 1 --min-lower 1 --min-digits 1
4f5NUp]1Ih=86*+,$g77F.YjDoes your service require at least one symbol, but the symbol is limited to a small set of characters?$ sillypass --min-symbols 1 --symbols "@#$%_"
6I_@vyFs6mdK6UBv0IY6I#mADoes your service prohibit symbols?$ sillypass --symbols ""
dcCnIqcbohv5rBPbpiPiS3WEDoes your service limit you to uppercase and lowercase ASCII letters only?$ sillypass --length 24 --min-letters 24
JwzDWLZDeyHXFsSPmsZqaDiILimitations and workaroundssillypasscan't accommodate every potential restriction a service may place on your password. In these cases, it's usually pretty easy to work around this by generating a less restrictive password withsillypassand then editing it by hand afterwards.Does your service limit your password to no more than 2 symbols?sillypasshandles minimum-count requirements well, but it doesn't support maximum-count requirements. The easiest approach here is probably to generate a longer password than you want and then delete any extra symbols:$ sillypass --length 32
bHc@SrFX0F6kEO(rj!ByHy3v0E^J&X}]And then edit it down tobHc@SrFX0F6kEO(rjByHy3v0. A more automated approach would be to make sure the minimum counts of each character group add up to the total length, implying that the minimum counts will be the exact counts:$ sillypass --length 24 --min-letters 18 --min-digits 4 --min-symbols 2
vrAIYy&YTHQL9x0[Dg7hSQi0Does your service require your password to start with a letter?sillypassdoesn't support positional restrictions like this. The easiest approach is probably to keep generating passwords until you get one that starts with a letter. A more direct approach (but longer to type) would be to combine two calls tosillypass:$ echo $(sillypass --length 1 --min-letters 1)$(sillypass --length 23)
Y:vI$F_MT]K5wfyT/WNymdLXUsage as an imported packageYou can usesillypassin your Python project by importing it as a package. It is a very simple package, exposing two functions:create_password()create_counts()and a set of pre-defined character groups:LETTERSUPPERCASELOWERCASEDIGITSSYMBOLSUsecreate_passwordto generate a random string containing a specified number of characters from various character groups. For example:import secrets
from sillypass import create_password

rng = secrets.SystemRandom()

counts = {
    "abc": 5,
    "123456": 1,
    "@": 1,
}

password = create_password(counts=counts, rng=rng)would create a password with 7 characters, 5 of which are chosen from "a", "b", or "c" (repeating the same character multiple times is allowed); 1 of which is chosen from "1", "2", "3", "4", "5", or "6"; and 1 of which would be "@".Usecreate_countsto create a dictionary suitable for passing tocreate_password. It accepts parameters that mimic the command-line script. For example:from sillypass import create_counts

counts = create_counts(
    length=24,
    min_upper=1,
    min_lower=1,
    min_digits=1,
)would create the following dictionary:{
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ": 1,
    "abcdefghijklmnopqrstuvwxyz": 1,
    "0123456789" 1,
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~": 21,
}That last entry is the "remainder" group, formed by the union of letters, digits, and symbols by default. (You can provide your own remainder group with theremainderargument.) Its count is computed to pad the length to the total desired length.