org.codice.ddf.commands.util.DigitalSignature.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.commands.util.DigitalSignature.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This 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 any later version.
 *
 * <p>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 Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.ddf.commands.util;

import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PrivilegedAction;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import org.apache.commons.io.IOUtils;
import org.codice.ddf.security.common.Security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DigitalSignature {

    private static final Logger LOGGER = LoggerFactory.getLogger(DigitalSignature.class);

    private static final int BUFFER_SIZE = 1024;

    private static final int OFFSET = 0;

    private KeyStore keyStore;

    public DigitalSignature() {
        Security security = Security.getInstance();
        this.keyStore = AccessController.doPrivileged((PrivilegedAction<KeyStore>) security::getSystemKeyStore);
    }

    public DigitalSignature(KeyStore keyStore) {
        this.keyStore = keyStore;
    }

    public byte[] createDigitalSignature(InputStream data, String alias, String password) throws IOException {
        PrivateKey privateKey = getPrivateKey(alias, password);

        if (privateKey == null) {
            throw new CatalogCommandRuntimeException("Unable to retrieve private key");
        }

        try {
            Signature rsa = Signature.getInstance("SHA256withRSA");

            rsa.initSign(privateKey);

            byte[] buffer = new byte[BUFFER_SIZE];
            int len;

            while ((len = data.read(buffer)) >= 0) {
                rsa.update(buffer, OFFSET, len);
            }

            return rsa.sign();
        } catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException e) {
            String message = "An error occurred while signing file";
            LOGGER.debug(message, e);
            throw new CatalogCommandRuntimeException(message, e);
        }
    }

    public boolean verifyDigitalSignature(InputStream data, InputStream signature, String certificateAlias)
            throws IOException {
        byte[] sigToVerify = IOUtils.toByteArray(signature);

        Certificate certificate = getCertificate(certificateAlias);

        if (certificate == null) {
            throw new CatalogCommandRuntimeException("Unable to retrieve certificate");
        }

        try {
            Signature rsa = Signature.getInstance("SHA256withRSA");
            rsa.initVerify(certificate);

            byte[] buffer = new byte[BUFFER_SIZE];
            int len;

            while ((len = data.read(buffer)) >= 0) {
                rsa.update(buffer, OFFSET, len);
            }

            return rsa.verify(sigToVerify);
        } catch (InvalidKeyException | SignatureException | NoSuchAlgorithmException e) {
            String message = "An error occurred while verifying file";
            LOGGER.debug(message, e);
            throw new CatalogCommandRuntimeException(message, e);
        }
    }

    private PrivateKey getPrivateKey(String alias, String password) {
        try {
            Key key = keyStore.getKey(alias, password.toCharArray());

            if (key instanceof PrivateKey) {
                return (PrivateKey) key;
            }

        } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
            LOGGER.debug("Unable to retrieve private key from key store", e);
        }

        return null;
    }

    private Certificate getCertificate(String alias) {
        try {
            return keyStore.getCertificate(alias);
        } catch (KeyStoreException e) {
            LOGGER.debug("Unable to retrieve certificate from key store", e);
        }

        return null;
    }
}