001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2013-2015 ForgeRock AS.
015 */
016
017package org.forgerock.json.jose.utils;
018
019import java.io.FileInputStream;
020import java.io.IOException;
021import java.security.KeyStore;
022import java.security.KeyStoreException;
023import java.security.NoSuchAlgorithmException;
024import java.security.PrivateKey;
025import java.security.PublicKey;
026import java.security.UnrecoverableKeyException;
027import java.security.cert.Certificate;
028import java.security.cert.CertificateException;
029import java.security.cert.X509Certificate;
030
031/**
032 * A class that manages a Java Key Store and has methods for extracting out public/private keys and certificates.
033 *
034 * @since 2.0.0
035 */
036public class KeystoreManager {
037
038    private KeyStore keyStore = null;
039
040    /**
041     * Constructs an instance of the KeystoreManager.
042     *
043     * @param keyStoreType The type of Java KeyStore.
044     * @param keyStoreFile The file path to the KeyStore.
045     * @param keyStorePassword The password for the KeyStore.
046     */
047    public KeystoreManager(String keyStoreType, String keyStoreFile,
048            String keyStorePassword) {
049        loadKeyStore(keyStoreType, keyStoreFile, keyStorePassword);
050    }
051
052    /**
053     * Loads the KeyStore based on the given parameters.
054     *
055     * @param keyStoreType The type of Java KeyStore.
056     * @param keyStoreFile The file path to the KeyStore.
057     * @param keyStorePassword The password for the KeyStore.
058     */
059    private void loadKeyStore(String keyStoreType, String keyStoreFile, String keyStorePassword) {
060        try {
061            keyStore = KeyStore.getInstance(keyStoreType);
062            if (keyStoreFile == null || keyStoreFile.isEmpty()) {
063                throw new KeystoreManagerException("mapPk2Cert.JKSKeyProvider: KeyStore FileName is null, "
064                        + "unable to establish Mapping Public Keys to Certificates!");
065            }
066            FileInputStream fis = new FileInputStream(keyStoreFile);
067            keyStore.load(fis, keyStorePassword.toCharArray());
068        } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
069            throw new KeystoreManagerException(e);
070        }
071    }
072
073    /**
074     * Gets the certificate from the KeyStore with the given alias.
075     *
076     * @param certAlias The Certificate Alias.
077     * @return The Certificate.
078     */
079    public Certificate getCertificate(String certAlias)  {
080        if (certAlias == null || certAlias.length() == 0) {
081            return null;
082        }
083
084        try {
085            return keyStore.getCertificate(certAlias);
086        } catch (KeyStoreException e) {
087            throw new KeystoreManagerException(e);
088        }
089    }
090
091    /**
092     * Gets a X509Certificate from the KeyStore with the given alias.
093     *
094     * @param certAlias The Certificate Alias.
095     * @return The X509Certificate.
096     */
097    public X509Certificate getX509Certificate(String certAlias) {
098        Certificate certificate = getCertificate(certAlias);
099        if (certificate instanceof X509Certificate) {
100            return (X509Certificate) certificate;
101        }
102        throw new KeystoreManagerException("Certificate not a X509 Certificate for alias: " + certAlias);
103    }
104
105    /**
106     * Gets the Public Key from the KeyStore with the given alias.
107     *
108     * @param keyAlias The Public Key Alias.
109     * @return The Public Key.
110     */
111    public PublicKey getPublicKey(String keyAlias) {
112        if (keyAlias == null || keyAlias.isEmpty()) {
113            return null;
114        }
115
116        X509Certificate cert = getX509Certificate(keyAlias);
117        if (cert == null) {
118            throw new KeystoreManagerException("Unable to retrieve certificate for alias: " + keyAlias);
119        }
120        return cert.getPublicKey();
121    }
122
123    /**
124     * Gets the Private Key from the KeyStore with the given alias.
125     *
126     * @param keyAlias The Private Key Alias.
127     * @param privateKeyPassword The private key password
128     * @return The Private Key.
129     */
130    public PrivateKey getPrivateKey(String keyAlias, String privateKeyPassword) {
131
132        if (keyAlias == null || keyAlias.length() == 0) {
133            return null;
134        }
135
136        try {
137            return (PrivateKey) keyStore.getKey(keyAlias, privateKeyPassword.toCharArray());
138        } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
139            throw new KeystoreManagerException(e);
140        }
141    }
142}