Saturday, April 29, 2017

Using KeePass with Multi Cert Key Provider plugin

I love the KeePass password managing tool, and I love the "Multi Cert Key Provider" plugin for it by Dirk Heitzmann, which allows opening the encrypted KeePass file with one or many certificates. It's very useful for sharing passwords and other sensitive data among members of a small team - everyone has his own cert and decrypts the file with his own key.

Unfortunately, the plugin is too picky: it demands that each certificate used with it would have "Data Encipherment" purpose listed in "Key usage" field. If it hasn't, the plugin just ignores the cert.

Until not so long ago, personal e-mail certificates issued by StartCom included this purpose in "Key Usage". But recently StartCom changed that - their certs now only  have "Digital Signature" and "Key Encipherment" extensions.

Of course, I could just create self-signed or internal-CA-signed certificate with any extensions I need, but why add one more cert, when I already have several?

So I just modified the plugin a bit. That's how it's done.

  1. Download the plugin source from here.
  2. Edit the keyfileClass4plugin.cs file, specifically the RSASelectCertificate() function:

public Boolean RSASelectCertificate()
    X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
    X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
    fcollection = (X509Certificate2Collection)fcollection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DataEncipherment, true);
    X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Certificate Select", "Select a certificate from the following list", X509SelectionFlag.SingleSelection);
    if (scollection.Count == 0)
        throw new ArgumentOutOfRangeException("ERROR : No certificate selected.");
    if (!scollection[0].HasPrivateKey)
        throw new CryptographicException("ERROR : Certificate contains no private key.");
    p_DecryptRSACert = scollection[0];
    return true;

Change two lines:
  • replace the new X509Store("MY", StoreLocation.CurrentUser) line by new X509Store("KeePass", StoreLocation.CurrentUser).
  • Comment out this line:
    fcollection = (X509Certificate2Collection)fcollection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DataEncipherment, true);
Now build the MultiCertKeyProvider.dll file from these source files and drop it to the KeePass Plugins folder.

Why replacing the default "MY" store (which is synonymous to "Personal" folder in certmgr.msc) by "KeePass" store? Just because there may be several certificates in "Personal", and choosing between one of them each time you want to open a KeePass file is tiresome and unnecessary. 
So we can copy our certificate into another folder, where it will reside along.

But before that, of course, we need to create it. It's done with this command:
makecert -sr CurrentUser -ss KeePass
It's created with some default cert in it - use certmgr.msc to delete it and then just copy your KeePass cert from "Personal" to "KeePass" store. It can reside it two places while referencing the same private key.

That's all, mischief managed. :-)

No comments:

Post a Comment