Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PKCS12 Certificates and Private Keys

125 views
Skip to first unread message

joshuaaa

unread,
Jul 31, 2008, 9:46:55 AM7/31/08
to
If I understand correctly, to import a certificate from a .p12 file,
you first have to store the private key on the internal key storage
token before you can import the certificate. Is this correct?

I've been banging my head against the wall for the past couple of days
trying to figure out why I cant import a user certificate from JSS or
Javascript. It wasn't until I repeatedly got NoSuchItemOnToken
exceptions in JSS that it finally clicked, duh.

I've only come across 1 java example that extracts information from a
p12 file and it doesn't look fun! For the sake of limiting the amount
of time that I bang my head against the wall, I figured I'd ask you
folks a few things first.

1) I can remove user certificates from firefox through javascript by
using the XPCOM nsIX509CertDB interface. However, I have not succeeded
yet in importing a p12 file. When I do a CertDB.ImportPKCS12File(null,
cert_file);
it runs fine, asks for the password, I enter the password, and then I
get an alert that reads "Failed to restore the PKCS #12 file for
unknown reasons".

I don't know if this is because the private key is not already stored
in a token, but that doesn't make a whole lot of sense to me, I would
imagine it knows what to do with the p12 file (ie get the certificate
and keys). Can anyone shed some light on this?

2) I know that writing to the database while firefox is running is
bad, but is it only bad when you are adding/removing certificates? The
real question is, will it corrupt the database if firefox is running
and I run a java application that adds a private key to the key
storage token?

3) How does NSS relate a particular private key on a token to a
certificate? Is the process as simple as: open a p12, get the private
key, add private key to token, import certificate and give it
nickname? I would imagine there is more to adding the key to the token
than just passing the key to the token?

I would like to accomplish this through the use of javascript, but jss
is an option if this can be done while the browser is running. If
anyone has done something similar, please get in touch with me.

As always, thanks for the help.

Josh

Nelson B Bolyard

unread,
Jul 31, 2008, 3:23:20 PM7/31/08
to mozilla's crypto code discussion list
joshuaaa wrote, On 2008-07-31 06:46:
> If I understand correctly, to import a certificate from a .p12 file,
> you first have to store the private key on the internal key storage
> token before you can import the certificate. Is this correct?

No. A PKCS#12 file contains (or should contain) both a private key and
the corresponding certificate. When you import it, you import both at
the same time. The only prerequisites to importing a PKCS#12 are:

- The pkcs12 file must contain a "friendly name" (a.k.a. "nickname") for
the certificate that corresponds to the private key, and
- the nickname must not "conflict" with a nickname already in the PKCS#11
token into which you are importing the cert and key.

Let me explain what a "nickname conflict" is. A nickname conflict occurs
when your pkcs12 file has the same nickname as a cert that is already in
the PKCS#11 token into which you are trying to import it, BUT the subject
name of the certificate with that nickname in the PKCS#11 token is not the
same as the subject name of the certificate with that nickname in the
PKCS#12 file.

> I've been banging my head against the wall for the past couple of days
> trying to figure out why I cant import a user certificate from JSS or
> Javascript. It wasn't until I repeatedly got NoSuchItemOnToken
> exceptions in JSS that it finally clicked, duh.

Maybe the wrong thing clicked. :)
But seriously, there is no prerequisite for a private key to already be
imported before importing a PKCS12 file.

Now, if you had a PKCS#11 token that was misbehaving, so that after you
imported a private key (or cert) into it, that private key (or cert)
could not subsequently be found in that token, that could cause the
symptom you describe, I think.

Nelson B Bolyard

unread,
Aug 1, 2008, 1:43:19 AM8/1/08
to mozilla's crypto code discussion list
joshuaaa wrote:
> However, I have not succeeded yet in importing a p12 file. When I do a
> CertDB.ImportPKCS12File(null, cert_file);
> it runs fine, asks for the password, I enter the password, and then I
> get an alert that reads "Failed to restore the PKCS #12 file for
> unknown reasons".

