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 }