org.codice.ddf.configuration.migration.CipherUtilsTest.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.configuration.migration.CipherUtilsTest.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.configuration.migration;

import static org.apache.commons.codec.binary.Hex.decodeHex;
import static org.apache.commons.codec.binary.Hex.encodeHex;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeStringToFile;
import static org.junit.Assert.assertThat;

import com.google.common.base.Charsets;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.IOUtils;
import org.codice.ddf.migration.MigrationException;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;

public class CipherUtilsTest extends AbstractMigrationSupport {

    private Path zipPath;
    private Path keyPath;
    private Path checksumPath;

    @Before
    public void setup() throws IOException, NoSuchAlgorithmException {
        zipPath = Paths.get(ddfHome.toString(), "exported", "test.dar");
        keyPath = Paths.get(ddfHome.toString(), "exported", "valid.key");
        checksumPath = Paths.get(ddfHome.toString(), "exported", "valid.checksum");
    }

    @Test
    public void testConstructorDefaultKeyAndChecksumLocations() {
        CipherUtils cipherUtils = new CipherUtils(zipPath);
        assertThat(cipherUtils.getZipPath(), Matchers.equalTo(zipPath));
        assertThat(cipherUtils.getKeyPath(),
                Matchers.equalTo(Paths.get(zipPath + MigrationZipConstants.KEY_EXTENSION)));
        assertThat(cipherUtils.getChecksumPath(),
                Matchers.equalTo(Paths.get(zipPath + MigrationZipConstants.CHECKSUM_EXTENSION)));
        assertThat(cipherUtils.getKeyPath().toFile().exists(), Matchers.equalTo(true));
    }

    @Test
    public void testConstructorAlternateKeyAndChecksumLocations() {
        CipherUtils cipherUtils = new CipherUtils(zipPath, keyPath, checksumPath);
        assertThat(cipherUtils.getZipPath(), Matchers.equalTo(zipPath));
        assertThat(cipherUtils.getKeyPath(), Matchers.equalTo(keyPath));
        assertThat(cipherUtils.getChecksumPath(), Matchers.equalTo(checksumPath));
        assertThat(keyPath.toFile().exists(), Matchers.equalTo(true));
    }

    @Test
    public void testCreatingKey() throws Exception {
        Path keyPath = Paths.get(ddfHome.toString(), "secret.key");

        CipherUtils cipherUtils = new CipherUtils(zipPath, keyPath, checksumPath);
        SecretKey secretKey = cipherUtils.getSecretKey();
        SecretKey loadedKey = loadKeyFrom(cipherUtils.getKeyPath());
        assertThat(keyPath.toFile().exists(), Matchers.equalTo(true));
        assertThat(secretKey, Matchers.equalTo(loadedKey));
    }

    @Test
    public void testKeyAlreadyExists() throws IOException {
        CipherUtils cipherUtils = new CipherUtils(zipPath, keyPath, checksumPath);
        CipherUtils testCipherUtils = new CipherUtils(zipPath, keyPath, checksumPath);
        assertThat(testCipherUtils.getSecretKey(), Matchers.equalTo(cipherUtils.getSecretKey()));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructorWithNullChecksumPath() {
        new CipherUtils(zipPath, keyPath, null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructorWithNullzipPath() {
        new CipherUtils(null, keyPath, checksumPath);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructorWithNullKeyPath() {
        new CipherUtils(zipPath, null, checksumPath);
    }

    @Test
    public void testCreateEncryptionCipher() {
        Path keyPath = Paths.get(ddfHome.toString(), "secret.key");
        CipherUtils cipherUtils = new CipherUtils(zipPath, keyPath, checksumPath);
        Cipher cipher = cipherUtils.getCipher();
        assertThat(keyPath.toFile().exists(), Matchers.equalTo(true));
        assertThat(cipher, Matchers.notNullValue());
    }

    @Test
    public void testCreateChecksum() throws Exception {
        CipherUtils cipherUtils = new CipherUtils(zipPath, keyPath, checksumPath);
        writeStringToFile(zipPath.toFile(), "test", StandardCharsets.UTF_8);
        cipherUtils.createZipChecksumFile();
        String expectedHash = getChecksum(zipPath);
        String hashFileContent = readFileToString(checksumPath.toFile(), Charsets.UTF_8);
        assertThat(hashFileContent, Matchers.equalTo(expectedHash));
    }

    @Test
    public void createEncryptedFile() throws IOException {
        CipherUtils cipherUtils = new CipherUtils(zipPath);
        Path encryptedFile = Paths.get(ddfHome.toString(), "encrypted.test.file");
        FileOutputStream fos = new FileOutputStream(encryptedFile.toFile());
        CipherOutputStream cipherOutputStream = cipherUtils.getCipherOutputStream(fos);
        IOUtils.write("foo", cipherOutputStream, StandardCharsets.UTF_8);
        cipherOutputStream.close();
        assertThat(readFileToString(encryptedFile.toFile(), StandardCharsets.UTF_8), Matchers.not("foo"));
    }

    @Test(expected = FileNotFoundException.class)
    public void testCreateChecksumFileNotExist() throws Exception {
        CipherUtils cipherUtils = new CipherUtils(zipPath);
        cipherUtils.createZipChecksumFile();
    }

    @Test(expected = MigrationException.class)
    public void testBadlyEncodedKeyFile() throws IOException {
        new CipherUtils(zipPath, keyPath, checksumPath);
        writeStringToFile(keyPath.toFile(), "1", StandardCharsets.UTF_8, true);
        new CipherUtils(zipPath, keyPath, checksumPath);
    }

    private SecretKey loadKeyFrom(Path keyPath) throws Exception {
        BufferedInputStream bif = new BufferedInputStream(new FileInputStream(keyPath.toFile()));
        String keyData = IOUtils.toString(bif, Charsets.UTF_8);
        IOUtils.closeQuietly(bif);
        byte[] keyBytes = decodeHex(keyData.toCharArray());
        return new SecretKeySpec(keyBytes, MigrationZipConstants.KEY_ALGORITHM);
    }

    private String getChecksum(Path path) throws Exception {
        FileInputStream fis = new FileInputStream(path.toFile());
        MessageDigest digest = MessageDigest.getInstance(MigrationZipConstants.CHECKSUM_DIGEST_ALGORITHM);
        byte[] fileBytes = IOUtils.toByteArray(fis);
        digest.update(fileBytes);
        return new String(encodeHex(digest.digest()));
    }
}