<sigh>. The report of "unknown reasons" is a failing of PSM, the FF code
that provides the GUI for the crypto stuff. NSS *ALWAYS* provides a
reason. PSM just takes a shortcut and says "unknown reasons" instead of
displaying the error string associated with the NSS error code.
I've been trying literally for years to get PSM to report the error string
that NSS provides for all errors, and never report "unknown reasons".
FF3 reports Unknown Reason in fewer circumstances than FF2 did, but it
still reports that in way too many places.

If I could get Mozilla Corporation to fix one thing about PSM, it would
be to stamp out all reports of "unknown reasons", once and for all.

> I don't know if this is because the private key is not already stored
> in a token, but that doesn't make a whole lot of sense to me, I would
> imagine it knows what to do with the p12 file (ie get the certificate
> and keys). Can anyone shed some light on this?

NSS reported a reason. But the GUI didn't bother to pass it on to the user.
All we can do is guess. I'm at least as frustrated about this as you are.

> 2) I know that writing to the database while firefox is running is
> bad, but is it only bad when you are adding/removing certificates?

No. It's always bad.

> 3) How does NSS relate a particular private key on a token to a
> certificate? Is the process as simple as: open a p12, get the private
> key, add private key to token, import certificate and give it
> nickname?

Almost that simple. It also checks to make sure that the pkcs12 file
has a private key that corresponds to at least one of the certs in the
file. If you had a p12 file with a private key and a cert, but the
public key in the cert did not correspond to the private key, that
would fail.

> I would imagine there is more to adding the key to the token
> than just passing the key to the token?

Not much. NSS computes a "key ID" value (the PKCS#11 CKA_ID attribute)
and puts that on both the private key and the cert as it imports them.
The CKA_ID is computed from the public key. That way, later when the
user says "use the private key for this cert", NSS can find the key by
looking for a key with the right CKA_ID value.


>
> I would like to accomplish this through the use of javascript, but jss
> is an option if this can be done while the browser is running. If
> anyone has done something similar, please get in touch with me.

The possibilities are:
- something wrong with the pkcs12 file (e.g. key and cert don't match,
cert lacks a nickname, nickname conflict),
- bug in some code

I'd suggest you start by exporting a private key and cert to a PKCS12 file
from the browser. The browser generally likes the file it makes. :)
Then try importing that.

joshuaaa

unread,
Aug 1, 2008, 4:15:12 PM8/1/08
to

Thanks for the info Nelson. I don't think that the p12 file could be
the problem, everything works fine if I import it manually through the
browser. It's only when I'm using the javascript to import the file
that it fails. I love firefox to death, but very disappointed in the
short comings of PSM. It's extremely frustrating knowing that there is
a problem and having no way to see where it came from or why it
occurred.

Now that I understand the process of how the nicknames work, I wonder
if I'm missing a step in my code. The importPKCS12File() function for
the XPCOM interface i'm using does not take any argument for a
nickname. Neither do the other import certificate functions... what
gives? Are they assigning the nicknames themselves? If I import a
certificate via the certificate manager, what does it assign for the
nickname value?

Here's a code snippet for how I think this *should* work:


netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

netscape.security.PrivilegeManager.enablePrivilege('UniversalFileRead');

const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
const nsLocalFile = "@mozilla.org/file/local;1";
const nsILocalFile = Components.interfaces.nsILocalFile;

var file =
Components.classes[nsLocalFile].createInstance(nsILocalFile);
file.initWithPath("path\to\cert.p12");

var db = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
db.importPKCS12File (null, file );

If anyone is wondering, the first argument for the importPKCS12File
function is the token, which can be null to mean any token. See:
http://www.xulplanet.com/references/xpcomref/ifaces/nsIX509CertDB.html#method_importPKCS12File

