You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2014/04/05 17:34:12 UTC

svn commit: r1585107 - /cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/key/JceksKeySource.java

Author: aadamchik
Date: Sat Apr  5 15:34:11 2014
New Revision: 1585107

URL: http://svn.apache.org/r1585107
Log:
CAY-1916 cayenne-crypto module that enables data encryption for certain model attributes

caching keys - reading it every time from the keystore is really expensive

Modified:
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/key/JceksKeySource.java

Modified: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/key/JceksKeySource.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/key/JceksKeySource.java?rev=1585107&r1=1585106&r2=1585107&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/key/JceksKeySource.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/key/JceksKeySource.java Sat Apr  5 15:34:11 2014
@@ -27,6 +27,8 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.cayenne.crypto.CayenneCryptoException;
 import org.apache.cayenne.crypto.CryptoConstants;
@@ -43,11 +45,36 @@ public class JceksKeySource implements K
 
     // this is the only standard keystore type that supports storing secret keys
     private static final String JCEKS_KEYSTORE_TYPE = "jceks";
+    private static final Key NULL_KEY = new Key() {
+
+        private static final long serialVersionUID = 4755682444381893880L;
+
+        @Override
+        public String getFormat() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public byte[] getEncoded() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String getAlgorithm() {
+            throw new UnsupportedOperationException();
+        }
+    };
 
     private KeyStore keyStore;
     private char[] keyPassword;
     private String defaultKeyAlias;
 
+    // caching the keys may not be a good idea for security reasons, but
+    // re-reading the key from KeyStore for every select row creates a huge
+    // bottleneck... And considering we are caching keystore password, it
+    // probably doesn't make things that much worse
+    private ConcurrentMap<String, Key> keyCache;
+
     public JceksKeySource(@Inject(CryptoConstants.PROPERTIES_MAP) Map<String, String> properties,
             @Inject(CryptoConstants.CREDENTIALS_MAP) Map<String, char[]> credentials) {
 
@@ -70,6 +97,8 @@ public class JceksKeySource implements K
             throw new CayenneCryptoException("Default key alias is not set. Property name: "
                     + CryptoConstants.ENCRYPTION_KEY_ALIAS);
         }
+
+        this.keyCache = new ConcurrentHashMap<String, Key>();
     }
 
     private KeyStore createKeyStore(String keyStoreUrl) throws KeyStoreException, IOException,
@@ -91,8 +120,22 @@ public class JceksKeySource implements K
 
     @Override
     public Key getKey(String alias) {
+
+        Key key = keyCache.get(alias);
+        if (key == null) {
+
+            Key newKey = createKey(alias);
+            Key oldKey = keyCache.putIfAbsent(alias, newKey);
+            key = oldKey != null ? oldKey : newKey;
+        }
+
+        return key == NULL_KEY ? null : key;
+    }
+
+    protected Key createKey(String alias) {
         try {
-            return keyStore.getKey(alias, keyPassword);
+            Key key = keyStore.getKey(alias, keyPassword);
+            return key != null ? key : NULL_KEY;
         } catch (Exception e) {
             throw new CayenneCryptoException("Error accessing key for alias: " + alias, e);
         }