Reputation: 2252
in the past we used a (windows) package using CryptLib to handle RSA encryption. Now we want to transfer our clients to a new platform where using CryptLib is not preferred. We created everything, and the only thing left is importing the private keys.
The keys are stored in CryptLib's keyset store (pkcs#15). When googling around, most (ten year old) mails state thing like "you don't want that", and "the author deliberately prevents that" etc. No software seems to handle pkcs#15, and security provider library-writers don't want to create support because nobody uses it.
There seems to be only way out: store the private key in pfx / pkcs#12 format. That format is supported far better.
To use pkcs#12, you have to enable a flag and recompile the cryptlib dll. I did that, and am able to call the pkcs#12 routines.
I use a delphi wrapper to the dll to make things readable: // load keyset (p15) from disk ks := TCryptKeyset.Create(CRYPT_KEYSET_FILE, pansichar(fname), CRYPT_KEYOPT_NONE);
// get private key from keyset ks
ck := TCryptKey.GetPrivateKey(ks, CRYPT_KEYID_NAME, pansichar('Key'), fpasswd);
// test write to a p15 store
ks2 := TCryptKeyset.Create(CRYPT_KEYSET_FILE, 'test.p15', CRYPT_KEYOPT_CREATE );
ks2.AddPrivateKey(ck, 'fiets');
// test write to p12 store
ks3 := TCryptKeyset.Create(CRYPT_KEYSET_FILE, 'test.p12', CRYPT_KEYOPT_CREATE );
ks3.AddPrivateKey(ck, 'fiets'); // <--- fails with error
The first test is with writing a p15 store, and that works well (the store created is almost identical to the original one, except of course the password had been changed). But the second write to the p12 store gets an error. If I trace down the source, it has to do with the private key I provide being seen as a certificate. And because no private key is present yet, it fails with the following error.
I hope someone has ever used the pcs#12 features of cryptlib, or knows another way to handle this situation. It's no problem if the solution is in python, php, c#, delphi...
UPDATE 22 april 2014 I have used the C# wrapper of cryptlib self, and rewrote the code (in case the Delphi wrapper caused trouble), but I got the same result :(
static void Main(string[] args)
{
int ks_ptr = 0;
int ks_pvk = 0;
int ks12_ptr = 0;
try
{
Console.WriteLine("Initializing...");
crypt.Init();
Console.WriteLine("Loading keystore");
ks_ptr = crypt.KeysetOpen(crypt.UNUSED, crypt.KEYSET_FILE, "privatekey.key", crypt.KEYOPT_NONE);
Console.WriteLine("Loading private key");
ks_pvk = crypt.GetPrivateKey(ks_ptr, crypt.KEYID_NAME, "Key", pwd);
Console.WriteLine("Creating new keystore");
ks12_ptr = crypt.KeysetOpen(crypt.UNUSED, crypt.KEYSET_FILE, "privatekey.pfx", crypt.KEYOPT_CREATE);
Console.WriteLine("Saving private key");
crypt.AddPrivateKey(ks12_ptr, ks_pvk, "mylittlesecret");
}
catch (CryptException ce)
{
Console.WriteLine("Exception: "+ce.Message);
Console.WriteLine("Status writingkeystore: " + GetStatusFor(ks12_ptr));
}
Console.WriteLine("Done. Press a key to quit.");
Console.ReadKey();
}
UPDATE #2
Looking through the tests, a .p12 IS generated in the tests. With some fiddling also for a brand new .p12 file. But the original key is read from the .p12, so it might contain info that is needed to write the file back... Let check some more...
UPDATE #3 Modified the unittests of cryptlib to get the test private key from my .p15 keystore and then write it to the p12 keystore, but it seems that when setting the private key, an empty pkcs12_info structure is passed to the set item function.
Pfff, I hope somebody has any pointers...
Upvotes: 1
Views: 502