I created a nice long passphrase, used it a few times, then forgot it ;) The twist is, I know the general theme and probably almost all of the characters. The perfectionist in me doesn't want to revoke the key or anything like that (and I think I need the passphrase to revoke it anyway, right?). I feel I should be able to have a good go at this by brute-forcing the likely layouts/characters that I've got wrong/mis-typed. I wrote a C program to produce such combinations. Unfortunately I don't have the code to hand (I'll go with the "it's not relevant" excuse for now ;). I also came across some code on the web using GPGME to do exactly this as a proof-of-concept. It had the comment "this could easily be 100 times faster". Problem is, profiling the code shows the bottleneck to be the GPGME call itself. Is this expected, or is it a limitation of GPGME that could be solved using the full library or a dedicated implementation?
How would you go about doing this? Obviously this method is infeasible for any decent unknown passphrase, but I think the key is that I know what I typed without knowing the exact formatting of how I typed it - should be feasible, no?
(and I think I need the passphrase to revoke it anyway, right?)
No, you need the revocation key. Which you should have generated and printed out when you created your key. Then stored it in a safe place, not where someone could use it to revoke your key when you don't want them to.
I've tried to brute-force passwords that I almost remembered, but without success. There are still a lot of permutations, and it takes a lot of rules on what can come after what to narrow it down to a reasonable problem size. I never tried too hard on this, since I luckily have never forgotten my GPG passphrase. Mostly when I've forgotten a password it's a login to a remote machine at the university, and I've never wanted to hammer on the ssh port, or webmail, with my guesses.
Maybe the function you're calling does a lot of setup that is non-key-dependent? So you could speed it up by copying the code out of the library and putting your brute-force loop later on in it.