public class PKCS12
extends java.lang.Object
The PKCS#12 Personal Information Exchange Syntax Standard describes a transfer syntax for personal identity information, including private keys, certificates, miscellaneous secrets, and extensions.
This class can be used for securely storing private key and associated
certificates protected by a password. When
creating
a PKCS12 Object for key
bag and certificate bags by default the iteration count for deriving the
content encryption keys from a password is set to 2000. Using an iteration
count of 2000 provides enhanced security by increasing the cost of brute
force attacks against the private key protection. However, please note that
former browser versions (e.g. Netscape Navigator versions prior 4.5, or MSIE
prior IE 4.0 on Windows NT with SP versions < 4) may not be able to handle
an iteration count value of 2000. In this case you may set
moreSecure
to false
and use constructor
PKCS12(KeyBag keyBag,
CertificateBag[] certificateBags, boolean moreSecure)
to create the PKCS12
object. However, where possible, it is recommended to use an iteration count
value of 2000!
When packing the private key into a KeyBag
and certificates
into cert bags
you can specify
locale key id
and friendly name
attributes. When
assigning key id and friendly name attributes you should take care that the
cert bag that contains a certificate with the public key that belongs to the
private key has the same key id and friendly name as the corresponding key
bag. Although attributes are optional some PKCS#12 implementations expect an
attribute for any bag that is included in a PKCS#12 object. Thus, if you have
more than only one certificate you may assign a friendly name attribute to
each certificate bag , e.g. (we assume that we have a private key and a
certificate chain of two certificates with user certificate at index 0 and ca
cert at index 1):
// the certificate chain; user cert at index 0 X509Certificate[] certs = ...; // get the private key PrivateKey privateKey = ...; // we set the commonName as friendlyName attribute Name subject = (Name)certs[0].getSubjectDN(); String friendlyName = subject.getRDN(ObjectID.commonName); // since SubjectKeyIdentifier is included use it as keyId byte[] keyId = ((SubjectKeyIdentifier)certs[0].getExtension(SubjectKeyIdentifier.oid)).get(); // create key bag KeyBag keyBag = new KeyBag(privateKey, friendlyName, keyId); // cert bags; user cert shall be at index (n-1) CertificateBag[] certBags = new CertificateBag[certs.length]; certBags[0] = new CertificateBag(certs[1]); Name caSubject = (Name)certs[1].getSubjectDN(); certBags[0].setFriendlyName(caSubject.getRDN(ObjectID.commonName)); // this certificate corresponds to the private key: certBags[1] = new CertificateBag(certs[0]); certBags[1].setFriendlyName(friendlyName); certBags[1].setLocalKeyID(keyId); // create PKCS12 object PKCS12 pkcs12 = new PKCS12(keyBag, certBags, false); // encrypt with password char[] password = "test".toCharArray(); pkcs12.encrypt(password); // save to file OutputStream os = ...; pkcs12.writeTo(os); os.close();As you see we have created the certificate bags in a way that the user certificate is located at certBags[n-1]. This certificate bag order is expected by some browser versions. The assignment between private key and corresponding certificate bag is done by locale key id and friendly name attribute to know which certificate belongs to the private key when
opening
the PKCS12 file:
// the stream from which to read the PKCS12 object: InputStream is = ...; // create PKCS12 object PKCS12 pkcs12 = new PKCS12(is); // verify MAC if (!pkcs12.verify(password)) { throw new Exception("Verification error!"); } // dercrypt the PKCS#12 object pkcs12.decrypt(password); // get the private key KeyBag kB = pkcs12.getKeyBag(); PrivateKey pk = kB.getPrivateKey(); // get the certificates CertificateBag[] certBag = pkcs12.getCertificateBags(); java.security.cert.Certificate[] certChain = CertificateBag.getCertificates(certBag); // convert to IAIK certs X509Certificate[] certArray = Util.convertCertificateChain(certChain); // we may want to have the end user cert at index 0 certArray = Util.arrangeCertificateChain(certArray, false); // or we may search the cert belonging to the private key based on the localkeyID attribute X509Certificate endUserCert = null; byte[] localKeyID = kB.getLocalKeyID(); if (localKeyID != null) { // check the cert bags for same locale key id for( int i=0; i < certBag.length; i++ ) { byte[] certID = certBag[i].getLocalKeyID(); if ((certID != null) && (CryptoUtils.equalsBlock(certID,localKeyID))) { endUserCert = certBag[i].getCertificate(); break; } } }
SafeBag
,
AuthenticatedSafe
,
KeyBag
,
CertificateBag
Modifier and Type | Field and Description |
---|---|
protected AuthenticatedSafe[] |
authenticated_safes |
protected int |
mode |
static int |
PASSWORD_INTEGRITY_MODE
The password integrity mode.
|
static int |
PUBLIC_KEY_INTEGRITY_MODE
The public-key integrity mode.
|
Constructor and Description |
---|
PKCS12(ASN1Object obj)
Creates a PKCS#12 object from an ASN1Object.
|
PKCS12(java.io.InputStream is)
Creates a new PKCS#12 object from an InputStream.
|
PKCS12(KeyBag[] keyBags,
CertificateBag[] certificateBags,
boolean moreSecure)
Creates a new PKCS#12 object from the given KeyBags and CertificateBags.
|
PKCS12(KeyBag keyBag,
CertificateBag[] certificateBags)
Creates a new PKCS#12 object from a KeyBag and an array of CertificateBags.
|
PKCS12(KeyBag keyBag,
CertificateBag[] certificateBags,
boolean moreSecure)
Creates a new PKCS#12 object from a KeyBag and an array of CertificateBags.
|
Modifier and Type | Method and Description |
---|---|
protected void |
decode()
Decodes this given PKCS#12 object for parsing the internal structure.
|
void |
decrypt(char[] password)
Uses the provided password to decrypt this PKCS12 object for recovering the
inherent authenticatedSafes.
|
void |
encrypt(char[] password)
Uses the provided password to encrypt the content of this PKCS#12 object.
|
void |
encrypt(char[] password,
AlgorithmID authSafesAlg,
AlgorithmID shroudedKeyBagAlg)
Uses the provided password to encrypt the content of this PKCS#12 object.
|
AuthenticatedSafe[] |
getAuthenticatedSafes()
Returns all AuthenticatesSafes included in this PKCS#12 object for manually
parsing.
|
CertificateBag[] |
getCertificateBags()
Returns an array of all CertificateBags within this PKCS#12 object.
|
KeyBag |
getKeyBag()
Tries to find a KeyBag within all AuthenticatedSafes and returns it.
|
KeyBag[] |
getKeyBags()
Tries to find KeyBags within all AuthenticatedSafes and returns them.
|
void |
setBlockSize(int blockSize)
Sets the block size to be used for encoding the inherent Data package.
|
ASN1Object |
toASN1Object()
Returns this PKCS#12 object as ASN1Object.
|
java.lang.String |
toString()
Returns a string giving some information about this
PKCS12
object. |
boolean |
verify(char[] password)
Verifies the MAC of this PKCS12 object.
|
void |
writeTo(java.io.OutputStream os)
Writes this PKCS#12 object to the specified output stream.
|
public static final int PUBLIC_KEY_INTEGRITY_MODE
public static final int PASSWORD_INTEGRITY_MODE
protected AuthenticatedSafe[] authenticated_safes
protected int mode
public PKCS12(KeyBag keyBag, CertificateBag[] certificateBags) throws PKCSException
moreSecure
to false
and use constructor
PKCS12(KeyBag keyBag,
CertificateBag[] certificateBags, boolean moreSecure)
to create the PKCS12
object. However, where possible, it is recommended to use an iteration
count value of 2000!keyBag
- the SafeBag containing the private keycertificateBags
- the SafeBags containing the users certificate and maybe a chain to
a CAPKCSException
- if the PKCS#12 object can not be created because of an
encoding problem concerning the private key or the
certificatespublic PKCS12(KeyBag keyBag, CertificateBag[] certificateBags, boolean moreSecure) throws PKCSException
moreSecure
is true
the
iteration count for deriving the content encryption keys from a password is
set to 2000. Using an iteration count of 2000 provides enhanced security by
increasing the cost of brute force attacks against the private key
protection. However, please note that former browser versions (e.g.
Netscape Navigator prior version 4.5, or MSIE prior IE 4.0 on Windows NT
with SP versions &lgt; 4) may not be able to handle an iteration count
value of 2000. In this case you may set moreSecure
to
false
. However, where possible, it is recommended to use an
iteration count value of 2000!keyBag
- the SafeBag containing the private keycertificateBags
- the SafeBags containing the users certificate and maybe a chain to
a CAmoreSecure
- if true, an iteration count of 2000 is used for generating the
keys. Take a look at the general class documentation for a
description of this parameter.PKCSException
- if the PKCS#12 object can not be created because of an
encoding problem concerning the private key or the
certificatespublic PKCS12(KeyBag[] keyBags, CertificateBag[] certificateBags, boolean moreSecure) throws PKCSException
moreSecure
is true
the
iteration count for deriving the content encryption keys from a password is
set to 2000. Using an iteration count of 2000 provides enhanced security by
increasing the cost of brute force attacks against the private key
protection. However, please note that former browser versions (e.g.
Netscape Navigator prior version 4.5, or MSIE prior IE 4.0 on Windows NT
with SP versions &lgt; 4) may not be able to handle an iteration count
value of 2000. In this case you may set moreSecure
to
false
. However, where possible, it is recommended to use an
iteration count value of 2000!keyBags
- the key bagscertificateBags
- the certificate bagsmoreSecure
- if true, an iteration count of 2000 is used for generating the
keys. Take a look at the general class documentation for a
description of this parameter.PKCSException
- if the PKCS#12 object can not be created because of an
encoding problem concerning the keys or the certificatespublic PKCS12(java.io.InputStream is) throws java.io.IOException, PKCSParsingException
Use this constructor for creating an object from an InputStream containing a DER encoded PKCS#12 object which was exported from MSIE or Netscape.
is
- the input stream where the object shall be read fromjava.io.IOException
- if the object could not be readPKCSParsingException
- if the object could not be parsedpublic PKCS12(ASN1Object obj) throws PKCSParsingException
Do not use this constructor for supplying authenticatedSafes
and setting the integrity mode. This constructor may be used for parsing an
already existing PKCS12
object, supplied as ASN1Object that
may have been created by calling toASN1Object
.
obj
- the PKCS12 object as ASN1ObjectPKCSParsingException
- if the ASN1Object could not be parsedprotected void decode() throws PKCSParsingException
PKCSParsingException
- if this object can not be parsedpublic void decrypt(char[] password) throws PKCSException
This method may be used for performing the decryption after creating a
PKCS12
object from a file that has been exported from some
platform, e.g.:
PKCS12 pkcs12 = new PKCS12(new FileInputStream("pkcs12.pfx")); pkcs12.decrypt(password);
This method automatically decrypts all inherent
AuthenticatedSafe
objects that have been encrypted with
password-encrypted privacy mode.
The password may even be null
; e.g. if the key has been
exported from Internet Explorer without a password.
password
- the password to decrypt the PKCS#12 object. null
is a
valid password.PKCSException
- if the PKCS#12 object could not be decryptedpublic AuthenticatedSafe[] getAuthenticatedSafes()
public KeyBag getKeyBag()
public KeyBag[] getKeyBags()
public CertificateBag[] getCertificateBags()
public boolean verify(char[] password) throws PKCSException
The MAC is computed by using the HMAC/SHA algorithm based on a secret key
which is derived from pseudo-random integrity key material of 160 bit
length, created with the SHA-1 hash algorithm as proposed by PKCS#12.
The salt value necessary for generating the integrity key is derived from
the macData
, and is the same as has been used when creating
this object.
password
- the password that was used to protect this PKCS#12 objecttrue
if the MAC turns out to be correct,
false
otherwisePKCSException
- if an error occurs during the verification process (e.g. the
inherent DigestInfo
cannot be parsed; or the MAC
computation fails)public void encrypt(char[] password) throws PKCSException
null
; the result is the same as if a
key is exported from Internet Explorer without providing a password.password
- the password for performing privacy encryption and integrity MAC
computation. null
is a valid password.PKCSException
- if the PKCS#12 object could not be encryptedpublic void encrypt(char[] password, AlgorithmID authSafesAlg, AlgorithmID shroudedKeyBagAlg) throws PKCSException
null
; the result is the same as if a
key is exported from Internet Explorer without providing a password.password
- the password for performing privacy encryption and integrity MAC
computation. null
is a valid password.authSafesAlg
- the PBE algorithm to be used to encrypt authenticated safesshroudedKeyBagAlg
- the PBE algorithm to be used to encrypt the shrouded key bagsPKCSException
- if the PKCS#12 object could not be encryptedpublic ASN1Object toASN1Object() throws PKCSException
PKCSException
public void writeTo(java.io.OutputStream os) throws java.io.IOException
This method may be used for writing this PFX object to a file to be imported into some platform, e.g.:
pkcs12.writeTo(new FileOutputStream("pkcs12.pfx"));
java.io.IOException
public void setBlockSize(int blockSize)
blockSize
- the blockSize to be used for Data encoding (default: 1024 for
indefinite constructed OCTET_STRING encoding; if not positive,
definite primitive encoding will be used)public java.lang.String toString()
PKCS12
object.toString
in class java.lang.Object