/* * Copyright (c) 2006-2014 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Florent Guillaume */ package org.nuxeo.ecm.core.storage.binary; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.nuxeo.ecm.core.storage.binary.AESBinaryManager.PARAM_KEY_ALIAS; import static org.nuxeo.ecm.core.storage.binary.AESBinaryManager.PARAM_KEY_PASSWORD; import static org.nuxeo.ecm.core.storage.binary.AESBinaryManager.PARAM_KEY_STORE_FILE; import static org.nuxeo.ecm.core.storage.binary.AESBinaryManager.PARAM_KEY_STORE_PASSWORD; import static org.nuxeo.ecm.core.storage.binary.AESBinaryManager.PARAM_KEY_STORE_TYPE; import static org.nuxeo.ecm.core.storage.binary.AESBinaryManager.PARAM_PASSWORD; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyStore; import javax.crypto.KeyGenerator; import org.apache.commons.io.IOUtils; import org.junit.Test; import org.nuxeo.ecm.core.api.NuxeoException; import org.nuxeo.runtime.test.NXRuntimeTestCase; public class TestAESBinaryManager extends NXRuntimeTestCase { private static final String KEY_STORE_TYPE = "JCEKS"; private static final String KEY_STORE_PASSWORD = "keystoresecret"; private static final String KEY_ALIAS = "myaeskey"; private static final String KEY_PASSWORD = "keysecret"; private static final String CONTENT = "this is a file au caf\u00e9"; private static final String CONTENT_MD5 = "d25ea4f4642073b7f218024d397dbaef"; private static final String UTF8 = "UTF-8"; @Test public void testEncryptDecryptWithPassword() throws Exception { AESBinaryManager binaryManager = new AESBinaryManager(); binaryManager.digestAlgorithm = binaryManager.getDigest(); // MD5 String options = String.format("%s=%s", PARAM_PASSWORD, "mypassword"); binaryManager.initializeOptions(options); // encrypt ByteArrayOutputStream out = new ByteArrayOutputStream(); String digest = binaryManager.storeAndDigest(new ByteArrayInputStream( CONTENT.getBytes(UTF8)), out); assertEquals(CONTENT_MD5, digest); byte[] encrypted = out.toByteArray(); // decrypt out = new ByteArrayOutputStream(); binaryManager.decrypt(new ByteArrayInputStream(encrypted), out); assertEquals(CONTENT, new String(out.toByteArray(), UTF8)); // cannot decrypt with wrong password options = String.format("%s=%s", PARAM_PASSWORD, "badpassword"); binaryManager.initializeOptions(options); out = new ByteArrayOutputStream(); try { binaryManager.decrypt(new ByteArrayInputStream(encrypted), out); assertFalse(CONTENT.equals(new String(out.toByteArray(), UTF8))); } catch (NuxeoException e) { String message = e.getMessage(); assertTrue(message, message.contains("Given final block not properly padded")); } binaryManager.close(); } @Test public void testEncryptDecryptWithKeyStore() throws Exception { File keyStoreFile = File.createTempFile("nuxeoKeyStore_", ""); keyStoreFile.delete(); createKeyStore(keyStoreFile); String options = String.format("%s=%s,%s=%s,%s=%s,%s=%s,%s=%s", PARAM_KEY_STORE_TYPE, KEY_STORE_TYPE, // PARAM_KEY_STORE_FILE, keyStoreFile.getPath(), // PARAM_KEY_STORE_PASSWORD, KEY_STORE_PASSWORD, // PARAM_KEY_ALIAS, KEY_ALIAS, // PARAM_KEY_PASSWORD, KEY_PASSWORD); AESBinaryManager binaryManager = new AESBinaryManager(); binaryManager.digestAlgorithm = binaryManager.getDigest(); // MD5 binaryManager.initializeOptions(options); // encrypt ByteArrayOutputStream out = new ByteArrayOutputStream(); String digest = binaryManager.storeAndDigest(new ByteArrayInputStream( CONTENT.getBytes(UTF8)), out); assertEquals(CONTENT_MD5, digest); byte[] encrypted = out.toByteArray(); // decrypt out = new ByteArrayOutputStream(); binaryManager.decrypt(new ByteArrayInputStream(encrypted), out); assertEquals(CONTENT, new String(out.toByteArray(), UTF8)); binaryManager.close(); } protected void createKeyStore(File file) throws GeneralSecurityException, IOException { AESBinaryManager.setUnlimitedJCEPolicy(); KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(256); Key skey = kgen.generateKey(); KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE); // keyStore.load(null, KEY_STORE_PASSWORD.toCharArray()); keyStore.load(null, null); keyStore.setKeyEntry(KEY_ALIAS, skey, KEY_PASSWORD.toCharArray(), null); OutputStream out = new FileOutputStream(file); keyStore.store(out, KEY_STORE_PASSWORD.toCharArray()); out.close(); } @Test public void testAESBinaryManager() throws Exception { AESBinaryManager binaryManager = new AESBinaryManager(); BinaryManagerDescriptor descriptor = new BinaryManagerDescriptor(); String options = String.format("%s=%s", PARAM_PASSWORD, "mypassword"); descriptor.key = options; binaryManager.initialize(descriptor); Binary binary = binaryManager.getBinary(CONTENT_MD5); assertNull(binary); // store binary byte[] bytes = CONTENT.getBytes(UTF8); binary = binaryManager.getBinary(new ByteArrayInputStream(bytes)); assertNotNull(binary); assertEquals(CONTENT_MD5, binary.getDigest()); // get binary binary = binaryManager.getBinary(CONTENT_MD5); assertNotNull(binary); assertEquals(bytes.length, binary.getLength()); try (InputStream stream = binary.getStream()) { assertEquals(CONTENT, IOUtils.toString(stream, UTF8)); } binaryManager.close(); } }