001 package org.cumulus4j.store.model;
002
003 import javax.jdo.PersistenceManager;
004 import javax.jdo.annotations.IdGeneratorStrategy;
005 import javax.jdo.annotations.IdentityType;
006 import javax.jdo.annotations.NullValue;
007 import javax.jdo.annotations.PersistenceCapable;
008 import javax.jdo.annotations.Persistent;
009 import javax.jdo.annotations.PrimaryKey;
010 import javax.jdo.annotations.Queries;
011 import javax.jdo.annotations.Query;
012 import javax.jdo.annotations.Sequence;
013 import javax.jdo.annotations.SequenceStrategy;
014 import javax.jdo.annotations.Unique;
015 import javax.jdo.annotations.Version;
016 import javax.jdo.annotations.VersionStrategy;
017
018 import org.cumulus4j.crypto.Cipher;
019 import org.cumulus4j.crypto.CryptoRegistry;
020 import org.cumulus4j.store.EncryptionCoordinateSetManager;
021 import org.cumulus4j.store.crypto.CryptoManager;
022 import org.cumulus4j.store.crypto.CryptoSession;
023
024 /**
025 * <p>
026 * Encryption coordinates used to encrypt a persistent record.
027 * </p>
028 * <p>
029 * Via the {@link EncryptionCoordinateSetManager}, the {@link CryptoManager}
030 * (or {@link CryptoSession}) implementation can map the {@link Cipher#getTransformation()
031 * cipher-transformation} and other encryption-coordinates (e.g. the {@link #getMACAlgorithm() MAC algorithm})
032 * to a number in order to save space in each persistent record.
033 * </p>
034 *
035 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
036 */
037 @PersistenceCapable(identityType=IdentityType.APPLICATION, detachable="true")
038 @Version(strategy=VersionStrategy.VERSION_NUMBER)
039 @Unique(name="EncryptionCoordinateSet_allAlgorithms", members={"cipherTransformation", "macAlgorithm"})
040 @Queries({
041 @Query(
042 name="getEncryptionCoordinateSetByAllAlgorithms",
043 value="SELECT UNIQUE WHERE this.cipherTransformation == :cipherTransformation && this.macAlgorithm == :macAlgorithm"
044 )
045 })
046 @Sequence(name="EncryptionCoordinateSetSequence", datastoreSequence="EncryptionCoordinateSetSequence", initialValue=0, strategy=SequenceStrategy.CONTIGUOUS)
047 public class EncryptionCoordinateSet
048 {
049 /**
050 * <p>
051 * Constant for deactivating the <a target="_blank" href="http://en.wikipedia.org/wiki/Message_authentication_code">MAC</a>.
052 * </p>
053 * <p>
054 * <b>Important: Deactivating the MAC is dangerous!</b> Choose this value only, if you are absolutely
055 * sure that your {@link #getCipherTransformation() cipher-transformation} already
056 * provides authentication - like <a target="_blank" href="http://en.wikipedia.org/wiki/Galois/Counter_Mode">GCM</a>
057 * does for example.
058 * </p>
059 */
060 public static final String MAC_ALGORITHM_NONE = "NONE";
061
062 @PrimaryKey
063 @Persistent(valueStrategy=IdGeneratorStrategy.NATIVE, sequence="EncryptionCoordinateSetSequence")
064 private Long encryptionCoordinateSetID;
065
066 @Persistent(nullValue=NullValue.EXCEPTION)
067 private String cipherTransformation;
068
069 @Persistent(nullValue=NullValue.EXCEPTION)
070 private String macAlgorithm;
071
072 /**
073 * Create a new <code>EncryptionCoordinateSet</code>. This default constructor only exists
074 * for JDO and should never be used directly!
075 */
076 protected EncryptionCoordinateSet() { }
077
078 /**
079 * Create a new <code>EncryptionCoordinateSet</code>. Instead of using this constructor,
080 * you should use {@link #createEncryptionCoordinateSet(PersistenceManager, String, String)}!
081 *
082 * @param cipherTransformation the cipher-transformation.
083 * @param macAlgorithm the MAC-algorithm.
084 */
085 protected EncryptionCoordinateSet(String cipherTransformation, String macAlgorithm)
086 {
087 if (cipherTransformation == null)
088 throw new IllegalArgumentException("cipherTransformation == null");
089
090 if (macAlgorithm == null)
091 throw new IllegalArgumentException("macAlgorithm == null");
092
093 this.cipherTransformation = cipherTransformation;
094 this.macAlgorithm = macAlgorithm;
095 }
096
097 /**
098 * <p>
099 * Get the unique numeric identifier of this <code>EncryptionCoordinateSet</code>.
100 * </p>
101 * <p>
102 * Note: Implementors of {@link CryptoManager} (or {@link CryptoSession} respectively) might
103 * choose not to store the entire int value (4 bytes), but reduce the size. Every time the
104 * encryption configuration is changed, a new instance of this class is persisted. Restricting
105 * the size to 2 bytes, for example, still gives the administrator the possibility to change
106 * the configuration 65535 times - which is likely enough.
107 * </p>
108 *
109 * @return the unique numeric identifier (primary key).
110 */
111 public int getEncryptionCoordinateSetID() {
112 if (encryptionCoordinateSetID == null)
113 return -1;
114
115 if (encryptionCoordinateSetID.longValue() > Integer.MAX_VALUE)
116 throw new IllegalStateException("encryptionCoordinateSetID > Integer.MAX_VALUE :: " + encryptionCoordinateSetID + " > " + Integer.MAX_VALUE);
117
118 return encryptionCoordinateSetID.intValue();
119 }
120
121 /**
122 * Get the {@link Cipher#getTransformation() cipher-transformation} that identifies the encryption
123 * algorithm, the mode and the padding used to encrypt a record. The system usually passes
124 * this value to {@link CryptoRegistry#createCipher(String)}.
125 * @return the {@link Cipher#getTransformation() cipher-transformation}. Never <code>null</code>.
126 */
127 public String getCipherTransformation() {
128 return cipherTransformation;
129 }
130 /**
131 * <p>
132 * Get the <a target="_blank" href="http://en.wikipedia.org/wiki/Message_authentication_code">MAC</a>-algorithm
133 * used to protect a record against corruption/manipulation.
134 * </p>
135 * <p>
136 * Implementors of {@link CryptoManager}/{@link CryptoSession} should take {@link #MAC_ALGORITHM_NONE}
137 * into account! If this value equals that constant, MAC calculation and storage should be skipped.
138 * </p>
139 * @return the <a target="_blank" href="http://en.wikipedia.org/wiki/Message_authentication_code">MAC</a>-algorithm.
140 */
141 public String getMACAlgorithm() {
142 return macAlgorithm;
143 }
144 }