001package ca.uhn.hl7v2.hoh.util;
002
003import java.io.BufferedInputStream;
004import java.io.File;
005import java.io.FileInputStream;
006import java.io.FileNotFoundException;
007import java.io.IOException;
008import java.security.Key;
009import java.security.KeyStore;
010import java.security.KeyStoreException;
011import java.security.NoSuchAlgorithmException;
012import java.security.PrivateKey;
013import java.security.UnrecoverableKeyException;
014import java.security.cert.CertificateException;
015import java.util.Enumeration;
016
017public class KeystoreUtils {
018
019        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(KeystoreUtils.class);
020
021        /** non instantiable */
022        private KeystoreUtils() {
023                // nothing
024        }
025
026        public static KeyStore loadKeystore(File theFile, char[] thePassword) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
027                KeyStore keystore = KeyStore.getInstance("JKS");
028                keystore.load(new BufferedInputStream(new FileInputStream(theFile)), thePassword);
029                return keystore;
030        }
031
032        public static KeyStore loadKeystore(String theFile, String theKeystorePassword) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
033                char[] pass = theKeystorePassword != null ? theKeystorePassword.toCharArray() : null;
034                return loadKeystore(new File(theFile), pass);
035        }
036
037        public static boolean validateKeystoreForTlsReceiving(KeyStore theKs) throws KeyStoreException {
038
039                Enumeration<String> aliases = theKs.aliases();
040                boolean foundPrivateKey = false;
041                while (aliases.hasMoreElements()) {
042                        String nextAlias = aliases.nextElement();
043
044                        ourLog.debug("Checking keystore alias: {}", nextAlias);
045
046                        if (theKs.isKeyEntry(nextAlias)) {
047                                ourLog.debug("Found private key: " + nextAlias);
048                                foundPrivateKey = true;
049                        }
050
051                }
052
053                return foundPrivateKey;
054        }
055
056        public static boolean validateKeystoreForSignatureSigning(KeyStore theKs) throws KeyStoreException {
057
058                Enumeration<String> aliases = theKs.aliases();
059                boolean foundPrivateKey = false;
060                while (aliases.hasMoreElements()) {
061                        String nextAlias = aliases.nextElement();
062
063                        ourLog.debug("Checking keystore alias: {}", nextAlias);
064
065                        if (theKs.isKeyEntry(nextAlias)) {
066                                ourLog.debug("Found private key: " + nextAlias);
067                                foundPrivateKey = true;
068                        }
069
070                }
071
072                return foundPrivateKey;
073        }
074
075        public static boolean validateKeystoreForTlsSending(KeyStore theKs) throws KeyStoreException {
076
077                Enumeration<String> aliases = theKs.aliases();
078                boolean foundPublicKey = false;
079                while (aliases.hasMoreElements()) {
080                        String nextAlias = aliases.nextElement();
081
082                        ourLog.debug("Checking keystore alias: {}", nextAlias);
083
084                        if (theKs.isCertificateEntry(nextAlias)) {
085                                ourLog.debug("Found public key: " + nextAlias);
086                                foundPublicKey = true;
087                        }
088
089                }
090
091                return foundPublicKey;
092        }
093
094        public static boolean validateKeystoreForSignatureVerifying(KeyStore theKs) throws KeyStoreException {
095
096                Enumeration<String> aliases = theKs.aliases();
097                boolean foundPublicKey = false;
098                while (aliases.hasMoreElements()) {
099                        String nextAlias = aliases.nextElement();
100
101                        ourLog.debug("Checking keystore alias: {}", nextAlias);
102
103                        if (theKs.isCertificateEntry(nextAlias)) {
104                                ourLog.debug("Found public key: " + nextAlias);
105                                foundPublicKey = true;
106                        }
107
108                }
109
110                return foundPublicKey;
111        }
112
113
114        public static boolean validateKeyForSignatureSigning(KeyStore theKeystore, String theKeyAlias, String theKeyPassword) {
115                Validate.notNull(theKeystore, "Keystore");
116                Validate.notBlank(theKeyAlias, "Key Alias");
117                Validate.notNull(theKeyPassword, "Key Password");
118                
119                Key key;
120                try {
121                        key = theKeystore.getKey(theKeyAlias, theKeyPassword.toCharArray());
122                } catch (UnrecoverableKeyException e) {
123                        ourLog.debug("Failed to recover key", e);
124                        return false;
125                } catch (KeyStoreException e) {
126                        ourLog.debug("Failed to recover key", e);
127                        return false;
128                } catch (NoSuchAlgorithmException e) {
129                        ourLog.debug("Failed to recover key", e);
130                        return false;
131                }
132                
133                if (key == null) {
134                        ourLog.debug("Key is null");
135                        return false;
136                } else if (!(key instanceof PrivateKey)) {
137                        ourLog.debug("Key is of type: {}", key.getClass());
138                        return false;
139                }
140                
141                return true;
142        }
143
144        /**
145         * Returns <code>true</code> if the key can be recovered using the given password
146         */
147        public static boolean canRecoverKey(KeyStore theKeystore, String theKeyAlias, String theKeyPassword) {
148                Validate.notNull(theKeystore, "Keystore");
149                Validate.notBlank(theKeyAlias, "Key Alias");
150                Validate.notNull(theKeyPassword, "Key Password");
151
152                try {
153                        Key key = theKeystore.getKey(theKeyAlias, theKeyPassword.toCharArray());
154                        return key != null;
155                } catch (UnrecoverableKeyException e) {
156                        ourLog.debug("Failed to recover key", e);
157                        return false;
158                } catch (KeyStoreException e) {
159                        ourLog.debug("Failed to recover key", e);
160                        return false;
161                } catch (NoSuchAlgorithmException e) {
162                        ourLog.debug("Failed to recover key", e);
163                        return false;
164                }
165                
166        }
167
168}