knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lmc...@apache.org
Subject knox git commit: KNOX-944 - Make PBE Hashing, Iteration Count and Salt Configurable and Manageable
Date Sat, 20 May 2017 16:36:12 GMT
Repository: knox
Updated Branches:
  refs/heads/master 551505640 -> d0726a227


KNOX-944 - Make PBE Hashing, Iteration Count and Salt Configurable and Manageable

Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/d0726a22
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/d0726a22
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/d0726a22

Branch: refs/heads/master
Commit: d0726a227d4f10e57489554b8adf8406e6d96920
Parents: 5515056
Author: Larry McCay <lmccay@hortonworks.com>
Authored: Sat May 20 12:26:32 2017 -0400
Committer: Larry McCay <lmccay@hortonworks.com>
Committed: Sat May 20 12:35:45 2017 -0400

----------------------------------------------------------------------
 .../gateway/config/impl/GatewayConfigImpl.java  |  35 ++++
 .../security/impl/DefaultCryptoService.java     |  14 +-
 .../security/impl/DefaultMasterService.java     |   2 +-
 .../services/security/CryptoServiceTest.java    |  75 ++++++--
 .../hadoop/gateway/config/GatewayConfig.java    |  42 +++++
 .../services/security/MasterService.java        |   2 -
 .../services/security/impl/AESEncryptor.java    | 152 ---------------
 .../security/impl/CMFMasterService.java         |  15 +-
 .../security/impl/ConfigurableEncryptor.java    | 188 +++++++++++++++++++
 .../hadoop/gateway/GatewayTestConfig.java       |  29 +++
 .../hadoop/gateway/GatewayTestConfig.java       |  30 +++
 11 files changed, 408 insertions(+), 176 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
