Create a script to find the correct password of my old expired key

I forgot the password to my key and since my passwords from 2014 time followed a pattern I have been trying to create a script to attempt a list of passwords in order to find the right one.

Context:
I have an old secret key from years ago, it was created in 2014 and it is expired. I want to decrypt old encrypted files, I have found the old secring.gpg but I have forgotten my password. The GPG keychain lists the correct key and even says “sec/pub” next to it but I don’t know the password. It is listed as having the secret key when doing “gpg --list-secret-keys --keyid-format LONG” but there’s no “[E]” next to it. I’ve been working on this for 2 days, I have replaced the .gnupg folder with the entire folder from 2014, which made the sec of the “sec/pub” show up I think.
(MBP M1 Max, macOS 12.7.6, GPG Keychain 1.4.4)

What I’ve tried:
I have been working with chatgpt to create a script that will try a list of potential passwords against a file that was encrypted by this key. I created a test version on another key where I know the password, and the script successfully found the correct password out of a short list of passwords, it stopped when it successfully decrypts the file and printed the password! See “gpg_passwords_forum.sh” linked below.

Problem:
When I have the script point to the key/file I’m interested in it seems to be guessing lots of passwords but I suspect there is something wrong on the end of interfacing with PGP/GPG. The end result is it saying “no valid password found” which is fine, but I need to know for sure that it’s really trying, I don’t know if it’s really trying to unlock the key.

Questions:
I believe the problem is that the script is not really able to find the right password of that key, how can I really have a script check against the actual key and stop when it finds it, either via trying to decrypt a file? maybe using something like pinentry?
Are there other routes I should think about to brute guess? I know I can promt pinentry to keep asking for the password via importing the secring but it’s too slow.
Would the fact that it’s an old expired key make it so my script would not stop and print the correct pasword?

Here is the script I have so far, it (tries) to run through all the passwords in password_combinations.txt, this . Any guidance/tips would be highly appreciated. :pray:t2:

Hi,

decrypt is not suited for such a test since decrypt tries to convert data to plain text and this can work for unencrypted data (e.g. the output of --store) or simply signed data, or signed and encrypted data. Then you have the signature states, e.g. it is a valid signature or an invalid signature. Each of these actions would require different return codes. So simply checking for success or failure invites bad scripts which might make assumptions like. “If this is symetcrically encrypted and I can decrypt it with my password then I know that the sender also knows that password and I can trust that input”. This is why the return code of decrypt should not be used. The correct way to check the decrypt result would involve parsing status-fd.

But checking for the passphrase can be done with --dry-run and --passwd so this test worked for me with one of my own keys:
echo "mypassword" | gpg --passphrase-fd=0 --pinentry-mode=loopback --dry-run --batch --passwd 00CF2F3FA26D29A7804B2F97AE0F1563575D4C90 && echo "Correct"

As I commented in the gist you would have to just change the test line. Makes it simpler as there is no input and output. Between tests of the script remember to flush the gpg-agent or kill it to avoid caching. (gpgconf --kill all)

1 Like

OK, with chatgpt and your feedback I have created a new script but you’ll have to forgive me for being such a noob; I understand that running the code you put above let’s me manually guess the password, and I hope the new script is doing that with the method you suggest in an automated way but I am not sure.

Questions please:

  1. Is the script set up right now? To know that seeing “no valid password found” really means that none of the list is the password would be amazing progress.

Do you mean swap your 00CF2F3FA26D29A7804B2F97AE0F1563575D4C90 for my key ID? If so, how would I then include that in the script?

  1. When I run “gpg --list-packets ” with a file I want to decrypt later when I hopefully find the password, I get:
    keyid 1AB1E7A23BB73E4D
    This is the subkey not the main key, in the script should put that, right?

  2. Anything else I should consider? Mainly I just want to use your method but put it in my script and I’m not sure how. Thanks so much!

NEW SCRIPT:

Yes replacing the keyid is fine, it needs to be some identifier under which gnupg can uniquely identify your key. Run gpg -K to list all your secret keys there you see the keyid and fingerprint.

To test your script do the following

Generate a new key:
gpg --quick-gen-key foo@bar.baz

Use a password from your file so that you know which password it is and can use it to test your script.
Restart the gpg-agent to clear your password cache (gpgconf --kill all)
And then run the script with foo@bar.baz as the keyid

I think your script looks okay but thats always the problem with chatgpt :wink:

Btw. some time ago I experimented with a custom gpt for GnuPG which might give you some better results as I instructed it to avoid the most common mistakes chatgpt makes when scripting for gnupg: ChatGPT - GASSI GnuPG Assisting Intelligence