Class 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 a public 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 the keytool supplied with the JDK. The path to the file can be changed by setting the file parameter, and the password with the "password" parameter. The KeyStore type parameter can be jks (the default, and used for jceks keystores as well) or pkcs12 if the KeyStore is in PKCS#12 format. Here's how to do this for an application

     java -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 the type 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 the type 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 the setParameters(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 the KeyStore, 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()
    • 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 the KeyStore this manager is supposed to work on, based on the parameters specified. These will typically include the file and password 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 and saveKeyStore().
        Throws:
        IOException - if the KeyStore file cannot be accessed
        GeneralSecurityException - if the KeyStore cannot be parsed or decoded
      • 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 to setParameter(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 include
        typeThe KeyStore type: one of "jks", "jceks", "pkcs12", "pkcs11" or "keychainstore"
        providerThe KeyStore provider
        fileFor jks, jceks and pkcs12 KeyStores, the file to save the KeyStore in
        passwordThe store password for the KeyStore
        keylengthWhen creating new key pairs, the number of bits to use for the key (default is 2048)
        sigalgWhen creating new key pairs, the algorith, to use (default is SHA1withRSA)
        completeIf 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
        For PKCS#11 KeyStores, any of the attributes specified in the Java PKCS#11 Reference Guide may be specified as well.
        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.
      • 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 the KeyStore. 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 the KeyStore. 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
      • isChanged

        public boolean isChanged()
        Return true if this KeyStore 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, or null to choose one
        cert - 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 this KeyStore. The File may be a KeyStore file or a file that can be parsed by an X.509 CertificateFactory.
        Parameters:
        file - the File containing the X.509 Certificates
        alias - the initial alias for the imports (may be null)
        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 reasons
        GeneralSecurityException - 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 an InputStream into the KeyStore. The InputStream is closed on completion.
        Parameters:
        in - the InputStream to read the X.509 Certificates from
        alias - if importing from a list of X.509 Certificates the alias to store the Certificate against, or null to pick one
        format - one of "X.509", "JKS" or "pkcs12" to specify the format of in - 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 reasons
        GeneralSecurityException - if the Certificates can not be read for a cryptographic reason
      • importPrivateKey

        public String importPrivateKey​(KeyStore store,
                                       String alias,
                                       char[] password)
                                throws GeneralSecurityException
        Add a PrivateKey to the KeyStore. The Key is loaded from the specified KeyStore
        Parameters:
        store - the KeyStore to load the private key from
        alias - the name the private key is stored under
        password - the password to access the private key
        Throws:
        GeneralSecurityException - if the Key could not be extracted or stored
      • 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 alias
        key - the key to store, or null to delete any secret key with this alias
        password - the password that will be used to encrypt this data. if null, the KeyStore password is tried.
        Throws:
        GeneralSecurityException
        IOException
        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
        Create a new 2048-bit RSA PrivateKey with self-signed X509Certificate, and add it to the KeyStore.
        Parameters:
        alias - the alias to store it as
        name - the CN of the X.509 certificate DN
        unit - the OU of the X.509 certificate DN
        organization - the O of the X.509 certificate DN
        city - the L of the X.509 certificate DN
        country - the C of the X.509 certificate DN
        password - the password to store the key with
        days - 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 new PrivateKey of the specified algorithm, with self-signed X509Certificate, and add it to the KeyStore.
        Parameters:
        alias - the alias to store it as
        name - the CN of the X.509 certificate DN
        unit - the OU of the X.509 certificate DN
        organization - the O of the X.509 certificate DN
        city - the L of the X.509 certificate DN
        country - the C of the X.509 certificate DN
        password - the password to store the key with
        days - 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 this KeyStore. A PropertyChangeEvent occurs when a new entry is added or removed from the KeyStore 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.