How can I print/display the "User Principal Name" or UPN of a "p12" certificate on Linux?
The PKCS#12 file usually contains a X.509 certificate and its associated private key. All information is stored in the certificate, so you need to extract it first:
openssl pkcs12 -in foo.p12 -out foo.pem
(foo.pem
will contain both the certificate and the private key.)
The UPN is stored as a special type of "subjectAltName" in the certificate. Unfortunately, OpenSSL does not yet know how to display UPNs (as well as some other types of names), so the usual command for examining certificates (openssl x509 -noout -text < foo.pem
) will not work. Instead, you'll need low-level tools.
Separate the certificate to a file of its own (you can also do this with a text editor):
openssl x509 < foo.pem > foo.cert
Print the certificate as an ASN.1 structure:
openssl asn1parse -i -dump < foo.cert
Find the lines that describe the subjectAltName extension:
742:d=4 hl=3 l= 200 cons: SEQUENCE
745:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Alternative Name
750:d=5 hl=3 l= 192 prim: OCTET STRING [HEX DUMP]:3081BDA036...
And run asn1parse
again, this time telling it to dig deeper into the extension's contents (which are a yet another ASN.1 structure) – in this example, the value ("OCTET STRING" line) starts at offset 750:
openssl asn1parse -i -dump -strparse 750 < foo.cert
Finally, look for the UPN in the dump:
59:d=1 hl=2 l= 40 cons: cont [ 0 ]
61:d=2 hl=2 l= 10 prim: OBJECT :Microsoft Universal Principal Name
73:d=2 hl=2 l= 26 cons: cont [ 0 ]
75:d=3 hl=2 l= 24 prim: UTF8STRING :[email protected]
If you have GnuTLS tools installed, there is a faster way but not as reliable. Once you have the certificate extracted, you can feed it to certtool -i < foo.cert
, and it will print the raw contents even of names it doesn't recognize:
Subject Alternative Name (not critical):
otherName OID: 1.3.6.1.4.1.311.20.2.3
otherName DER: 0c1867726177697479404e554c4c524f5554452e45552e4f5247
otherName ASCII: [email protected]
Look for the OID 1.3.6.1.4.1.311.20.2.3
; it will be followed by the name's raw contents. Luckily, they consist of a single UTF8String, so the "otherName ASCII" output is easily understood – just strip the first two bytes (shown as dots here).
A simpler way would be to just try entering your own Windows login; the UPN is always in the form username@domain
.
(It's a bit sad that out of all tools I've tried, almost none of them know how to interpret such simple and commonly used – even if proprietary – name types.)