All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.luminis.quic.client.CertificateSelector Maven / Gradle / Ivy

/*
 * Copyright © 2024 Peter Doornbosch
 *
 * This file is part of Kwik, an implementation of the QUIC protocol in Java.
 *
 * Kwik is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Kwik is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see .
 */
package net.luminis.quic.client;

import net.luminis.quic.log.Logger;
import net.luminis.tls.engine.CertificateWithPrivateKey;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.security.auth.x500.X500Principal;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;


public class CertificateSelector {

    private KeyStore keyStore;
    private final String keyPassword;
    private final Logger log;

    public CertificateSelector(KeyStore keyManager, String keyPassword, Logger log) {
        this.keyStore = keyManager;
        this.keyPassword = keyPassword;
        this.log = log;
    }

    public CertificateWithPrivateKey selectCertificate(List authorities, boolean fallback) {
        CertificateWithPrivateKey result = null;
        try {
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, keyPassword.toCharArray());
            KeyManager keyManager = keyManagerFactory.getKeyManagers()[0];
            if (keyManager instanceof X509ExtendedKeyManager) {
                X509ExtendedKeyManager x509KeyManager = (X509ExtendedKeyManager) keyManager;

                Principal[] issuers = authorities.toArray(new Principal[0]);
                String clientAlias = x509KeyManager.chooseEngineClientAlias(new String[]{"RSA", "EC"}, issuers, null);
                if (clientAlias != null) {
                    X509Certificate certificate = x509KeyManager.getCertificateChain(clientAlias)[0];
                    Key key = x509KeyManager.getPrivateKey(clientAlias);
                    result = new CertificateWithPrivateKey(certificate, (PrivateKey) key);
                }
                else {
                    log.warn("No client certificate found in key store signed by one of the requested authorities: " + authorities);
                }
            }
            else {
                log.warn("Key manager is not an X509ExtendedKeyManager");
            }

            if (result == null && fallback) {
                // Fallback to the first certificate in the key store.
                if (!Collections.list(keyStore.aliases()).isEmpty()) {
                    String alias = Collections.list(keyStore.aliases()).get(0);
                    result = new CertificateWithPrivateKey((X509Certificate) keyStore.getCertificate(alias),
                            (PrivateKey) keyStore.getKey(alias, keyPassword.toCharArray()));
                }
                else {
                    log.error("No client certificate found in key store");
                }
            }
        }
        catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
            log.error("Failed to extract client certificate from key store", e);
        }
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy