HADOOP-10803. Update OpensslCipher#getInstance to accept CipherSuite#name format. (yliu)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/fs-encryption@1609403 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yi Liu 2014-07-10 06:27:52 +00:00
parent 7aa07912dc
commit d90671137e
5 changed files with 97 additions and 31 deletions

View File

@ -28,6 +28,12 @@ fs-encryption (Unreleased)
HADOOP-10713. Refactor CryptoCodec#generateSecureRandom to take a byte[]. HADOOP-10713. Refactor CryptoCodec#generateSecureRandom to take a byte[].
(wang via yliu) (wang via yliu)
HADOOP-10693. Implementation of AES-CTR CryptoCodec using JNI to OpenSSL.
(Yi Liu via cmccabe)
HADOOP-10803. Update OpensslCipher#getInstance to accept CipherSuite#name
format. (Yi Liu)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -70,8 +70,7 @@ private static class OpensslAesCtrCipher implements Encryptor, Decryptor {
public OpensslAesCtrCipher(int mode) throws GeneralSecurityException { public OpensslAesCtrCipher(int mode) throws GeneralSecurityException {
this.mode = mode; this.mode = mode;
cipher = OpensslCipher.getInstance(OpensslCipher.AES_CTR, cipher = OpensslCipher.getInstance(SUITE.getName());
OpensslCipher.PADDING_NOPADDING);
} }
@Override @Override

View File

@ -19,6 +19,7 @@
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.StringTokenizer;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException; import javax.crypto.IllegalBlockSizeException;
@ -45,11 +46,34 @@ public final class OpensslCipher {
public static final int DECRYPT_MODE = 0; public static final int DECRYPT_MODE = 0;
/** Currently only support AES/CTR/NoPadding. */ /** Currently only support AES/CTR/NoPadding. */
public static final int AES_CTR = 0; private static enum AlgMode {
public static final int PADDING_NOPADDING = 0; AES_CTR;
static int get(String algorithm, String mode)
throws NoSuchAlgorithmException {
try {
return AlgMode.valueOf(algorithm + "_" + mode).ordinal();
} catch (Exception e) {
throw new NoSuchAlgorithmException("Doesn't support algorithm: " +
algorithm + " and mode: " + mode);
}
}
}
private static enum Padding {
NoPadding;
static int get(String padding) throws NoSuchPaddingException {
try {
return Padding.valueOf(padding).ordinal();
} catch (Exception e) {
throw new NoSuchPaddingException("Doesn't support padding: " + padding);
}
}
}
private long context = 0; private long context = 0;
private final int algorithm; private final int alg;
private final int padding; private final int padding;
private static boolean nativeCipherLoaded = false; private static boolean nativeCipherLoaded = false;
@ -69,26 +93,71 @@ public static boolean isNativeCodeLoaded() {
return nativeCipherLoaded; return nativeCipherLoaded;
} }
private OpensslCipher(long context, int algorithm, int padding) { private OpensslCipher(long context, int alg, int padding) {
this.context = context; this.context = context;
this.algorithm = algorithm; this.alg = alg;
this.padding = padding; this.padding = padding;
} }
/** /**
* Return an <code>OpensslCipher<code> object that implements the specified * Return an <code>OpensslCipher<code> object that implements the specified
* algorithm. * transformation.
* *
* @param algorithm currently only supports {@link #AES_CTR} * @param transformation the name of the transformation, e.g.,
* @param padding currently only supports {@link #PADDING_NOPADDING} * AES/CTR/NoPadding.
* @return OpensslCipher an <code>OpensslCipher<code> object * @return OpensslCipher an <code>OpensslCipher<code> object
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException if <code>transformation</code> is null,
* @throws NoSuchPaddingException * empty, in an invalid format, or if Openssl doesn't implement the
* specified algorithm.
* @throws NoSuchPaddingException if <code>transformation</code> contains
* a padding scheme that is not available.
*/ */
public static final OpensslCipher getInstance(int algorithm, public static final OpensslCipher getInstance(String transformation)
int padding) throws NoSuchAlgorithmException, NoSuchPaddingException { throws NoSuchAlgorithmException, NoSuchPaddingException {
long context = initContext(algorithm, padding); Transform transform = tokenizeTransformation(transformation);
return new OpensslCipher(context, algorithm, padding); int algMode = AlgMode.get(transform.alg, transform.mode);
int padding = Padding.get(transform.padding);
long context = initContext(algMode, padding);
return new OpensslCipher(context, algMode, padding);
}
/** Nested class for algorithm, mode and padding. */
private static class Transform {
final String alg;
final String mode;
final String padding;
public Transform(String alg, String mode, String padding) {
this.alg = alg;
this.mode = mode;
this.padding = padding;
}
}
private static Transform tokenizeTransformation(String transformation)
throws NoSuchAlgorithmException {
if (transformation == null) {
throw new NoSuchAlgorithmException("No transformation given.");
}
/*
* Array containing the components of a Cipher transformation:
*
* index 0: algorithm (e.g., AES)
* index 1: mode (e.g., CTR)
* index 2: padding (e.g., NoPadding)
*/
String[] parts = new String[3];
int count = 0;
StringTokenizer parser = new StringTokenizer(transformation, "/");
while (parser.hasMoreTokens() && count < 3) {
parts[count++] = parser.nextToken().trim();
}
if (count != 3 || parser.hasMoreTokens()) {
throw new NoSuchAlgorithmException("Invalid transformation format: " +
transformation);
}
return new Transform(parts[0], parts[1], parts[2]);
} }
/** /**
@ -99,7 +168,7 @@ public static final OpensslCipher getInstance(int algorithm,
* @param iv crypto iv * @param iv crypto iv
*/ */
public void init(int mode, byte[] key, byte[] iv) { public void init(int mode, byte[] key, byte[] iv) {
context = init(context, mode, algorithm, padding, key, iv); context = init(context, mode, alg, padding, key, iv);
} }
/** /**

View File

@ -38,21 +38,18 @@ public void testGetInstance() throws Exception {
if (!OpensslCipher.isNativeCodeLoaded()) { if (!OpensslCipher.isNativeCodeLoaded()) {
return; return;
} }
OpensslCipher cipher = OpensslCipher.getInstance(OpensslCipher.AES_CTR, OpensslCipher cipher = OpensslCipher.getInstance("AES/CTR/NoPadding");
OpensslCipher.PADDING_NOPADDING);
Assert.assertTrue(cipher != null); Assert.assertTrue(cipher != null);
try { try {
cipher = OpensslCipher.getInstance(OpensslCipher.AES_CTR + 100, cipher = OpensslCipher.getInstance("AES2/CTR/NoPadding");
OpensslCipher.PADDING_NOPADDING);
Assert.fail("Should specify correct algorithm."); Assert.fail("Should specify correct algorithm.");
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// Expect NoSuchAlgorithmException // Expect NoSuchAlgorithmException
} }
try { try {
cipher = OpensslCipher.getInstance(OpensslCipher.AES_CTR, cipher = OpensslCipher.getInstance("AES/CTR/NoPadding2");
OpensslCipher.PADDING_NOPADDING + 100);
Assert.fail("Should specify correct padding."); Assert.fail("Should specify correct padding.");
} catch (NoSuchPaddingException e) { } catch (NoSuchPaddingException e) {
// Expect NoSuchPaddingException // Expect NoSuchPaddingException
@ -64,8 +61,7 @@ public void testUpdateArguments() throws Exception {
if (!OpensslCipher.isNativeCodeLoaded()) { if (!OpensslCipher.isNativeCodeLoaded()) {
return; return;
} }
OpensslCipher cipher = OpensslCipher.getInstance(OpensslCipher.AES_CTR, OpensslCipher cipher = OpensslCipher.getInstance("AES/CTR/NoPadding");
OpensslCipher.PADDING_NOPADDING);
Assert.assertTrue(cipher != null); Assert.assertTrue(cipher != null);
cipher.init(OpensslCipher.ENCRYPT_MODE, key, iv); cipher.init(OpensslCipher.ENCRYPT_MODE, key, iv);
@ -100,8 +96,7 @@ public void testDoFinalArguments() throws Exception {
if (!OpensslCipher.isNativeCodeLoaded()) { if (!OpensslCipher.isNativeCodeLoaded()) {
return; return;
} }
OpensslCipher cipher = OpensslCipher.getInstance(OpensslCipher.AES_CTR, OpensslCipher cipher = OpensslCipher.getInstance("AES/CTR/NoPadding");
OpensslCipher.PADDING_NOPADDING);
Assert.assertTrue(cipher != null); Assert.assertTrue(cipher != null);
cipher.init(OpensslCipher.ENCRYPT_MODE, key, iv); cipher.init(OpensslCipher.ENCRYPT_MODE, key, iv);

View File

@ -8,9 +8,6 @@ fs-encryption (Unreleased)
IMPROVEMENTS IMPROVEMENTS
HADOOP-10693. Implementation of AES-CTR CryptoCodec using JNI to OpenSSL
(hitliuyi via cmccabe)
HDFS-6387. HDFS CLI admin tool for creating & deleting an HDFS-6387. HDFS CLI admin tool for creating & deleting an
encryption zone. (clamb) encryption zone. (clamb)