P12Breaker.java

/*
 * Copyright (C) 2019 sw4j.org
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.sw4j.tool.p12breaker.breaker;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Uwe Plonus
 */
public class P12Breaker {

    private final Logger logger = Logger.getLogger(P12Breaker.class.getName());

    private final InputStream p12Stream;

    private final char[] password;

    private final PasswordResultListener listener;

    private ErrorType errorType;

    private boolean errorOccured = false;

    private boolean passwordCorrect = false;

    private Exception errorCause;

    public P12Breaker(final InputStream p12Stream, final char[] password, final PasswordResultListener listener) {
        this.p12Stream = p12Stream;
        this.password = password;
        this.listener = listener;
    }

    public void testPassword() {
        logger.fine(String.format("Testing password %s", String.valueOf(password)));
        KeyStore ks;
        try {
            ks = KeyStore.getInstance("pkcs12");
        } catch (KeyStoreException ksex) {
            logger.warning(String.format("KeyStoreException occured for password %s", String.valueOf(password)));
            errorOccured = true;
            errorType = ErrorType.PKCS12_UNKNOWN;
            errorCause = ksex;
            return;
        }
        try {
            ks.load(p12Stream, password);
        } catch (IOException ioex) {
            if (ioex.getCause() instanceof UnrecoverableKeyException) {
                logger.fine(String.format("Password %s incorrect", String.valueOf(password)));
                passwordCorrect = false;
            } else {
                logger.log(Level.WARNING,
                        String.format("IOException occured for password %s", String.valueOf(password)),
                        ioex);
                errorOccured = true;
                errorType = ErrorType.IO_ERROR;
                errorCause = ioex;
            }
            return;
        } catch (NoSuchAlgorithmException nsaex) {
            logger.warning(String.format("NoSuchAlgorithmException occured for password %s", String.valueOf(password)));
            errorOccured = true;
            errorType = ErrorType.ALGORITHM_ERROR;
            errorCause = nsaex;
            return;
        } catch (CertificateException cex) {
            logger.warning(String.format("CertificateException occured for password %s", String.valueOf(password)));
            errorOccured = true;
            errorType = ErrorType.CERTIFICATE_ERROR;
            errorCause = cex;
            return;
        }
        logger.fine(String.format("Password %s correct", String.valueOf(password)));
        passwordCorrect = true;
        listener.passwordFound(String.valueOf(password));
    }

    public ErrorType getErrorType() {
        return errorType;
    }

    public boolean hasErrorOccured() {
        return errorOccured;
    }

    public boolean isPasswordCorrect() {
        return passwordCorrect;
    }

    public Exception getErrorCause() {
        return errorCause;
    }


    public enum ErrorType {

        PKCS12_UNKNOWN,
        IO_ERROR,
        ALGORITHM_ERROR,
        CERTIFICATE_ERROR;

    }


    public interface PasswordResultListener {

        void passwordFound(String password);

    }

}