sernet.verinice.encryption.test.CryptoTest.java Source code

Java tutorial

Introduction

Here is the source code for sernet.verinice.encryption.test.CryptoTest.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Sebastian Hagedorn <sh@sernet.de>.
 * 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/>.
 * 
 * Contributors:
 *     Sebastian Hagedorn <sh@sernet.de> - initial API and implementation
 ******************************************************************************/
package sernet.verinice.encryption.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Calendar;

import javax.security.auth.x500.X500Principal;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.junit.Test;

import sernet.gs.service.FileUtil;
import sernet.verinice.encryption.impl.EncryptionService;
import sernet.verinice.interfaces.CommandException;
import sernet.verinice.service.commands.SyncParameterException;

/**
 *
 */
public class CryptoTest {

    private static final Logger LOG = Logger.getLogger(CryptoTest.class);

    private static final int MAX_PASSWORD_LENGTH = 100;

    private EncryptionService encryptionService;

    private static final String VNA_FILE = "CryptoTest.vna";

    private static final String SECRET = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
            + " Donec at ligula et nibh pretium vulputate vitae quis tortor. "
            + "Integer ultrices facilisis ligula a pulvinar. Etiam commodo blandit eleifend. "
            + "Suspendisse malesuada ligula ut lectus fermentum, sit amet sodales elit malesuada. "
            + "Etiam nec vestibulum erat. Sed eget varius risus, vel ornare nisl. Duis sem augue, "
            + "volutpat at nisl ac, condimentum tincidunt erat. "
            + "Integer dapibus hendrerit lacus, quis semper augue feugiat sed. ";

    @Test
    public void passwordStreamBasedCryptoTest() {
        try {
            File f = File.createTempFile("veriniceCryptoTest", "pcr");
            f.deleteOnExit();
            char[] password = getPassword(20);
            FileOutputStream fileOutputStream = new FileOutputStream(f);
            OutputStream encryptedOutputStream = getEncryptionService().encrypt(fileOutputStream, password);
            encryptedOutputStream.write(SECRET.getBytes());
            encryptedOutputStream.flush();
            encryptedOutputStream.close();

            FileInputStream fileInputStream = new FileInputStream(f.getAbsolutePath());
            InputStream decryptedInputStream = getEncryptionService().decrypt(fileInputStream, password);
            StringBuilder sb = new StringBuilder();
            byte data = -1;
            while ((data = (byte) decryptedInputStream.read()) != -1) {
                sb.append((char) data);
            }
            assertEquals(SECRET, sb.toString());

        } catch (IOException e) {
            LOG.error("IO-Error", e);
        }

    }

    @Test
    public void passwordByteBasedCryptoTest() {

        for (int i = 1; i <= MAX_PASSWORD_LENGTH; i++) {
            char[] password = getPassword(i);
            byte[] encryptedMessage = getEncryptionService().encrypt(SECRET.getBytes(), password);

            byte[] decryptedMessage = getEncryptionService().decrypt(encryptedMessage, password);

            assertEquals("test fails on password(" + password.length + "):\n" + String.valueOf(password),
                    new String(decryptedMessage), SECRET);

        }
    }

    @Test
    public void certificateByteBasedCryptoTest() throws GeneralSecurityException, IOException {
        KeyPair keyPair = generateKeyPair();
        assertNotNull("Keypair is null", keyPair);
        String distinguishedName = "CN=Test, L=Berlin, C=DE";
        int days = 365;
        X509Certificate cert = generateCertificate(distinguishedName, keyPair, days);
        String certPEM = convertToPem(cert.getEncoded(), false, true);
        assertNotNull(certPEM);
        File certFile = File.createTempFile("veriniceCert", "PEM");
        assertNotNull(certFile);
        FileUtil.writeStringToFile(certPEM, certFile.getAbsolutePath());
        certFile.deleteOnExit();
        byte[] encryptedData = getEncryptionService().encrypt(SECRET.getBytes(), certFile);
        byte[] privateKey = keyPair.getPrivate().getEncoded();
        String privateKeyString = convertToPem(privateKey, true, false);
        File keyFile = File.createTempFile("veriniceKey", "PEM");
        assertNotNull(keyFile);
        FileUtil.writeStringToFile(privateKeyString, keyFile.getAbsolutePath());
        certFile.deleteOnExit();
        byte[] decryptedData = getEncryptionService().decrypt(encryptedData, certFile, keyFile);
        assertEquals(SECRET, new String(decryptedData));
    }

