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            Date getCreationTimestamp();
113    
114            /**
115             * <p>
116             * Get the timestamp of the last call to {@link #release()}.
117             * If {@link #release()} was not yet called, get the time when this
118             * instance was created (just like {@link #getCreationTimestamp()} does).
119             * </p>
120             * <p>
121             * Therefore, this method always returns the time when the session was stopped being used
122             * the last time.
123             * </p>
124             * <p>
125             * This timestamp is used for automatic closing of expired sessions.
126             * </p>
127             *
128             * @return the timestamp of the last usage of this session.
129             */
130            Date getLastUsageTimestamp();
131    
132            /**
133             * <p>
134             * Set the {@link #getLastUsageTimestamp() lastUsageTimestamp} to <i>now</i>, i.e. <code>new Date()</code>.
135             * </p>
136             * <p>
137             * This method should be called by {@link CryptoManager#getCryptoSession(String)}.
138             * </p>
139             *
140             * @see #getLastUsageTimestamp()
141             */
142            void updateLastUsageTimestamp();
143    
144            /**
145             * <p>
146             * Encrypt the given <a target="_blank" href="http://en.wikipedia.org/wiki/Plaintext">plaintext</a>.
147             * </p>
148             * <p>
149             * This method is thread-safe. Thus, implementors should keep in mind that {@link Cipher} is not thread-safe!
150             * </p>
151             * @param cryptoContext context used to encrypt or decrypt data.
152             * @param plaintext the unencrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Plaintext">plaintext</a>) to be encrypted.
153             *
154             * @return the encrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Ciphertext">ciphertext</a>).
155             */
156            Ciphertext encrypt(CryptoContext cryptoContext, Plaintext plaintext);
157    
158            /**
159             * <p>
160             * Decrypt the given <a target="_blank" href="http://en.wikipedia.org/wiki/Ciphertext">ciphertext</a>.
161             * </p>
162             * <p>
163             * This method is thread-safe. Thus, implementors should keep in mind that {@link Cipher} is not thread-safe!
164             * </p>
165             * @param cryptoContext context used to encrypt or decrypt data.
166             * @param ciphertext the encrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Ciphertext">ciphertext</a>) to be decrypted.
167             *
168             * @return the unencrypted information (aka <a target="_blank" href="http://en.wikipedia.org/wiki/Plaintext">plaintext</a>).
169             */
170            Plaintext decrypt(CryptoContext cryptoContext, Ciphertext ciphertext);
171    
172            /**
173             * <p>Close the session.</p>
174             * <p>
175             * After closing, the <code>CryptoSession</code> cannot be used for encryption/decryption anymore, i.e.
176             * {@link #encrypt(CryptoContext, Plaintext)} and {@link #decrypt(CryptoContext, Ciphertext)} very likely throw an exception. The other
177             * methods might still work.
178             * </p>
179             * <p>
180             * This method can be called multiple times - every following call will be silently ignored.
181             * </p>
182             */
183            void close();
184    
185            /**
186             * Indicate, whether the session was already {@link #close() closed}.
187             * @return <code>true</code>, if {@link #close()} was already called; <code>false</code> otherwise.
188             */
189            boolean isClosed();
190    }