index 3952d7b..368787a 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
@@ -192,6 +192,12 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig
{
 
   public static final String COOKIE_SCOPING_ENABLED =  GATEWAY_CONFIG_FILE_PREFIX + ".scope.cookies.feature.enabled";
   public static final boolean DEFAULT_COOKIE_SCOPING_FEATURE_ENABLED =  false;
+  private static final String CRYPTO_ALGORITHM = GATEWAY_CONFIG_FILE_PREFIX + ".crypto.algorithm";
+  private static final String CRYPTO_PBE_ALGORITHM = GATEWAY_CONFIG_FILE_PREFIX + ".crypto.pbe.algorithm";
+  private static final String CRYPTO_TRANSFORMATION = GATEWAY_CONFIG_FILE_PREFIX + ".crypto.transformation";
+  private static final String CRYPTO_SALTSIZE = GATEWAY_CONFIG_FILE_PREFIX + ".crypto.salt.size";
+  private static final String CRYPTO_ITERATION_COUNT = GATEWAY_CONFIG_FILE_PREFIX + ".crypto.iteration.count";
+  private static final String CRYPTO_KEY_LENGTH = GATEWAY_CONFIG_FILE_PREFIX + ".crypto.key.length";
 
   private static List<String> DEFAULT_GLOBAL_RULES_SERVICES;
 
@@ -824,4 +830,33 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig
{
     return value;
   }
 
+  @Override
+  public String getAlgorithm() {
+	return getVar(CRYPTO_ALGORITHM, null);
+  }
+
+  @Override
+  public String getPBEAlgorithm() {
+	return getVar(CRYPTO_PBE_ALGORITHM, null);
+  }
+
+  @Override
+  public String getTransformation() {
+	return getVar(CRYPTO_TRANSFORMATION, null);
+  }
+
+  @Override
+  public String getSaltSize() {
+	return getVar(CRYPTO_SALTSIZE, null);
+  }
+
+  @Override
+  public String getIterationCount() {
+	return getVar(CRYPTO_ITERATION_COUNT, null);
+  }
+
+  @Override
+  public String getKeyLength() {
+	return getVar(CRYPTO_KEY_LENGTH, null);
+  }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultCryptoService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultCryptoService.java
b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultCryptoService.java
index b8348dc..b6ef5a3 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultCryptoService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultCryptoService.java
@@ -43,7 +43,9 @@ public class DefaultCryptoService implements CryptoService {
 
   private AliasService as = null;
   private KeystoreService ks = null;
-  private HashMap<String,AESEncryptor> encryptorCache = new HashMap<>();
+  private HashMap<String,ConfigurableEncryptor> encryptorCache =
+		  new HashMap<String,ConfigurableEncryptor>();
+  private GatewayConfig config = null;
 
   public void setKeystoreService(KeystoreService ks) {
     this.ks = ks;
@@ -56,7 +58,8 @@ public class DefaultCryptoService implements CryptoService {
   @Override
   public void init(GatewayConfig config, Map<String, String> options)
       throws ServiceLifecycleException {
-    if (as == null) {
+    this.config = config;
+	if (as == null) {
       throw new ServiceLifecycleException("Alias service is not set");
     }
   }
@@ -188,11 +191,12 @@ public class DefaultCryptoService implements CryptoService {
 
   // The assumption here is that lock contention will be less of a performance issue than
the cost of object creation.
   // We have seen via profiling that AESEncryptor instantiation is very expensive.
-  private final AESEncryptor getEncryptor( final String clusterName, final char[] password
) {
+  private final ConfigurableEncryptor getEncryptor( final String clusterName, final char[]
password ) {
     synchronized( encryptorCache ) {
-      AESEncryptor encryptor = encryptorCache.get( clusterName );
+    	ConfigurableEncryptor encryptor = encryptorCache.get( clusterName );
       if( encryptor == null ) {
-        encryptor = new AESEncryptor( String.valueOf( password ) );
+        encryptor = new ConfigurableEncryptor( String.valueOf( password ) );
+        encryptor.init(config);
         encryptorCache.put( clusterName, encryptor );
       }
       return encryptor;

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
index 47368d0..ece8445 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultMasterService.java
@@ -43,7 +43,7 @@ public class DefaultMasterService extends CMFMasterService implements MasterServ
       boolean persisting = options.get( "persist-master").equals("true");
       String securityDir = config.getGatewaySecurityDir();
       String filename = "master";
-      setupMasterSecret(securityDir, filename, persisting);
+      setupMasterSecret(securityDir, filename, persisting, config);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
b/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
index bcd5ec2..57e2abc 100644
--- a/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
+++ b/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
@@ -19,15 +19,17 @@ package org.apache.hadoop.gateway.services.security;
 
 import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.services.ServiceLifecycleException;
-import org.apache.hadoop.gateway.services.security.impl.AESEncryptor;
+import org.apache.hadoop.gateway.services.security.impl.ConfigurableEncryptor;
 import org.apache.hadoop.gateway.services.security.impl.DefaultCryptoService;
 import org.apache.hadoop.test.category.ManualTests;
 import org.apache.hadoop.test.category.MediumTests;
+import org.easymock.EasyMock;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 import java.security.cert.Certificate;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -113,42 +115,91 @@ public class CryptoServiceTest {
     cs = new DefaultCryptoService();
     ((DefaultCryptoService)cs).setAliasService(as);
   }
-  
+
   @Test
-  public void testAESEncryptor() throws Exception {
+  public void testCryptoServiceAES() throws Exception {
+    GatewayConfig config = EasyMock.createNiceMock( GatewayConfig.class );
+    EasyMock.expect(config.getAlgorithm()).andReturn("AES");
+    EasyMock.expect(config.getPBEAlgorithm()).andReturn("PBKDF2WithHmacSHA1");
+    EasyMock.expect(config.getSaltSize()).andReturn("16");
+    EasyMock.expect(config.getIterationCount()).andReturn("65536");
+    EasyMock.expect(config.getKeyLength()).andReturn("128");
+    EasyMock.expect(config.getTransformation()).andReturn("AES/CBC/PKCS5Padding");
+    EasyMock.replay(config);
+
     // password to create key - same Encryptor
     String queryString = "url=http://localhost:50070/api/v1/blahblah";
-    AESEncryptor aes0 = new AESEncryptor("password");
+    ConfigurableEncryptor aes0 = new ConfigurableEncryptor("password");
+    aes0.init(config);
+    cs.init(config, new HashMap<String,String>());
     EncryptionResult result0 = cs.encryptForCluster("Test", "encrypt_url", queryString.getBytes("UTF8"));
-    byte[] decrypted0 = aes0.decrypt(result0.salt, result0.iv, result0.cipher);
+    byte[] decrypted0 = cs.decryptForCluster("Test", "encrypt_url", result0.cipher, result0.iv,
result0.salt);
     assertEquals(queryString, new String(decrypted0, "UTF8"));
     assertEquals(queryString.getBytes("UTF8").length, decrypted0.length);
     assertEquals(queryString.getBytes("UTF8").length, new String(decrypted0, "UTF8").toCharArray().length);
-    
+  }
+
+  @Test
+  public void testCryptoServiceDES() throws Exception {
+    GatewayConfig config = EasyMock.createNiceMock( GatewayConfig.class );
+    EasyMock.expect(config.getAlgorithm()).andReturn("DES");
+    EasyMock.expect(config.getPBEAlgorithm()).andReturn("PBKDF2WithHmacSHA1");
+    EasyMock.expect(config.getSaltSize()).andReturn("16");
+    EasyMock.expect(config.getIterationCount()).andReturn("65536");
+    EasyMock.expect(config.getKeyLength()).andReturn("128");
+    EasyMock.expect(config.getTransformation()).andReturn("DES");
+    EasyMock.replay(config);
+
     // password to create key - same Encryptor
-    AESEncryptor aes = new AESEncryptor("Test");
+    String queryString = "url=http://localhost:50070/api/v1/blahblah";
+    ConfigurableEncryptor aes0 = new ConfigurableEncryptor("password");
+    aes0.init(config);
+    cs.init(config, new HashMap<String,String>());
+    EncryptionResult result0 = cs.encryptForCluster("Test", "encrypt_url", queryString.getBytes("UTF8"));
+    byte[] decrypted0 = cs.decryptForCluster("Test", "encrypt_url", result0.cipher, result0.iv,
result0.salt);
+    assertEquals(queryString, new String(decrypted0, "UTF8"));
+    assertEquals(queryString.getBytes("UTF8").length, decrypted0.length);
+    assertEquals(queryString.getBytes("UTF8").length, new String(decrypted0, "UTF8").toCharArray().length);
+  }
+
+  @Test
+  public void testConfigurableEncryptor() throws Exception {
+    GatewayConfig config = EasyMock.createNiceMock( GatewayConfig.class );
+    EasyMock.expect(config.getAlgorithm()).andReturn("AES");
+    EasyMock.expect(config.getPBEAlgorithm()).andReturn("PBKDF2WithHmacSHA1");
+    EasyMock.expect(config.getSaltSize()).andReturn("16");
+    EasyMock.expect(config.getIterationCount()).andReturn("65536");
+    EasyMock.expect(config.getKeyLength()).andReturn("128");
+    EasyMock.expect(config.getTransformation()).andReturn("AES/CBC/PKCS5Padding");
+    EasyMock.replay(config);
+
+    // password to create key - same Encryptor
+    ConfigurableEncryptor aes = new ConfigurableEncryptor("Test");
+    aes.init(config);
     EncryptionResult result = aes.encrypt("larry".getBytes("UTF8"));
     byte[] decrypted = aes.decrypt(result.salt, result.iv, result.cipher);
     assertEquals(new String(decrypted, "UTF8"), "larry");
 
     // password to create key - different Encryptor
-    AESEncryptor aes2 = new AESEncryptor("Test");
+    ConfigurableEncryptor aes2 = new ConfigurableEncryptor("Test");
+    aes2.init(config);
     decrypted = aes2.decrypt(result.salt, result.iv, result.cipher);
     assertEquals(new String(decrypted, "UTF8"), "larry");
 
-    
     // password to create key resolved from alias - same Encryptor
-    AESEncryptor aes3 = new AESEncryptor(new String(as.getPasswordFromAliasForCluster("test",
"encrypt_url")));
+    ConfigurableEncryptor aes3 = new ConfigurableEncryptor(new String(as.getPasswordFromAliasForCluster("test",
"encrypt_url")));
+    aes3.init(config);
     result = aes3.encrypt("larry".getBytes("UTF8"));
     decrypted = aes3.decrypt(result.salt, result.iv, result.cipher);
     assertEquals(new String(decrypted, "UTF8"), "larry");
 
     // password to create key resolved from alias - different Encryptor
-    AESEncryptor aes4 = new AESEncryptor(new String(as.getPasswordFromAliasForCluster("test",
"encrypt_url")));
+    ConfigurableEncryptor aes4 = new ConfigurableEncryptor(new String(as.getPasswordFromAliasForCluster("test",
"encrypt_url")));
+    aes4.init(config);
     decrypted = aes4.decrypt(result.salt, result.iv, result.cipher);
     assertEquals(new String(decrypted, "UTF8"), "larry");
   }
-  
+
   @Test
   //@Ignore
   public void testEncryptionOfQueryStrings() throws Exception {

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
b/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
index 9d8e044..af03bbd 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
@@ -236,4 +236,46 @@ public interface GatewayConfig {
    */
   String getHeaderNameForRemoteAddress();
 
+  /**
+   * Configured Algorithm name to be used by the CryptoService
+   * and MasterService implementations
+   * @return
+   */
+  String getAlgorithm();
+
+  /**
+   * Configured Algorithm name to be used by the CryptoService
+   * for password based encryption
+   * @return
+   */
+  String getPBEAlgorithm();
+
+  /**
+   * Configured Transformation name to be used by the CryptoService
+   * and MasterService implementations
+   * @return
+   */
+  String getTransformation();
+
+  /**
+   * Configured SaltSize to be used by the CryptoService
+   * and MasterService implementations
+   * @return
+   */
+  String getSaltSize();
+
+  /**
+   * Configured IterationCount to be used by the CryptoService
+   * and MasterService implementations
+   * @return
+   */
+  String getIterationCount();
+
+  /**
+   * Configured KeyLength to be used by the CryptoService
+   * and MasterService implementations
+   * @return
+   */
+  String getKeyLength();
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
index 6d42dfe..ff84565 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/MasterService.java
@@ -18,7 +18,5 @@
 package org.apache.hadoop.gateway.services.security;
 
 public interface MasterService {
-
   public abstract char[] getMasterSecret();
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
deleted file mode 100644
index f6ff910..0000000
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/AESEncryptor.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.services.security.impl;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.spec.KeySpec;
-
-import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.services.security.EncryptionResult;
-
-public class AESEncryptor {
-  private static final GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class
);
-  
-  private static final int ITERATION_COUNT = 65536;
-  private static final int KEY_LENGTH = 128;
-  
-  private Cipher ecipher;
-  private Cipher dcipher;
-  private SecretKey secret;
-  private byte[] salt = null;
-  private char[] passPhrase = null;
- 
-  public AESEncryptor(String passPhrase) {
-      try {
-        this.passPhrase = passPhrase.toCharArray();
-        salt = new byte[8];
-        SecureRandom rnd = new SecureRandom();
-        rnd.nextBytes(salt);
-        
-        SecretKey tmp = getKeyFromPassword(passPhrase);
-        secret = new SecretKeySpec (tmp.getEncoded(), "AES");
- 
-        ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-        ecipher.init(Cipher.ENCRYPT_MODE, secret);
-       
-        dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-        byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
-        dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (NoSuchPaddingException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (InvalidKeyException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (InvalidParameterSpecException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (InvalidAlgorithmParameterException e) {
-        LOG.failedToEncryptPassphrase( e );
-      }
-  }
-  
-  AESEncryptor(SecretKey secret) {
-    try {
-      this.secret = new SecretKeySpec (secret.getEncoded(), "AES");
-
-      ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-      ecipher.init(Cipher.ENCRYPT_MODE, secret);
-     
-      dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-      byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
-      dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (NoSuchPaddingException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (InvalidKeyException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (InvalidParameterSpecException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (InvalidAlgorithmParameterException e) {
-      LOG.failedToEncryptPassphrase( e );
-    }
-  }
-
-  public SecretKey getKeyFromPassword(String passPhrase) {
-    return getKeyFromPassword(passPhrase, salt);
-  }
-  
-  public SecretKey getKeyFromPassword(String passPhrase, byte[] salt) {
-    SecretKeyFactory factory;
-    SecretKey key = null;
-    try {
-      factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
-      KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
-      key = factory.generateSecret(spec);
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToGenerateKeyFromPassword( e );
-    } catch (InvalidKeySpecException e) {
-      LOG.failedToGenerateKeyFromPassword( e );
-    }
-    
-    return key;
-  }
-
-  public EncryptionResult encrypt(String encrypt) throws Exception {
-      byte[] bytes = encrypt.getBytes("UTF8");
-      EncryptionResult atom = encrypt(bytes);
-      return atom;
-  }
-
-  public EncryptionResult encrypt(byte[] plain) throws Exception {
-    EncryptionResult atom = new EncryptionResult(salt, ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
ecipher.doFinal(plain));
-    return atom;
-  }
-
-  public String decrypt(String salt, String iv, String cipher) throws Exception {
-    byte[] decrypted = decrypt(salt.getBytes("UTF8"), iv.getBytes("UTF8"), cipher.getBytes("UTF8"));
-    return new String(decrypted, "UTF8");
-  }
-
-  public byte[] decrypt(byte[] salt, byte[] iv, byte[] encrypt) throws Exception {
-    SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
-    secret = new SecretKeySpec(tmp.getEncoded(), "AES");
-    
-    dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-    return dcipher.doFinal(encrypt);
-  }
-  
-  public byte[] decrypt(byte[] encrypt) throws Exception {
-    dcipher.init(Cipher.DECRYPT_MODE, secret);
-    return dcipher.doFinal(encrypt);
-  }
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
index 7960787..5a37f9b 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/CMFMasterService.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.gateway.services.security.impl;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.net.ntp.TimeStamp;
+import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.services.ServiceLifecycleException;
@@ -39,7 +40,7 @@ public class CMFMasterService {
   private static final String MASTER_PERSISTENCE_TAG = "#1.0# " + TimeStamp.getCurrentTime().toDateString();
   protected char[] master = null;
   protected String serviceName = null;
-  private AESEncryptor aes = new AESEncryptor(MASTER_PASSPHRASE);
+  private ConfigurableEncryptor encryptor = new ConfigurableEncryptor(MASTER_PASSPHRASE);
 
   public CMFMasterService(String serviceName) {
     super();
@@ -50,6 +51,13 @@ public class CMFMasterService {
     return this.master;
   }
 
+  public void setupMasterSecret(String securityDir, String filename,
+		  boolean persisting, GatewayConfig config)
+				  throws ServiceLifecycleException  {
+      encryptor.init(config);
+      setupMasterSecret(securityDir, filename, persisting);
+  }
+
   protected void setupMasterSecret(String securityDir, boolean persisting) throws ServiceLifecycleException
{
     setupMasterSecret(securityDir, serviceName + "-master", persisting);
   }
@@ -60,7 +68,6 @@ public class CMFMasterService {
       try {
         initializeFromMaster(masterFile);
       } catch (Exception e) {
-        // TODO Auto-generated catch block
         throw new ServiceLifecycleException("Unable to load the persisted master secret.",
e);
       }
     }
@@ -146,7 +153,7 @@ public class CMFMasterService {
   private EncryptionResult encryptMaster(char[] master) {
     // TODO Auto-generated method stub
     try {
-      return aes.encrypt(new String(master));
+      return encryptor.encrypt(new String(master));
     } catch (Exception e) {
       LOG.failedToEncryptMasterSecret(e);
     }
@@ -160,7 +167,7 @@ public class CMFMasterService {
         LOG.loadingFromPersistentMaster( tag );
         String line = new String(Base64.decodeBase64(lines.get(1)));
         String[] parts = line.split("::");
-        this.master = new String(aes.decrypt(Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]),
Base64.decodeBase64(parts[2])), "UTF8").toCharArray();
+        this.master = new String(encryptor.decrypt(Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]),
Base64.decodeBase64(parts[2])), "UTF8").toCharArray();
       } catch (IOException e) {
         LOG.failedToInitializeFromPersistentMaster(masterFile.getName(), e);
         throw e;

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/ConfigurableEncryptor.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/ConfigurableEncryptor.java
b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/ConfigurableEncryptor.java
new file mode 100644
index 0000000..49be71d
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/impl/ConfigurableEncryptor.java
@@ -0,0 +1,188 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.gateway.services.security.impl;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.KeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.security.EncryptionResult;
+
+public class ConfigurableEncryptor {
+  private static final GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class
);
+  
+  private static final int ITERATION_COUNT = 65536;
+  private static final int KEY_LENGTH = 128;
+  
+  private Cipher ecipher;
+  private Cipher dcipher;
+  private SecretKey secret;
+  private byte[] salt = null;
+  private char[] passPhrase = null;
+  private String alg = "AES";
+  private String pbeAlg = "PBKDF2WithHmacSHA1";
+  private String transformation = "AES/CBC/PKCS5Padding";
+  private int saltSize = 8;
+  private int iterationCount = ITERATION_COUNT;
+  private int keyLength = KEY_LENGTH;
+ 
+  public ConfigurableEncryptor(String passPhrase) {
+      try {
+        this.passPhrase = passPhrase.toCharArray();
+        salt = new byte[saltSize];
+        SecureRandom rnd = new SecureRandom();
+        rnd.nextBytes(salt);
+        
+        SecretKey tmp = getKeyFromPassword(passPhrase);
+        secret = new SecretKeySpec (tmp.getEncoded(), alg);
+ 
+        ecipher = Cipher.getInstance(transformation);
+        ecipher.init(Cipher.ENCRYPT_MODE, secret);
+       
+        dcipher = Cipher.getInstance(transformation);
+        byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
+        dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (NoSuchPaddingException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (InvalidKeyException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (InvalidParameterSpecException e) {
+        LOG.failedToEncryptPassphrase( e );
+      } catch (InvalidAlgorithmParameterException e) {
+        LOG.failedToEncryptPassphrase( e );
+      }
+  }
+  
+  ConfigurableEncryptor(SecretKey secret) {
+    try {
+      this.secret = new SecretKeySpec (secret.getEncoded(), alg);
+
+      ecipher = Cipher.getInstance(transformation);
+      ecipher.init(Cipher.ENCRYPT_MODE, secret);
+     
+      dcipher = Cipher.getInstance(transformation);
+      byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
+      dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (NoSuchPaddingException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (InvalidKeyException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (InvalidParameterSpecException e) {
+      LOG.failedToEncryptPassphrase( e );
+    } catch (InvalidAlgorithmParameterException e) {
+      LOG.failedToEncryptPassphrase( e );
+    }
+  }
+
+  public void init(GatewayConfig config) {
+    if (config != null) {
+	    String alg = config.getAlgorithm();
+	    if (alg != null) {
+		  this.alg = alg;
+	    }
+	    String pbeAlg = config.getPBEAlgorithm();
+	    if (pbeAlg != null) {
+		  this.pbeAlg = pbeAlg;
+	    }
+	    String transformation = config.getTransformation();
+	    if (transformation != null) {
+		  this.transformation = transformation;
+	    }
+	    String saltSize = config.getSaltSize();
+	    if (saltSize != null) {
+		  this.saltSize = Integer.parseInt(saltSize);
+	    }
+	    String iterationCount = config.getIterationCount();
+	    if (iterationCount != null) {
+		  this.iterationCount = Integer.parseInt(iterationCount);
+	    }
+	    String keyLength = config.getKeyLength();
+	    if (keyLength != null) {
+		  this.keyLength = Integer.parseInt(keyLength);
+	    }
+    }
+  }
+
+  public SecretKey getKeyFromPassword(String passPhrase) {
+    return getKeyFromPassword(passPhrase, salt);
+  }
+  
+  public SecretKey getKeyFromPassword(String passPhrase, byte[] salt) {
+    SecretKeyFactory factory;
+    SecretKey key = null;
+    try {
+      factory = SecretKeyFactory.getInstance(pbeAlg);
+      KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount, keyLength);
+      key = factory.generateSecret(spec);
+    } catch (NoSuchAlgorithmException e) {
+      LOG.failedToGenerateKeyFromPassword( e );
+    } catch (InvalidKeySpecException e) {
+      LOG.failedToGenerateKeyFromPassword( e );
+    }
+    
+    return key;
+  }
+
+  public EncryptionResult encrypt(String encrypt) throws Exception {
+      byte[] bytes = encrypt.getBytes("UTF8");
+      EncryptionResult atom = encrypt(bytes);
+      return atom;
+  }
+
+  public EncryptionResult encrypt(byte[] plain) throws Exception {
+    EncryptionResult atom = new EncryptionResult(salt, ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
ecipher.doFinal(plain));
+    return atom;
+  }
+
+  public String decrypt(String salt, String iv, String cipher) throws Exception {
+    byte[] decrypted = decrypt(salt.getBytes("UTF8"), iv.getBytes("UTF8"), cipher.getBytes("UTF8"));
+    return new String(decrypted, "UTF8");
+  }
+
+  public byte[] decrypt(byte[] salt, byte[] iv, byte[] encrypt) throws Exception {
+    SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
+    secret = new SecretKeySpec(tmp.getEncoded(), alg);
+    
+    dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
+    return dcipher.doFinal(encrypt);
+  }
+  
+  public byte[] decrypt(byte[] encrypt) throws Exception {
+    dcipher.init(Cipher.DECRYPT_MODE, secret);
+    return dcipher.doFinal(encrypt);
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
----------------------------------------------------------------------
diff --git a/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
b/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
index c079531..f41046b 100644
--- a/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
+++ b/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
@@ -478,4 +478,33 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig
{
     return "X-Forwarded-For";
   }
 
+  @Override
+  public String getAlgorithm() {
+	return null;
+  }
+
+  @Override
+  public String getPBEAlgorithm() {
+	return null;
+  }
+
+  @Override
+  public String getTransformation() {
+	return null;
+  }
+
+  @Override
+  public String getSaltSize() {
+	return null;
+  }
+
+  @Override
+  public String getIterationCount() {
+	return null;
+  }
+
+  @Override
+  public String getKeyLength() {
+	return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/d0726a22/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
index e96dde2..580d875 100644
--- a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
+++ b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
@@ -535,4 +535,34 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig
{
   public String getHeaderNameForRemoteAddress() {
     return "X-Forwarded-For";
   }
+
+  @Override
+  public String getAlgorithm() {
+	return null;
+  }
+
+  @Override
+  public String getPBEAlgorithm() {
+	return null;
+  }
+
+  @Override
+  public String getTransformation() {
+	return null;
+  }
+
+  @Override
+  public String getSaltSize() {
+	return null;
+  }
+
+  @Override
+  public String getIterationCount() {
+	return null;
+  }
+
+  @Override
+  public String getKeyLength() {
+	return null;
+  }
 }


Mime
View raw message