I've read a ton of older discussions in this group and haven't come
across anything quite like this, but I did see the importing of a
certificate using the HTTP header: Content-type:application/x-x509-
user-cert. I realize that you can't use a p12 for this (sure would be
nice though), so I used the pem and der versions of the certificate
but got an alert that told me the private key corresponding to that
cert was not in the database and therefore was not imported. I'm
assuming that this is by design, but I'm not sure how it's useful
considering that the key and cert go hand in hand. Obviously I'm
missing something there, forgive my ignorance. Nelson can you explain
this to me?

Nelson B Bolyard

unread,
Aug 1, 2008, 5:59:24 PM8/1/08
to mozilla's crypto code discussion list
joshuaaa wrote:

> Now that I understand the process of how the nicknames work, I wonder
> if I'm missing a step in my code. The importPKCS12File() function for
> the XPCOM interface i'm using does not take any argument for a
> nickname. Neither do the other import certificate functions... what
> gives? Are they assigning the nicknames themselves?

The nickname is a component in the PKCS12 file. Each cert potentially
has its own "friendly name" (nickname) in the pkcs12 file. When you
import a PKCS12 file, NSS uses the nickname in the file. When you export
one or more certs into a PKCS#12 file, it's up to the software that
creates the file to put nicknames into it. NSS puts the nicknames it
already has for the certs into the file.

> If I import a certificate via the certificate manager, what does it assign
> for the nickname value?

When you import a "bare" certificate using PSM's certificate manager,
PSM itself derives a nickname from the cert's subject name. I don't know
the exact algorithm. I think it comes from the O and OU attributes, if any.

> Here's a code snippet for how I think this *should* work:

[snipped]
I can't help you with that.

> I've read a ton of older discussions in this group and haven't come
> across anything quite like this, but I did see the importing of a
> certificate using the HTTP header: Content-type:application/x-x509-
> user-cert.

Yes. That imports a "bare" cert (binary or PEM). The private key
should (must?) be present in some local token already.

> I realize that you can't use a p12 for this (sure would be
> nice though), so I used the pem and der versions of the certificate
> but got an alert that told me the private key corresponding to that
> cert was not in the database and therefore was not imported.

That's what I would have suspected. If I recall correctly, in another (?)
recent thread in this group, someone reported that they tried importing a
user cert for which the private key was not present and it silently failed.
(Or was that this thread?) I certainly didn't expect that.

> I'm assuming that this is by design,

Yes. This method of importing user certs is intended to be used in the
common case where a user has just requested a certificate (and in so
doing generated a key pair, leaving the private key in a local token)
and is now downloading his just-issued cert for that private key.

Years ago, in Netscape Navigator 3, this would display a dialog asking
the user to enter a nickname for his new cert. But we found that users
were no good at picking nicknames, because they didn't understand what
the nickname was intended to differentiate. Users always used "My cert",
which was OK for the first cert, but no good for the second one (typically).
It never occurred to users to use names like "My Verisign Cert" or
"My Thawte cert" or "My Verisign cert for m...@somewhere.net". So,
eventually that dialog was dropped and PSM began to create its own
nicknames. That has worked pretty well for certs from real CAs.
As far as I can recall, it's only been a problem for certs issued by
OpenSSL users, who don't put enough info into the cert's names to be
distinguished names.

Kaspar Brand

unread,
Aug 2, 2008, 2:30:24 AM8/2/08
to dev-tec...@lists.mozilla.org
joshuaaa wrote:
> var file =
> Components.classes[nsLocalFile].createInstance(nsILocalFile);
> file.initWithPath("path\to\cert.p12");

What path name exactly are you using, and on what platform? My guess is
that you're not really stumbling on importPKCS12File(), but on creating
the file object with a proper path name.

If you insert something like "alert(file.exists());" after the
initWithPath call, does it really say "true" then? Are there any
messages in the Error Console? (I would expect
NS_ERROR_FILE_UNRECOGNIZED_PATH or similar.) Under Windows, try
"c:\\path\\to\\cert.p12" or so, that should do the trick.

Kaspar

0 new messages