It started with a VPN problem
The other day, I had an issue with my VPN and someone from the IT service remotely connected to my machine to put a certificate on it. While he manipulated the certificate manager, he exported a certificate and typed a password of 4 characters that I couldn’t see (characters were obfuscated). Just after that he requested me to use another wifi connection to test the VPN so we had to stop the chat and the remote session. Unfortunatly for me it didn’t work and the guy went to lunch.
So now, I was stuck with no VPN and a certificate which were not working! I decided to delete all the personal certificates having my name from my computer and to re-import the p12 file that the IT guy left on my desktop. I tried to do so but then I was requested to type the password – remember? it was only 4 chars. I tried all the stupid 4 letters password I got in mind (“test”, “1234”, “0000”, “aaaa”, “azer”, “qwert” …) but none of them worked.
Let’s brute force that weak p12 password
So here is the interesting part. I decided to try that very famous thing called “brute force” a password. I was saying in my mind “With my years of programming experience, it should take me 10 minutes to code it and few second to run”.
But actually it took me up to one hour to make the stuff to actually work without obvious bug in C#:
private IEnumerable<string> EnumerateOptions(IList<char> options, int minLength, int maxLength) { var number = new List<int>(maxLength); for (int i = 0; i < minLength; i++) number.Add(0); while (number.Count <= maxLength) { yield return Stringify(number, options); bool overflowed = true; for (int numberPart = number.Count - 1; numberPart >= 0 && overflowed; numberPart--) { number[numberPart]++; if (number[numberPart] >= options.Count) { number[numberPart] = number[numberPart] % options.Count; } else { overflowed = false; } } if (overflowed) number.Insert(0, 0); } } private string Stringify(IList<int> number, IList<char> options) { return string.Join("", number.Select(n => options[n])); }
The result
The app was testing 2k passwords per seconds and found the password in less than 3 minutes 🙂 !
The conclusions are
- don’t use a 4 letters password, obviously, especially on your p12 files which can used to act on your behalf
- coding simple things can take more time than we expect (think hiring interview questions)
- The method I’m using to check the password (X509Certificate2Collection.Import) throws an exception when the password is wrong. This makes the process extremelly slow (15x). When you happen to completely ignore the exception (catch(Exception) with a variable), it becomes reasonably faster if you activate the code optimization (Release mode)
That’s it, the code is on Github. If you happen to spot obvious bugs in the enumerator of passwords, don’t hesitate to let me know with a comment.
I’d like to use this, but I don’t understand how to run the tool. I’m on a Mac, but could also try from a PC. I tried using MS Visual Studio, but I have no idea what I’m doing! Please excuse my utter ignorance.
I’m in a situation where I am trying to update a legacy Android app, but the previous creators of the app have not saved the .p12 password, and my employer is quite annoyed that we might have to create a new app. If I’m able to recover the current production app, it will be extremely helpful!
I appreciate any help you may be able to offer.
Thanks!
Hi Chris,
From Visual Studio, just run the app in “Release” mode with ctrl+F5.
Then, in the password lenght field, leave the minimum to 4 and put the maximum value so 10 or more.
Then run this on a strong computer for a week end.
I don’t want to fool you: this is has little chance to actually find the password because brute forcing a 10 char long password would take a century or two.
Note as well that I’m trying only english lower case chars.
If you want to test upper case and special chars, you have to edit the source code a little bit.
Manitra.
strange that file select button does not work. It seems to act as a stop/go button instead. Also, how can I disable dictionary search? If I empty the dictionary URL, the program crashes.