    @Test
    public void VNAPBCryptoTest() throws SyncParameterException, IOException, CommandException {
        byte[] plainContent = FileUtil.getFileData(new File(getAbsoluteFilePath(VNA_FILE)));
        char[] password = getPassword(10);
        byte[] encryptedContent = getEncryptionService().encrypt(plainContent, password);
        byte[] decryptedContent = getEncryptionService().decrypt(encryptedContent, password);
        assertTrue(Arrays.areEqual(plainContent, decryptedContent));
    }

    private char[] getPassword(int length) {
        return RandomStringUtils.randomAscii(length).toCharArray();
    }

    public EncryptionService getEncryptionService() {
        if (encryptionService == null) {
            encryptionService = new EncryptionService();
        }
        return encryptionService;
    }

    X509Certificate generateCertificate(String dn, KeyPair pair, int days)
            throws GeneralSecurityException, IOException {
        PublicKey publicKey = pair.getPublic();
        PrivateKey privateKey = pair.getPrivate();
        if (publicKey instanceof RSAPublicKey) {
            RSAPublicKey rsaPk = (RSAPublicKey) publicKey;
            RSAPublicKeySpec rsaPkSpec = new RSAPublicKeySpec(rsaPk.getModulus(), rsaPk.getPublicExponent());
            try {
                publicKey = KeyFactory.getInstance("RSA").generatePublic(rsaPkSpec);
            } catch (InvalidKeySpecException e) {
                publicKey = pair.getPublic();
            }
        }
        if (privateKey instanceof RSAPrivateKey) {
            RSAPrivateKey rsaPk = (RSAPrivateKey) privateKey;
            RSAPrivateKeySpec rsaPkSpec = new RSAPrivateKeySpec(rsaPk.getModulus(), rsaPk.getPrivateExponent());
            try {
                privateKey = KeyFactory.getInstance("RSA").generatePrivate(rsaPkSpec);
            } catch (InvalidKeySpecException e) {
                privateKey = pair.getPrivate();
            }
        }

        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        String commonName = "CN=" + dn + ", OU=None, O=None L=None, C=None";
        X500Principal dnName = new X500Principal(commonName);
        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
        certGen.setIssuerDN(dnName);
        certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));
        Calendar cal = Calendar.getInstance();
        certGen.setNotBefore(cal.getTime());
        cal.add(Calendar.YEAR, 5);
        certGen.setNotAfter(cal.getTime());
        certGen.setSubjectDN(dnName);
        certGen.setPublicKey(publicKey);
        certGen.setSignatureAlgorithm("MD5WithRSA");
        return certGen.generate(privateKey, BouncyCastleProvider.PROVIDER_NAME);
    }

    KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyPairGenerator keyGen;
        keyGen = org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator.getInstance("RSA",
                BouncyCastleProvider.PROVIDER_NAME);
        keyGen.initialize(1024, new SecureRandom());
        return keyGen.generateKeyPair();
    }

    private String convertToPem(byte[] data, boolean isKey, boolean isCert) {
        String prefix = "";
        String suffix = "";
        if (isCert && !isKey) {
            prefix = "-----BEGIN CERTIFICATE-----\n";
            suffix = "\n-----END CERTIFICATE-----";
        }
        if (!isCert && isKey) {
            prefix = "-----BEGIN PRIVATE KEY-----\n";
            suffix = "\n-----END PRIVATE KEY-----";
        }
        String certData;
        try {
            return certData = prefix + DatatypeConverter.printBase64Binary(data) + suffix;
        } catch (Exception e) {
            LOG.error("Error converting cert", e);
        }
        return null;
    }

    private String getAbsoluteFilePath(String path) {
        return getClass().getResource(path).getPath();
    }

}