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    }