001 /*
002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org
003 * Copyright (C) 2011 NightLabs Consulting GmbH
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
017 */
018 package org.cumulus4j.store;
019
020 import javax.crypto.BadPaddingException;
021 import javax.crypto.Cipher;
022 import javax.crypto.IllegalBlockSizeException;
023 import javax.crypto.spec.IvParameterSpec;
024 import javax.crypto.spec.SecretKeySpec;
025
026 import org.cumulus4j.store.crypto.AbstractCryptoManager;
027 import org.cumulus4j.store.crypto.AbstractCryptoSession;
028 import org.cumulus4j.store.crypto.Ciphertext;
029 import org.cumulus4j.store.crypto.CryptoContext;
030 import org.cumulus4j.store.crypto.CryptoSession;
031 import org.cumulus4j.store.crypto.Plaintext;
032
033 /**
034 * Dummy crypto-manager for debugging and testing.
035 *
036 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
037 */
038 public class DummyCryptoManager extends AbstractCryptoManager
039 {
040 @Override
041 protected CryptoSession createCryptoSession() {
042 return new DummySession();
043 }
044
045 private static final class DummySession
046 extends AbstractCryptoSession
047 {
048 // key length: 128 bits
049 private static final byte[] dummyKey = { 'D', 'e', 'r', ' ', 'F', 'e', 'r', 'd', ' ', 'h', 'a', 't', ' ', 'v', 'i', 'e' };
050 // initialization vector length: 128 bits
051 private static final IvParameterSpec iv = new IvParameterSpec(new byte[] {'b', 'l', 'a', 't', 'r', 'u', 'l', 'l', 'a', 'l', 'a', 't', 'r', 'a', 'r', 'a'});
052
053 private static final String ALGORITHM = "AES";
054 private static final String ALGORITHM_WITH_PARAMS = ALGORITHM + "/CBC/PKCS5Padding";
055
056 private Cipher encrypter;
057 private Cipher decrypter;
058 {
059 try {
060 SecretKeySpec key = new SecretKeySpec(dummyKey, ALGORITHM);
061 encrypter = Cipher.getInstance(ALGORITHM_WITH_PARAMS);
062 encrypter.init(Cipher.ENCRYPT_MODE, key, iv);
063 decrypter = Cipher.getInstance(ALGORITHM_WITH_PARAMS);
064 decrypter.init(Cipher.DECRYPT_MODE, key, iv);
065 } catch (Exception ex) {
066 throw new RuntimeException(ex);
067 }
068 }
069
070 @Override
071 public Ciphertext encrypt(CryptoContext cryptoContext, Plaintext plaintext)
072 {
073 // First get the required resources (that are cleared in close()).
074 Cipher c = encrypter;
075
076 // Then assert that we are not yet closed. This makes sure that we definitely can continue
077 // even if close() is called right now simultaneously.
078 assertNotClosed();
079
080 Ciphertext result = new Ciphertext();
081 result.setKeyID(12345);
082
083 synchronized (c) {
084 try {
085 result.setData(
086 c.doFinal(plaintext.getData())
087 );
088 } catch (IllegalBlockSizeException e) {
089 throw new RuntimeException(e);
090 } catch (BadPaddingException e) {
091 throw new RuntimeException(e);
092 }
093 }
094
095 return result;
096 }
097
098 @Override
099 public Plaintext decrypt(CryptoContext cryptoContext, Ciphertext ciphertext)
100 {
101 if (ciphertext.getKeyID() != 12345)
102 throw new IllegalArgumentException("No key with this keyID: " + ciphertext.getKeyID());
103
104 // First get the required resources (that are cleared in close()).
105 Cipher c = decrypter;
106
107 // Then assert that we are not yet closed. This makes sure that we definitely can continue
108 // even if close() is called right now simultaneously.
109 assertNotClosed();
110
111 Plaintext result = new Plaintext();
112
113 synchronized (c) {
114 try {
115 result.setData(
116 c.doFinal(ciphertext.getData())
117 );
118 } catch (IllegalBlockSizeException e) {
119 throw new RuntimeException(e);
120 } catch (BadPaddingException e) {
121 throw new RuntimeException(e);
122 }
123 }
124
125 return result;
126 }
127
128 @Override
129 public void close() {
130 super.close();
131 encrypter = null;
132 decrypter = null;
133 }
134 }
135
136 }