Class KeyStoreManager
- java.lang.Object
-
- org.faceless.pdf2.viewer2.KeyStoreManager
-
public class KeyStoreManager extends Object
This class is a wrapper around a
KeyStore
, providing high-level management functions and the ability to load and save the KeyStore, selecting the file via a Swing dialog.Each
PDFViewer
should have a KeyStoreManager if it needs to work with digital identities, which in practice means PDFs containing digital signatures (or that will have signatures added) or those encrypted with apublic key
. By default this class works with KeyStores stored in a file, although subclasses aren't bound by this.File-based KeyStores - JKS, JCEKS and PKCS#12
If nothing else is specified, the default
KeyStore
used is a JKS KeyStore loaded from the file${user.home}/.keystore
, which is the default for thekeytool
supplied with the JDK. The path to the file can be changed by setting thefile
parameter, and the password with the "password" parameter. The KeyStoretype
parameter can bejks
(the default, and used forjceks
keystores as well) orpkcs12
if the KeyStore is in PKCS#12 format. Here's how to do this for an applicationjava -Dorg.faceless.pdf2.viewer2.KeyStoreManager.params="type=pkcs12;file=/path/to/file.p12" org.faceless.pdf2.viewer2.PDFViewer
Using the OS X KeyChain as a KeyStore
Certificates and keys stored in the Apple OS X "KeyChain" can be accessed by setting the
provider
parameter to "Apple" and thetype
parameter to "KeychainStore". No other parameters are required. There are some issues with this KeyStore - in particular, at least until OS X 10.6 only the first private key in the KeyStore can be accessed. Here's an example.java -Dorg.faceless.pdf2.viewer2.KeyStoreManager.params=type=KeychainStore\;provider=Apple org.faceless.pdf2.viewer2.PDFViewer
PKCS#11 based Keystores
Since 2.11.14 it's possible to use a PKCS#11 based Hardware Security Module (HSM) as a KeyStore. The attributes supplied to the
sun.security.pkcs11.SunPKCS11
Provider (specified here) can be supplied directly as parameters, and thetype
parameter must be set to "pkcs11". For example, here's how to use a Safenet eToken Pro on Windows as a KeyStore: for an explanation of how to parse the parameters see thesetParameters(java.lang.String)
method.java -Dorg.faceless.pdf2.viewer2.KeyStoreManager.params="type=pkcs11;name=eToken;library='c:\\WINDOWS\\system32\\eTPKCS11.dll';password=1234" org.faceless.pdf2.viewer2.PDFViewer
Alternatively, if you prefer to read the PKCS#11 parameters from a file, specify the file using the "configfile" parameter:
java -Dorg.faceless.pdf2.viewer2.KeyStoreManager.params="type=pkcs11;configfile=pkcs11.cfg" org.faceless.pdf2.viewer2.PDFViewer
The
ManageIdentities
feature is a useful companion to this class and can be used to maintain theKeyStore
, but it's not necessary for this class's operation.This code is copyright the Big Faceless Organization. You're welcome to use, modify and distribute it in any form in your own projects, provided those projects continue to make use of the Big Faceless PDF library.
- Since:
- 2.8.3, but a major rewrite in 2.11
- See Also:
ManageIdentities
,KeyStoreSignatureProvider
,PublicKeyPromptEncryptionHandler
,PDFViewer.getKeyStoreManager()
-
-
Field Summary
Fields Modifier and Type Field Description protected boolean
changed
static FileFilter
FILTER_CERTIFICATE
AFileFilter
that selects anyX.509 Certificate
file.static FileFilter
FILTER_KEYSTORE
AFileFilter
that selects anyKeyStore
filestatic FileFilter
FILTER_KEYSTORE_JKS
AFileFilter
that selects any JKS/JCEKS formatKeyStore
filestatic FileFilter
FILTER_KEYSTORE_PKCS12
AFileFilter
that selects any PKCS#12 formatKeyStore
fileprotected KeyStore
keystore
protected Map<String,String>
params
protected WeakPropertyChangeSupport
propertyChangeSupport
protected PropertyManager
propertymanager
-
Constructor Summary
Constructors Constructor Description KeyStoreManager(PropertyManager propertymanager)
Create a new KeyStoreManager.KeyStoreManager(PDFViewer viewer)
Create a new KeyStoreManager
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addPropertyChangeListener(PropertyChangeListener listener)
Add a Listener to changes to thisKeyStore
.void
cancelKeyStore()
Cancel any changes to the current keystore.boolean
canCreateSelfSignedCertificate()
Return true if this KeyStoreManager has permission to create a new self-signed certificate.boolean
canStoreSecretKeys()
Return true if this KeyStore can store Secret (symmetric) key information.boolean
canStoreSecretKeysOnConversion()
Return true if this KeyStore can store Secret (symmetric) key information, or can be converted to one that can.boolean
contains(Certificate cert)
Indicates whether this key store contains the specified certificate.void
createKeyStore()
Initialize a newKeyStore
for this object to manage.String
createSelfSignedKey(String alias, String name, String unit, String organization, String city, String state, String country, char[] password, int days)
String
createSelfSignedKey(String alias, String name, String unit, String organization, String city, String state, String country, char[] password, int days, String algorithm, int keylength)
Create a newPrivateKey
of the specified algorithm, with self-signedX509Certificate
, and add it to theKeyStore
.void
deleteEntry(String alias)
void
exportCertificate(OutputStream out, String alias)
Export a publicX509Certificate
from theKeyStore
to a DES-encoded Certificate file.void
exportPKCS12Certificate(OutputStream out, String alias, char[] password)
CallbackHandler
getCallbackHandler()
Return the CallbackHandler used by this object to authenticate access to the KeyStore.KeyStore
getKeyStore()
Get theKeyStore
managed by this object - will callloadKeyStore()
if it's not already been called.String
getParameter(String key)
Return a parameter set bysetParameter(java.lang.String, java.lang.String)
SecretKey
getSecret(String alias, String type, char[] password)
Get a secret value from the KeyStore, as set byputSecret()
String
getStoreType()
Get the KeyStore typeString[]
importAllCertificates(File file, String alias)
Import all the X.509 Certificates from the specified file into thisKeyStore
.String[]
importAllCertificates(InputStream in, String alias, String format)
Import all the X.509 Certificates from anInputStream
into theKeyStore
.String
importCertificate(String alias, X509Certificate cert)
Add the specified X.509 Certificate to the list of trusted root certificates.String
importPrivateKey(KeyStore store, String alias, char[] password)
Add aPrivateKey
to theKeyStore
.String
importPrivateKey(PrivateKey key, Certificate[] certs, String alias, char[] password)
Add aPrivateKey
to theKeyStore
.boolean
isCancellable()
Return true if changes to the KeyStore can be cancelled, or false if they're committed immediatelyboolean
isChanged()
Return true if thisKeyStore
is "dirty" and needs to be saved to commit any changes, or false if no changes have been made.boolean
isFileBased()
Return true if the KeyStore is file based, false otherwise.boolean
isKeyPasswordUsed()
Return true if this type of KeyStore uses a per-key password.void
loadKeyStore()
Load theKeyStore
this manager is supposed to work on, based on theparameters
specified.boolean
loadKeyStore(JComponent root)
Create a Swing component prompting the user to load theKeyStore
.void
putSecret(String alias, SecretKey key, char[] password)
Store a secret value in the KeyStore - any data which needs to be password protected.void
removePropertyChangeListener(PropertyChangeListener listener)
Remove a Listener that was previously added inaddPropertyChangeListener(java.beans.PropertyChangeListener)
void
saveKeyStore()
Save theKeyStore
using thesetParameter(java.lang.String, java.lang.String)
parameters specified for this class - for file-based KeyStores like JKS, JCEKS and PKCS#12, this requires thefile
parameter and optionally thepassword
parameter too (if no password is specified, the empty string is used).boolean
saveKeyStore(JComponent root)
Create a Swing compoment prompting the user to save theKeyStore
.void
setCallbackHandler(CallbackHandler callbackHandler)
Set the CallbackHandler used by this object to authenticate access to the KeyStore.void
setParameter(String key, String value)
Set a parameter to be used when loading or saving the KeyStore.void
setParameters(String in)
Set the store parameters.
-
-
-
Field Detail
-
FILTER_KEYSTORE
public static final FileFilter FILTER_KEYSTORE
AFileFilter
that selects anyKeyStore
file- Since:
- 2.11
-
FILTER_KEYSTORE_JKS
public static final FileFilter FILTER_KEYSTORE_JKS
AFileFilter
that selects any JKS/JCEKS formatKeyStore
file- Since:
- 2.11
-
FILTER_KEYSTORE_PKCS12
public static final FileFilter FILTER_KEYSTORE_PKCS12
AFileFilter
that selects any PKCS#12 formatKeyStore
file- Since:
- 2.11
-
FILTER_CERTIFICATE
public static final FileFilter FILTER_CERTIFICATE
AFileFilter
that selects anyX.509 Certificate
file.- Since:
- 2.11
-
propertyChangeSupport
protected WeakPropertyChangeSupport propertyChangeSupport
-
keystore
protected KeyStore keystore
-
propertymanager
protected final PropertyManager propertymanager
-
changed
protected boolean changed
-
-
Constructor Detail
-
KeyStoreManager
public KeyStoreManager(PDFViewer viewer)
Create a new KeyStoreManager- Parameters:
viewer
- the Viewer - must not be null
-
KeyStoreManager
public KeyStoreManager(PropertyManager propertymanager)
Create a new KeyStoreManager. This constructor can be used when no PDFViewer is instantiated.- Parameters:
propertymanager
- the PropertyManager to load properties from - must not be null- Since:
- 2.16
-
-
Method Detail
-
getCallbackHandler
public CallbackHandler getCallbackHandler()
Return the CallbackHandler used by this object to authenticate access to the KeyStore. The default implementation will use the "password"parameter
if specified, otherwise it will prompt with a password dialog.- Since:
- 2.23.5
-
setCallbackHandler
public void setCallbackHandler(CallbackHandler callbackHandler)
Set the CallbackHandler used by this object to authenticate access to the KeyStore.- Since:
- 2.23.5
-
loadKeyStore
public void loadKeyStore() throws IOException, GeneralSecurityException
Load theKeyStore
this manager is supposed to work on, based on theparameters
specified. These will typically include thefile
andpassword
parameters. If the KeyStore cannot be loaded, this method will throw an Exception Subclasses that need to manage their own KeyStore will typically override this method andsaveKeyStore()
.- Throws:
IOException
- if the KeyStore file cannot be accessedGeneralSecurityException
- if the KeyStore cannot be parsed or decoded
-
saveKeyStore
public void saveKeyStore() throws IOException, GeneralSecurityException
Save theKeyStore
using thesetParameter(java.lang.String, java.lang.String)
parameters specified for this class - for file-based KeyStores like JKS, JCEKS and PKCS#12, this requires thefile
parameter and optionally thepassword
parameter too (if no password is specified, the empty string is used).- Throws:
IOException
- if the KeyStore file cannot be saved.GeneralSecurityException
- if the KeyStore cannot be saved for a cryptographic-related reason.
-
setParameters
public void setParameters(String in)
Set the store parameters. The supplied string is a semi-colon delimitered String which contains the parameters that could also be specified individually in calls tosetParameter(java.lang.String, java.lang.String)
. For instance, the following method calls are the same:setParameters("type=pkcs11;name=eToken;library='/usr/lib/libeTPkcs11.so';enabledMechanisms='{CKM_RSA_PKCS CKM_RSA_PKCS_KEY_PAIR_GEN};attributes(*,CKO_PRIVATE_KEY,*)='{\\nCKA_SIGN=true\\nCKA_DECRYPT=true\\n}'"); setParameter("type", "pkcs11"); setParameter("name", "eToken"); setParameter("library", "/usr/lib/libeTPkcs11.so"); setParameter("enabledMechanisms", "{CKM_RSA_PKCS CKM_RSA_PKCS_KEY_PAIR_GEN}"); setParameter("attribute(*,CKO_PRIVATE_KEY,*)", "{\nCKA_SIGN=true\nCKA_DECRYPT=true\n}");
Characters can be quoted or preceded with a backslash to treat them as literals.
If one of the parameters is "configfile", parameters will also be loaded from that file. For example:
setParameters("type=pkcs11;configfile=pkcs11.cfg");
- Since:
- 2.11.14
-
setParameter
public void setParameter(String key, String value)
Set a parameter to be used when loading or saving the KeyStore. Typical parameters includetype The KeyStore type: one of "jks", "jceks", "pkcs12", "pkcs11" or "keychainstore" provider The KeyStore provider file For jks, jceks and pkcs12 KeyStores, the file to save the KeyStore in password The store password for the KeyStore keylength When creating new key pairs, the number of bits to use for the key (default is 2048) sigalg When creating new key pairs, the algorith, to use (default is SHA1withRSA) complete If not-null, the current KeyStore defines the complete list of certificates - the system keystore supplied with Java will not be used to supplement the list of certificates - Since:
- 2.11.14
-
getParameter
public String getParameter(String key)
Return a parameter set bysetParameter(java.lang.String, java.lang.String)
- Since:
- 2.11.14
-
getStoreType
public String getStoreType()
Get the KeyStore type- Since:
- 2.11.21
-
cancelKeyStore
public void cancelKeyStore()
Cancel any changes to the current keystore.
-
createKeyStore
public void createKeyStore() throws GeneralSecurityException
Initialize a newKeyStore
for this object to manage. The KeyStore will use theprovider
andtype
parameters set bysetParameter()
, or the system defaults, to determine the type of store to create.- Throws:
GeneralSecurityException
- if the KeyStore cannot be created.
-
isFileBased
public boolean isFileBased()
Return true if the KeyStore is file based, false otherwise.- Since:
- 2.11.14
-
isCancellable
public boolean isCancellable()
Return true if changes to the KeyStore can be cancelled, or false if they're committed immediately- Since:
- 2.11.14
-
isKeyPasswordUsed
public boolean isKeyPasswordUsed()
Return true if this type of KeyStore uses a per-key password. It is for file-based stores, but isn't for PKCS#11.- Since:
- 2.23.5
-
loadKeyStore
public boolean loadKeyStore(JComponent root)
Create a Swing component prompting the user to load theKeyStore
. The initially selected file is the KeyStore managed by this object, if specified.- Parameters:
root
- the JComponent to position the dialog relative too.- Returns:
- true if a KeyStore was loaded, false otherwise
-
saveKeyStore
public boolean saveKeyStore(JComponent root)
Create a Swing compoment prompting the user to save theKeyStore
. The initially selected file is the KeyStore managed by this object, if specified.- Parameters:
root
- the JComponent to position the dialog relative too.- Returns:
- true if the KeyStore was saved, false otherwise
-
getKeyStore
public KeyStore getKeyStore() throws GeneralSecurityException, IOException
Get theKeyStore
managed by this object - will callloadKeyStore()
if it's not already been called.- Throws:
GeneralSecurityException
IOException
-
isChanged
public boolean isChanged()
Return true if thisKeyStore
is "dirty" and needs to be saved to commit any changes, or false if no changes have been made.
-
importCertificate
public String importCertificate(String alias, X509Certificate cert) throws GeneralSecurityException
Add the specified X.509 Certificate to the list of trusted root certificates.- Parameters:
alias
- the alias to store it under, ornull
to choose onecert
- the X.509 Certificate to store- Returns:
- the name the Certificate was stored under, or
null
if the certificate already existed - Throws:
GeneralSecurityException
- if the Certificate can not be imported
-
importAllCertificates
public String[] importAllCertificates(File file, String alias) throws GeneralSecurityException, IOException
Import all the X.509 Certificates from the specified file into thisKeyStore
. The File may be aKeyStore
file or a file that can be parsed by an X.509CertificateFactory
.- Parameters:
file
- the File containing the X.509 Certificatesalias
- the initial alias for the imports (may benull
)- Returns:
- a list of the aliases the Certificates were stored under
- Throws:
IOException
- if the Certificates can not be read due to File I/O reasonsGeneralSecurityException
- if the Certificates can not be read for a cryptographic reason
-
importAllCertificates
public String[] importAllCertificates(InputStream in, String alias, String format) throws GeneralSecurityException, IOException
Import all the X.509 Certificates from anInputStream
into theKeyStore
. The InputStream is closed on completion.- Parameters:
in
- the InputStream to read the X.509 Certificates fromalias
- if importing from a list of X.509 Certificates the alias to store the Certificate against, ornull
to pick oneformat
- one of "X.509", "JKS" or "pkcs12" to specify the format ofin
- a list of X.509 certificates, a JKS/JCEKS KeyStore or a PKCS#12 KeyStore- Returns:
- a list of aliases added to the KeyStore
- Throws:
IOException
- if the Certificates can not be read due to File I/O reasonsGeneralSecurityException
- if the Certificates can not be read for a cryptographic reason
-
importPrivateKey
public String importPrivateKey(KeyStore store, String alias, char[] password) throws GeneralSecurityException
Add aPrivateKey
to theKeyStore
. The Key is loaded from the specified KeyStore- Parameters:
store
- the KeyStore to load the private key fromalias
- the name the private key is stored underpassword
- the password to access the private key- Throws:
GeneralSecurityException
- if the Key could not be extracted or stored
-
importPrivateKey
public String importPrivateKey(PrivateKey key, Certificate[] certs, String alias, char[] password) throws GeneralSecurityException
Add aPrivateKey
to theKeyStore
.- Parameters:
key
- the Keycerts
- the Certificate chainalias
- a suggestion for the name the private key should be stored underpassword
- the password to encrypt the private key with- Throws:
GeneralSecurityException
- if the Key could not be stored
-
exportPKCS12Certificate
public void exportPKCS12Certificate(OutputStream out, String alias, char[] password) throws GeneralSecurityException, IOException
Export aPrivateKey
and associatedCertificate Chain
from theKeyStore
to a PKCS#12 object. The PKCS#12 object is written to theOutputStream
, and the stream is left open on completion of this method.- Parameters:
out
- the OutputStreamalias
- the alias of the entry to exportpassword
- the password used to access the private key- Throws:
IOException
- if an I/O exception occurs while writingGeneralSecurityException
- if the PrivateKey cannot be extracted from the KeyStore
-
contains
public boolean contains(Certificate cert) throws GeneralSecurityException, IOException
Indicates whether this key store contains the specified certificate.- Parameters:
cert
- the certificate to test- Throws:
GeneralSecurityException
IOException
-
exportCertificate
public void exportCertificate(OutputStream out, String alias) throws GeneralSecurityException, IOException
Export a publicX509Certificate
from theKeyStore
to a DES-encoded Certificate file. The file is written to the specified OutputStream, and the stream is left open on completion of this method.- Parameters:
out
- the OutputStreamalias
- the alias of the entry to export- Throws:
IOException
- if an I/O exception occurs while writingGeneralSecurityException
- if the Certificate cannot be extracted from the KeyStore
-
deleteEntry
public void deleteEntry(String alias) throws GeneralSecurityException
- Parameters:
alias
- the entry to delete- Throws:
GeneralSecurityException
- if the entry cannot be deleted from the KeyStore
-
canStoreSecretKeysOnConversion
public boolean canStoreSecretKeysOnConversion()
Return true if this KeyStore can store Secret (symmetric) key information, or can be converted to one that can.- Since:
- 2.11.22
- See Also:
canStoreSecretKeys()
-
canStoreSecretKeys
public boolean canStoreSecretKeys()
Return true if this KeyStore can store Secret (symmetric) key information.- Since:
- 2.11.21
- See Also:
canStoreSecretKeysOnConversion()
-
putSecret
public void putSecret(String alias, SecretKey key, char[] password) throws GeneralSecurityException, IOException
Store a secret value in the KeyStore - any data which needs to be password protected.- Parameters:
alias
- the aliaskey
- the key to store, or null to delete any secret key with this aliaspassword
- the password that will be used to encrypt this data. if null, the KeyStore password is tried.- Throws:
GeneralSecurityException
IOException
- Since:
- 2.11.21
-
getSecret
public SecretKey getSecret(String alias, String type, char[] password) throws GeneralSecurityException
Get a secret value from the KeyStore, as set byputSecret()
- Parameters:
alias
- the aliaspassword
- the password - if null, the KeyStore password is tried.- Throws:
GeneralSecurityException
- Since:
- 2.11.21
-
createSelfSignedKey
public String createSelfSignedKey(String alias, String name, String unit, String organization, String city, String state, String country, char[] password, int days) throws GeneralSecurityException
- Parameters:
alias
- the alias to store it asname
- the CN of the X.509 certificate DNunit
- the OU of the X.509 certificate DNorganization
- the O of the X.509 certificate DNcity
- the L of the X.509 certificate DNcountry
- the C of the X.509 certificate DNpassword
- the password to store the key withdays
- the number of days the Key is valid for from now.- Returns:
- the alias the new Key is stored under in the KeyStore
- Throws:
GeneralSecurityException
- if something goes wrong
-
createSelfSignedKey
public String createSelfSignedKey(String alias, String name, String unit, String organization, String city, String state, String country, char[] password, int days, String algorithm, int keylength) throws GeneralSecurityException
Create a newPrivateKey
of the specified algorithm, with self-signedX509Certificate
, and add it to theKeyStore
.- Parameters:
alias
- the alias to store it asname
- the CN of the X.509 certificate DNunit
- the OU of the X.509 certificate DNorganization
- the O of the X.509 certificate DNcity
- the L of the X.509 certificate DNcountry
- the C of the X.509 certificate DNpassword
- the password to store the key withdays
- the number of days the Key is valid for from now.algorithm
- the Signature algorithm, eg "SHA1withRSA", "SHA256withRSA", "SHA256withDSA"keylength
- the length of the key in bits, eg 1024, 2048, 4096- Returns:
- the alias the new Key is stored under in the KeyStore
- Throws:
GeneralSecurityException
- if something goes wrong- Since:
- 2.11.14
-
canCreateSelfSignedCertificate
public boolean canCreateSelfSignedCertificate()
Return true if this KeyStoreManager has permission to create a new self-signed certificate.
-
addPropertyChangeListener
public void addPropertyChangeListener(PropertyChangeListener listener)
Add a Listener to changes to thisKeyStore
. APropertyChangeEvent
occurs when a new entry is added or removed from theKeyStore
managed by this KeyStoreManager. Duplicate PropertyChangeListeners are ignored and listeners are held in this class with a weak-reference and so will be removed automatically on garbage collection.- Parameters:
listener
- the Listener.
-
removePropertyChangeListener
public void removePropertyChangeListener(PropertyChangeListener listener)
Remove a Listener that was previously added inaddPropertyChangeListener(java.beans.PropertyChangeListener)
- Parameters:
listener
- a listener
-
-