瀏覽代碼

HADOOP-10635. Add a method to CryptoCodec to generate SRNs for IV. Contributed by Yi Liu

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/fs-encryption@1598493 13f79535-47bb-0310-9956-ffa450edef68
Yi Liu 11 年之前
父節點
當前提交
f7921030cd

+ 2 - 0
hadoop-common-project/hadoop-common/CHANGES-fs-encryption.txt

@@ -17,6 +17,8 @@ fs-encryption (Unreleased)
     HADOOP-10632. Minor improvements to Crypto input and output streams. 
     (Yi Liu)
 
+    HADOOP-10635. Add a method to CryptoCodec to generate SRNs for IV. (Yi Liu)
+
   OPTIMIZATIONS
 
   BUG FIXES

+ 7 - 0
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoCodec.java

@@ -79,4 +79,11 @@ public abstract class CryptoCodec implements Configurable {
    * @param IV the IV for input stream position
    */
   public abstract void calculateIV(byte[] initIV, long counter, byte[] IV);
+  
+  /**
+   * Generate secure random.
+   * @param bytes length of the secure random
+   * @return byte[] the secure random
+   */
+  public abstract byte[] generateSecureRandom(int bytes);
 }

+ 21 - 0
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/JCEAESCTRCryptoCodec.java

@@ -20,6 +20,7 @@ package org.apache.hadoop.crypto;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
 
 import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
@@ -31,6 +32,8 @@ import org.apache.hadoop.conf.Configuration;
 import com.google.common.base.Preconditions;
 
 import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY;
+import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_KEY;
+import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_DEFAULT;
 
 /**
  * Implement the AES-CTR crypto codec using JCE provider.
@@ -39,6 +42,7 @@ import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY
 public class JCEAESCTRCryptoCodec extends AESCTRCryptoCodec {
   private Configuration conf;
   private String provider;
+  private SecureRandom random;
 
   public JCEAESCTRCryptoCodec() {
   }
@@ -52,6 +56,16 @@ public class JCEAESCTRCryptoCodec extends AESCTRCryptoCodec {
   public void setConf(Configuration conf) {
     this.conf = conf;
     provider = conf.get(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY);
+    final String secureRandomAlg = conf.get(
+        HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_KEY, 
+        HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_DEFAULT);
+    try {
+      random = (provider != null) ? 
+          SecureRandom.getInstance(secureRandomAlg, provider) : 
+            SecureRandom.getInstance(secureRandomAlg);
+    } catch (GeneralSecurityException e) {
+      throw new IllegalArgumentException(e);
+    }
   }
 
   @Override
@@ -64,6 +78,13 @@ public class JCEAESCTRCryptoCodec extends AESCTRCryptoCodec {
     return new JCEAESCTRCipher(Cipher.DECRYPT_MODE, provider);
   }
   
+  @Override
+  public byte[] generateSecureRandom(int bytes) {
+    final byte[] data = new byte[bytes];
+    random.nextBytes(data);
+    return data;
+  }  
+  
   private static class JCEAESCTRCipher implements Encryptor, Decryptor {
     private final Cipher cipher;
     private final int mode;

+ 6 - 0
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java

@@ -296,5 +296,11 @@ public class CommonConfigurationKeysPublic {
   /** Class to override Impersonation provider */
   public static final String  HADOOP_SECURITY_IMPERSONATION_PROVIDER_CLASS =
     "hadoop.security.impersonation.provider.class";
+  /** See <a href="{@docRoot}/../core-default.html">core-default.xml</a> */
+  public static final String HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_KEY = 
+      "hadoop.security.secure.random.algorithm";
+  /** Defalt value for HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_KEY */
+  public static final String HADOOP_SECURITY_SECURE_RANDOM_ALGORITHM_DEFAULT = 
+      "SHA1PRNG";
 }
 

+ 8 - 0
hadoop-common-project/hadoop-common/src/main/resources/core-default.xml

@@ -1384,4 +1384,12 @@
     The buffer size used by CryptoInputStream and CryptoOutputStream. 
   </description>
 </property>
+
+<property>
+  <name>hadoop.security.secure.random.algorithm</name>
+  <value></value>
+  <description>
+    The secure random algorithm. 
+  </description>
+</property>
 </configuration>

+ 81 - 0
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/TestCryptoCodec.java

@@ -0,0 +1,81 @@
+/**
+ * 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.crypto;
+
+import org.apache.hadoop.conf.Configuration;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestCryptoCodec {
+  private static CryptoCodec codec;
+  
+  @BeforeClass
+  public static void init() throws Exception {
+    Configuration conf = new Configuration();
+    codec = CryptoCodec.getInstance(conf);
+  }
+  
+  @AfterClass
+  public static void shutdown() throws Exception {
+  }
+  
+  @Test(timeout=120000)
+  public void testSecureRandom() throws Exception {
+    // len = 16
+    checkSecureRandom(16);
+    
+    // len = 32
+    checkSecureRandom(32);
+    
+    // len = 128
+    checkSecureRandom(128);
+  }
+  
+  private void checkSecureRandom(int len) {
+    byte[] rand = codec.generateSecureRandom(len);
+    byte[] rand1 = codec.generateSecureRandom(len);
+    
+    Assert.assertEquals(len, rand.length);
+    Assert.assertEquals(len, rand1.length);
+    Assert.assertFalse(bytesArrayEquals(rand, rand1));
+  }
+  
+  private boolean bytesArrayEquals(byte[] expected, byte[] actual) {
+    if ((expected == null  && actual != null) || 
+        (expected != null && actual == null)) {
+      return false;
+    }
+    if (expected == null && actual == null) {
+      return true;
+    }
+    
+    if (expected.length != actual.length) {
+      return false;
+    }
+    
+    for (int i = 0; i < expected.length; i++) {
+      if (expected[i] != actual[i]) {
+        return false;
+      }
+    }
+    
+    return true;
+  }
+}