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.crypto;
019
020 import java.util.Date;
021
022 import org.cumulus4j.crypto.Cipher;
023 import org.datanucleus.NucleusContext;
024
025 /**
026 * <p>
027 * A <code>CryptoSession</code> is a session managed by a client to decrypt/encrypt data.
028 * </p>
029 * <p>
030 * Data can only be decrypted (or encrypted) within the scope of a valid session. That means,
031 * the client must open a <code>CryptoSession</code> prior to persisting/querying data.
032 * </p>
033 * <p>
034 * There exists one <code>CryptoSession</code> instance for each unique combination of
035 * {@link NucleusContext}, {@link CryptoManager#getCryptoManagerID() cryptoManagerID} and
036 * {@link #getCryptoSessionID() cryptoSessionID}. Therefore, it can happen, that multiple
037 * <code>PersistenceManager</code>/<code>EntityManager</code> instances access the same
038 * <code>CryptoSession</code> from multiple threads.
039 * </p>
040 * <p>
041 * Thus all implementations of CryptoSession must be thread-safe! In this context, it is important
042 * to know that {@link Cipher} is <b>not</b> thread-safe! You should thus always synchronize on the <code>Cipher</code>
043 * instance before using it (if you share them, which you probably do due to the expensiveness of key-initialisations).
044 * </p>
045 * <p>
046 * A <code>CryptoSession</code> must not be instantiated directly, but instead obtained via
047 * {@link CryptoManager#getCryptoSession(String)}. In other words, a new instance of
048 * <code>CryptoSession</code> must only be created within the {@link CryptoManager}
049 * implementation.
050 * </p>
051 * <p>
052 * <b>Important:</b> It is strongly recommended to subclass {@link AbstractCryptoSession}
053 * instead of directly implementing this interface!
054 * </p>
055 *
056 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
057 */
058 public interface CryptoSession
059 {
060 /**
061 * <p>
062 * Property-name used to pass the {@link #getCryptoSessionID() cryptoSessionID} to the Cumulus4j-core.
063 * </p>
064 * <p>
065 * The property must be passed to the Cumulus4j-core via
066 * {@link javax.jdo.PersistenceManager#setProperty(String, Object)} or
067 * {@link javax.persistence.EntityManager#setProperty(String, Object)}.
068 * </p>
069 */
070 static final String PROPERTY_CRYPTO_SESSION_ID = "cumulus4j.cryptoSessionID";
071
072 /**
073 * <p>
074 * Set the {@link CryptoManager} to which this session belongs.
075 * </p>
076 * <p>
077 * If you subclass {@link AbstractCryptoManager} (instead of directly implementing the {@link CryptoManager} interface)
078 * you must never call this method. Otherwise, it is expected, that you call this method once in {@link CryptoManager#getCryptoSession(String)}
079 * after creating a new <code>CryptoSession</code>, before returning it.
080 * </p>
081 *
082 * @param cryptoManager the <code>CryptoManager</code> to which this session belongs.
083 * @see #getCryptoManager()
084 */
085 void setCryptoManager(CryptoManager cryptoManager);
086
087 /**
088 * <p>
089 * Get the {@link CryptoManager} to which this session belongs.
090 * </p>
091 * @return the <code>CryptoManager</code> to which this session belongs.
092 */
093 CryptoManager getCryptoManager();
094
095 /**
096 * <p>
097 * Set the {@link #getCryptoSessionID() cryptoSessionID}.
098 * </p>
099 * <p>
100 * If you subclass {@link AbstractCryptoManager} (instead of directly implementing the {@link CryptoManager} interface)
101 * you must never call this method. Otherwise, it is expected, that you call this method once in {@link CryptoManager#getCryptoSession(String)}
102 * after creating a new <code>CryptoSession</code>, before returning it.
103 * </p>
104 *
105 * @param cryptoSessionID the identifier of this session.
106 * @see #getCryptoSessionID()
107 */
108 void setCryptoSessionID(String cryptoSessionID);
109
110 String getCryptoSessionID();
111
112 String getKeyStoreID();
113
114 Date getCreationTimestamp();
115
116 /**
117 * <p>
118 * Get the timestamp of the last call to {@link #release()}.
119 * If {@link #release()} was not yet called, get the time when this
120 * instance was created (just like {@link #getCreationTimestamp()} does).
121 * </p>
122 * <p>
123 * Therefore, this method always returns the time when the session was stopped being used
124 * the last time.
125 * </p>
126 * <p>
127 * This timestamp is used for automatic closing of expired sessions.
128 * </p>
129 *
130 * @return the timestamp of the last usage of this session.
131 */
132 Date getLastUsageTimestamp();
133
134 /**
135 * <p>
136 * Set the {@link #getLastUsageTimestamp() lastUsageTimestamp} to <i>now</i>, i.e. <code>new Date()</code>.
137 * </p>
138 * <p>
139 * This method should be called by {@link CryptoManager#getCryptoSession(String)}.
140 * </p>
141 *
142 * @see #getLastUsageTimestamp()
143 */
144 void updateLastUsageTimestamp();
145
146 /**
147 * <p>
148 * Encrypt the given <a target="_blank" href="http://en.wikipedia.org/wiki/Plaintext">plaintext</a>.
149 * </p>
150 * <p>
151 * This method is thread-safe. Thus, implementors should keep in mind that {@link Cipher} is not thread-safe!
152 * </p>
153 * @param cryptoContext context used to encrypt or decrypt data.
154 * @param plaintext the unencrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Plaintext">plaintext</a>) to be encrypted.
155 *
156 * @return the encrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Ciphertext">ciphertext</a>).
157 */
158 Ciphertext encrypt(CryptoContext cryptoContext, Plaintext plaintext);
159
160 /**
161 * <p>
162 * Decrypt the given <a target="_blank" href="http://en.wikipedia.org/wiki/Ciphertext">ciphertext</a>.
163 * </p>
164 * <p>
165 * This method is thread-safe. Thus, implementors should keep in mind that {@link Cipher} is not thread-safe!
166 * </p>
167 * @param cryptoContext context used to encrypt or decrypt data.
168 * @param ciphertext the encrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Ciphertext">ciphertext</a>) to be decrypted.
169 *
170 * @return the unencrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Plaintext">plaintext</a>).
171 */
172 Plaintext decrypt(CryptoContext cryptoContext, Ciphertext ciphertext);
173
174 /**
175 * <p>Close the session.</p>
176 * <p>
177 * After closing, the <code>CryptoSession</code> cannot be used for encryption/decryption anymore, i.e.
178 * {@link #encrypt(CryptoContext, Plaintext)} and {@link #decrypt(CryptoContext, Ciphertext)} very likely throw an exception. The other
179 * methods might still work.
180 * </p>
181 * <p>
182 * This method can be called multiple times - every following call will be silently ignored.
183 * </p>
184 */
185 void close();
186
187 /**
188 * Indicate, whether the session was already {@link #close() closed}.
189 * @return <code>true</code>, if {@link #close()} was already called; <code>false</code> otherwise.
190 */
191 boolean isClosed();
192 }