8041787: Need new regressions tests for buffer handling for PBE algorithms
Reviewed-by: vinnie
This commit is contained in:
parent
03788b946a
commit
9ba56436a1
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Provider;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
/**
|
||||
* Wrapper class to test a given AES-based PBE algorithm.
|
||||
*
|
||||
* @author Alexander Fomin
|
||||
*/
|
||||
public class AESPBEWrapper extends PBEWrapper {
|
||||
|
||||
private AlgorithmParameters pbeParams;
|
||||
|
||||
/**
|
||||
* Constructor. Instantiate Cipher using the given AES-based PBE algorithms.
|
||||
*
|
||||
* @param p security Provider
|
||||
* @param algo PKDF2 algorithm
|
||||
* @param passwd password phrase
|
||||
* @param out print stream
|
||||
* @throws Exception all exceptions are thrown
|
||||
*/
|
||||
public AESPBEWrapper(Provider p, String algo, String passwd,
|
||||
PrintStream out) throws Exception {
|
||||
super(algo,
|
||||
SecretKeyFactory.getInstance(algo, p).generateSecret(
|
||||
new PBEKeySpec(passwd.toCharArray())),
|
||||
Cipher.getInstance(algo, p), out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform encryption/decryption operation (depending on the specified
|
||||
* edMode) on the same byte buffer. Compare result with the result at an
|
||||
* allocated buffer. If both results are equal - return true, otherwise
|
||||
* return false.
|
||||
*
|
||||
* @param edMode specified mode
|
||||
* @param inputText text to decrypt
|
||||
* @param offset offset in the text
|
||||
* @param len input length
|
||||
* @return ture - test passed; false - test failed
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(int edMode, byte[] inputText, int offset, int len) {
|
||||
try {
|
||||
// init Cipher
|
||||
if (Cipher.ENCRYPT_MODE == edMode) {
|
||||
ci.init(Cipher.ENCRYPT_MODE, this.key);
|
||||
pbeParams = ci.getParameters();
|
||||
} else {
|
||||
ci.init(Cipher.DECRYPT_MODE, this.key, pbeParams);
|
||||
}
|
||||
|
||||
// First, generate the cipherText at an allocated buffer
|
||||
byte[] outputText = ci.doFinal(inputText, offset, len);
|
||||
|
||||
// Second, generate cipherText again at the same buffer of plainText
|
||||
int myoff = offset / 2;
|
||||
int off = ci.update(inputText, offset, len, inputText, myoff);
|
||||
ci.doFinal(inputText, myoff + off);
|
||||
|
||||
if (this.algo.endsWith("AES_256")) {
|
||||
out.print("Expected exception uncaught, "
|
||||
+ "keyStrength > 128 within " + this.algo);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare to see whether the two results are the same or not
|
||||
return equalsBlock(inputText, myoff, outputText, 0,
|
||||
outputText.length);
|
||||
} catch (Exception ex) {
|
||||
if ((ex instanceof InvalidKeyException)
|
||||
&& this.algo.endsWith("AES_256")) {
|
||||
out.println("Expected InvalidKeyException exception: "
|
||||
+ ex.getMessage());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
out.println("Catch unexpected exception within " + algo);
|
||||
ex.printStackTrace(out);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Valerie PENG
|
||||
* @author Yun Ke
|
||||
* @author Alexander Fomin
|
||||
* @author rhalade
|
||||
*/
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Provider;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.PBEParameterSpec;
|
||||
|
||||
public class PBECipherWrapper extends PBEWrapper {
|
||||
|
||||
private final AlgorithmParameterSpec aps;
|
||||
|
||||
public PBECipherWrapper(
|
||||
Provider p, String algo, String passwd, PrintStream out)
|
||||
throws Exception {
|
||||
super(algo,
|
||||
SecretKeyFactory.getInstance(
|
||||
new StringTokenizer(algo, "/").nextToken(), p).generateSecret(
|
||||
new PBEKeySpec(passwd.toCharArray())),
|
||||
Cipher.getInstance(algo, p), out);
|
||||
|
||||
int SALT_SIZE = 8;
|
||||
aps = new PBEParameterSpec(generateSalt(SALT_SIZE), ITERATION_COUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(int edMode, byte[] inputText, int offset,
|
||||
int len) {
|
||||
StringTokenizer st = new StringTokenizer(algo, "/");
|
||||
String baseAlgo = st.nextToken().toUpperCase();
|
||||
|
||||
// Perform encryption or decryption depends on the specified edMode
|
||||
try {
|
||||
ci.init(edMode, key, aps);
|
||||
|
||||
// First, generate the cipherText at an allocated buffer
|
||||
byte[] outputText = ci.doFinal(inputText, offset, len);
|
||||
|
||||
// Second, generate cipherText again at the same buffer of
|
||||
// plainText
|
||||
int myoff = offset / 2;
|
||||
int off = ci.update(inputText, offset, len, inputText, myoff);
|
||||
|
||||
ci.doFinal(inputText, myoff + off);
|
||||
|
||||
if (baseAlgo.endsWith("TRIPLEDES")
|
||||
|| baseAlgo.endsWith("AES_256")) {
|
||||
out.print("Expected exception uncaught,"
|
||||
+ "keyStrength > 128 within " + this.algo);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare to see whether the two results are the same or not
|
||||
boolean result = equalsBlock(inputText, myoff, outputText, 0,
|
||||
outputText.length);
|
||||
|
||||
return result;
|
||||
} catch (Exception ex) {
|
||||
if ((ex instanceof InvalidKeyException)
|
||||
&& (baseAlgo.endsWith("TRIPLEDES")
|
||||
|| baseAlgo.endsWith("AES_256"))) {
|
||||
out.println("Expected InvalidKeyException exception: "
|
||||
+ ex.getMessage());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
out.println("Catch unexpected exception within " + algo);
|
||||
ex.printStackTrace(out);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8041787
|
||||
* @library .
|
||||
* @build PBEWrapper PBEWrapperCreator PBKDF2Wrapper AESPBEWrapper PBECipherWrapper
|
||||
* @summary Verify that same encrypt/decrypt buffer can be used for PBE ciphers
|
||||
* @author Alexander Fomin
|
||||
* @author rhalade
|
||||
* @run main PBESameBuffer
|
||||
*/
|
||||
import java.io.PrintStream;
|
||||
import java.security.*;
|
||||
import java.util.Random;
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class PBESameBuffer {
|
||||
|
||||
private static final String[] pbeAlgorithms = {
|
||||
"pbeWithMD5ANDdes", "PBEWithMD5AndDES/CBC/PKCS5Padding",
|
||||
"pbeWithMD5ANDtripledes", "PBEWithMD5AndTRIPLEDES/CBC/PKCS5Padding",
|
||||
"PBEwithSHA1AndDESede", "PBEwithSHA1AndDESede/CBC/PKCS5Padding",
|
||||
"PBEwithSHA1AndRC2_40", "PBEwithSHA1AndRC2_40/CBC/PKCS5Padding",
|
||||
"PBEWithSHA1AndRC2_128", "PBEWithSHA1AndRC2_128/CBC/PKCS5Padding",
|
||||
"PBEWithSHA1AndRC4_40", "PBEWithSHA1AndRC4_40/ECB/NoPadding",
|
||||
"PBEWithSHA1AndRC4_128", "PBEWithSHA1AndRC4_128/ECB/NoPadding",
|
||||
"PBEWithHmacSHA1AndAES_128",
|
||||
"PBEWithHmacSHA224AndAES_128",
|
||||
"PBEWithHmacSHA256AndAES_128",
|
||||
"PBEWithHmacSHA384AndAES_128",
|
||||
"PBEWithHmacSHA512AndAES_128",
|
||||
"PBEWithHmacSHA1AndAES_256",
|
||||
"PBEWithHmacSHA224AndAES_256",
|
||||
"PBEWithHmacSHA256AndAES_256",
|
||||
"PBEWithHmacSHA384AndAES_256",
|
||||
"PBEWithHmacSHA512AndAES_256",
|
||||
"PBKDF2WithHmacSHA1",
|
||||
"PBKDF2WithHmacSHA224",
|
||||
"PBKDF2WithHmacSHA256",
|
||||
"PBKDF2WithHmacSHA384",
|
||||
"PBKDF2WithHmacSHA512"
|
||||
};
|
||||
|
||||
private static final String PBEPASS = "Hush, it's supposed to be a secret!";
|
||||
|
||||
private static final int INPUT_LENGTH = 800;
|
||||
private static final int[] OFFSETS = {0, 1, 2, 3};
|
||||
private static final int NUM_PAD_BYTES = 8;
|
||||
private static final int PBKDF2_ADD_PAD_BYTES = 8;
|
||||
|
||||
private static int OUTPUT_OFFSET;
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (!(new PBESameBuffer().test(args, System.out))) {
|
||||
throw new RuntimeException("Some PBE algorithm tests failed");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean test(String[] args, PrintStream out) {
|
||||
boolean result = true;
|
||||
|
||||
Provider p = Security.getProvider("SunJCE");
|
||||
|
||||
for (int loop : OFFSETS) {
|
||||
OUTPUT_OFFSET = loop;
|
||||
|
||||
// generate input data
|
||||
byte[] inputText = new byte[INPUT_LENGTH + NUM_PAD_BYTES
|
||||
+ OUTPUT_OFFSET * 2 + PBKDF2_ADD_PAD_BYTES];
|
||||
new Random().nextBytes(inputText);
|
||||
|
||||
for (String algorithm : pbeAlgorithms) {
|
||||
out.println("=> Testing algorithm " + algorithm + " and offset "
|
||||
+ OUTPUT_OFFSET + ":");
|
||||
|
||||
try {
|
||||
// Initialize Cipher and key for this algorithm
|
||||
PBEWrapper pbeCi = PBEWrapperCreator.createWrapper(p,
|
||||
algorithm,
|
||||
PBEPASS,
|
||||
out);
|
||||
|
||||
// Encrypt
|
||||
if ((pbeCi != null) && (!pbeCi.execute(Cipher.ENCRYPT_MODE,
|
||||
inputText,
|
||||
OUTPUT_OFFSET * 2,
|
||||
INPUT_LENGTH))) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
// PBKDF2 required 16 byte padding
|
||||
int padLength = getPadLength(algorithm);
|
||||
|
||||
// Decrypt
|
||||
// Note: inputText is implicitly padded by the above encrypt
|
||||
// operation so decrypt operation can safely proceed
|
||||
if ((pbeCi != null) && (!pbeCi.execute(Cipher.DECRYPT_MODE,
|
||||
inputText,
|
||||
OUTPUT_OFFSET,
|
||||
INPUT_LENGTH + padLength))) {
|
||||
result = false;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace(out);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the padding length for the given algorithm
|
||||
*
|
||||
* @param theAlgName algorithm name
|
||||
* @return padding length for the given algorithm
|
||||
*/
|
||||
private int getPadLength(String theAlgName) {
|
||||
if (theAlgName.toUpperCase().contains("PBKDF2")) {
|
||||
return NUM_PAD_BYTES + PBKDF2_ADD_PAD_BYTES;
|
||||
}
|
||||
|
||||
if (theAlgName.toUpperCase().contains("AES")) {
|
||||
return NUM_PAD_BYTES + PBKDF2_ADD_PAD_BYTES;
|
||||
}
|
||||
|
||||
return NUM_PAD_BYTES;
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Random;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
/**
|
||||
* PBEWrapper is the abstract class for all concrete PBE Cipher wrappers. A
|
||||
* PBEWrapper object encapsulates the information and behavior needed to test if
|
||||
* the multiple-part encryption/decryption is performing by expected way on the
|
||||
* same byte buffer.
|
||||
*
|
||||
* @author Alexandr Fomin
|
||||
* @author rhalade
|
||||
*/
|
||||
public abstract class PBEWrapper {
|
||||
|
||||
protected final static int ITERATION_COUNT = 1000;
|
||||
|
||||
protected final SecretKey key;
|
||||
protected final Cipher ci;
|
||||
protected final String algo;
|
||||
protected final PrintStream out;
|
||||
|
||||
public PBEWrapper(String pAlgo, SecretKey pKey, Cipher pCi,
|
||||
PrintStream pOut ){
|
||||
this.algo = pAlgo;
|
||||
this.key = pKey;
|
||||
this.ci = pCi;
|
||||
this.out = pOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method need to be implemented in the subclasses.
|
||||
*
|
||||
* @param edMode Cipher mode - encrypt/decrypt
|
||||
* @param inputText byte buffer to process
|
||||
* @param offset offset in byte the inputText
|
||||
* @param len length of byte to process in inputText
|
||||
* @return true if cipher operation is successful, false otherwise
|
||||
*/
|
||||
public abstract boolean execute(int edMode, byte[] inputText, int offset,
|
||||
int len);
|
||||
|
||||
/**
|
||||
* An utility method to prepare "salt" for following Secret Key generation.
|
||||
*
|
||||
* @param numberOfBytes number of bytes in salt
|
||||
* @return randomly generated byte array
|
||||
*/
|
||||
protected static byte[] generateSalt(int numberOfBytes) {
|
||||
byte[] salt = new byte[numberOfBytes];
|
||||
new Random().nextBytes(salt);
|
||||
return salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* An utility method to check if two byte arrays are equal
|
||||
*
|
||||
* @param b1 first byte array
|
||||
* @param off1 offset to compare from in b1
|
||||
* @param b2 second byte array
|
||||
* @param off2 offset to compare from in b2
|
||||
* @param len length to compare
|
||||
* @return true of arrays are equal, false otherwise
|
||||
*/
|
||||
protected boolean equalsBlock(byte[] b1, int off1,
|
||||
byte[] b2, int off2, int len) {
|
||||
for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) {
|
||||
if (b1[i] != b2[j]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.security.Provider;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* An utility class to create PBEWrapper object for the TestCipherSameBuffer
|
||||
* test.
|
||||
*
|
||||
* @author Alexander Fomin
|
||||
*/
|
||||
public class PBEWrapperCreator {
|
||||
|
||||
private static final String PBKDF2 = "PBKDF2";
|
||||
private static final String AES = "AES";
|
||||
|
||||
/**
|
||||
* Create PBEWrapper for the TestCipherSameBuffer test using given
|
||||
* parameters.
|
||||
*
|
||||
* @param p security provider
|
||||
* @param algo algorithms to test
|
||||
* @param passwd a password phrase
|
||||
* @param out print stream object
|
||||
* @return PBEWrapper in accordance to requested algorithm
|
||||
* @throws Exception all exception are thrown.
|
||||
*/
|
||||
public static PBEWrapper createWrapper(Provider p, String algo,
|
||||
String passwd, PrintStream out) throws Exception {
|
||||
if (algo.toUpperCase().contains(PBKDF2)) {
|
||||
return new PBKDF2Wrapper(p, algo, passwd, out);
|
||||
} else if (algo.toUpperCase().contains(AES)) {
|
||||
return new AESPBEWrapper(p, algo, passwd, out);
|
||||
} else {
|
||||
return new PBECipherWrapper(p, algo, passwd, out);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.security.Provider;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* Wrapper class to test a given SecretKeyFactory.PBKDF2 algorithm.
|
||||
*
|
||||
* @author Alexander Fomin
|
||||
*/
|
||||
public class PBKDF2Wrapper extends PBEWrapper {
|
||||
private static final String CIPHER_TANSFORMATION = "AES/CBC/PKCS5Padding";
|
||||
private static final int SALT_SIZE = 64;
|
||||
private static final int PKDF2_DEFAULT_KEY_LEN = 128;
|
||||
|
||||
private static volatile byte[] iv;
|
||||
|
||||
/**
|
||||
* PBKDF2Wrapper constructor. Instantiate Cipher using
|
||||
* "AES/CBC/PKCS5Padding" transformation. Generate a secret key using given
|
||||
* PKDF2 algorithms.
|
||||
*
|
||||
* @param p security Provider
|
||||
* @param algo PKDF2 algorithm
|
||||
* @param passwd password phrase
|
||||
* @param out print stream
|
||||
* @throws Exception all exceptions are thrown
|
||||
*/
|
||||
public PBKDF2Wrapper(Provider p, String algo, String passwd,
|
||||
PrintStream out) throws Exception {
|
||||
super(algo,
|
||||
SecretKeyFactory.getInstance(algo, p).generateSecret(
|
||||
new PBEKeySpec(passwd.toCharArray(),
|
||||
generateSalt(SALT_SIZE), ITERATION_COUNT, PKDF2_DEFAULT_KEY_LEN)),
|
||||
Cipher.getInstance(CIPHER_TANSFORMATION, p), out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform encryption/decryption operation (depending on the specified
|
||||
* edMode) on the same byte buffer. Compare result with the result at an
|
||||
* allocated buffer. If both results are equal - return true, otherwise
|
||||
* return false.
|
||||
*
|
||||
* @param edMode specified mode
|
||||
* @param inputText text to decrypt
|
||||
* @param offset offset in the text
|
||||
* @param len input length
|
||||
* @return ture - test passed; false - test failed
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(int edMode, byte[] inputText, int offset, int len) {
|
||||
int needBytesForResult = -1;
|
||||
String KEY_ALGORITHM = "AES";
|
||||
|
||||
try {
|
||||
// init Cipher
|
||||
if (Cipher.ENCRYPT_MODE == edMode) {
|
||||
ci.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getEncoded(),
|
||||
KEY_ALGORITHM));
|
||||
iv = ci.getParameters().getParameterSpec(IvParameterSpec.class).
|
||||
getIV();
|
||||
} else {
|
||||
ci.init(Cipher.DECRYPT_MODE,
|
||||
new SecretKeySpec(key.getEncoded(), KEY_ALGORITHM),
|
||||
new IvParameterSpec(iv));
|
||||
}
|
||||
|
||||
// First, generate the cipherText at an allocated buffer
|
||||
byte[] outputText = ci.doFinal(inputText, offset, len);
|
||||
|
||||
// Second, generate cipherText again at the same buffer of plainText
|
||||
int myoff = offset / 2;
|
||||
int off = ci.update(inputText, offset, len, inputText, myoff);
|
||||
ci.doFinal(inputText, myoff + off);
|
||||
|
||||
// Compare to see whether the two results are the same or not
|
||||
return equalsBlock(inputText, myoff, outputText, 0,
|
||||
outputText.length);
|
||||
} catch (Exception ex) {
|
||||
out.println("Catch unexpected exception within " + algo
|
||||
+ " " + edMode + ": " + ex.getMessage()
|
||||
+ ". getOutputSize()" + "returned " + needBytesForResult);
|
||||
ex.printStackTrace(out);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
248
jdk/test/com/sun/crypto/provider/Cipher/PBE/PBMacBuffer.java
Normal file
248
jdk/test/com/sun/crypto/provider/Cipher/PBE/PBMacBuffer.java
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Random;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8041787
|
||||
* @summary verify that Mac.update works with different size ByteBuffer
|
||||
* @author Alexander Fomin
|
||||
* @run main PBMacBuffer
|
||||
*/
|
||||
public class PBMacBuffer {
|
||||
|
||||
private final int LARGE_SIZE = 500000;
|
||||
|
||||
public static void main(String[] args) {
|
||||
String[] PBMAC1Algorithms = {
|
||||
"HmacPBESHA1",
|
||||
"PBEWithHmacSHA1",
|
||||
"PBEWithHmacSHA224",
|
||||
"PBEWithHmacSHA256",
|
||||
"PBEWithHmacSHA384",
|
||||
"PBEWithHmacSHA512"
|
||||
};
|
||||
|
||||
String[] PBKDF2Algorithms = {
|
||||
"PBKDF2WithHmacSHA1",
|
||||
"PBKDF2WithHmacSHA224",
|
||||
"PBKDF2WithHmacSHA256",
|
||||
"PBKDF2WithHmacSHA384",
|
||||
"PBKDF2WithHmacSHA512"
|
||||
};
|
||||
|
||||
PBMacBuffer testRunner = new PBMacBuffer();
|
||||
boolean failed = false;
|
||||
|
||||
for (String thePBMacAlgo : PBMAC1Algorithms) {
|
||||
|
||||
for (String thePBKDF2Algo : PBKDF2Algorithms) {
|
||||
|
||||
System.out.println("Running test with " + thePBMacAlgo
|
||||
+ " and " + thePBKDF2Algo + ":");
|
||||
try {
|
||||
if (!testRunner.doTest(thePBMacAlgo, thePBKDF2Algo)) {
|
||||
failed = true;
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException |
|
||||
InvalidKeySpecException e) {
|
||||
failed = true;
|
||||
e.printStackTrace(System.out);
|
||||
System.out.println("Test FAILED.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
throw new RuntimeException("One or more tests failed....");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Mac.update(ByteBuffer input) method. Three test cases are
|
||||
* performed: - large ByteBuffer test case to test if the update() method
|
||||
* process a large ByteBuffer correctly; - empty ByteBuffer test case to
|
||||
* test if the update() method process an empty ByteBuffer correctly; - NULL
|
||||
* ByteBuffer test case to test if the update() method throws expected
|
||||
* IllegalArgumentException exception.
|
||||
*
|
||||
* @param theMacAlgo PBMAC algorithm to test
|
||||
* @param thePBKDF2Algo PBKDF2 algorithm to test
|
||||
* @return true - test passed; false - otherwise.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
* @throws InvalidKeySpecException
|
||||
* @see javax.crypto.Mac
|
||||
*/
|
||||
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException,
|
||||
InvalidKeySpecException {
|
||||
// obtain a SecretKey using PBKDF2
|
||||
SecretKey key = getSecretKey(thePBKDF2Algo);
|
||||
|
||||
// Instantiate Mac object and init it with a SecretKey
|
||||
Mac theMac = Mac.getInstance(theMacAlgo);
|
||||
theMac.init(key);
|
||||
|
||||
// Do large ByteBuffer test case
|
||||
if (!largeByteBufferTest(theMac)) {
|
||||
System.out.println("Large ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do empty ByteBuffer test case
|
||||
if (!emptyByteBufferTest(theMac)) {
|
||||
System.out.println("Empty ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do null ByteBuffer test case
|
||||
if (!nullByteBufferTest(theMac)) {
|
||||
System.out.println("NULL ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Large ByteBuffer test case. Generate random ByteBuffer of LARGE_SIZE
|
||||
* size. Performs MAC operation with the given Mac object (theMac
|
||||
* parameter).Verifies the assertion "Upon return, the buffer's position
|
||||
* will be equal to its limit; its limit will not have changed".
|
||||
*
|
||||
* @param theMac MAC object to test.
|
||||
* @return true - test case passed; false - otherwise;
|
||||
*/
|
||||
protected boolean largeByteBufferTest(Mac theMac) {
|
||||
ByteBuffer buf = generateRandomByteBuffer(LARGE_SIZE);
|
||||
int limitBefore = buf.limit();
|
||||
|
||||
theMac.update(buf);
|
||||
theMac.doFinal();
|
||||
|
||||
int limitAfter = buf.limit();
|
||||
int positonAfter = buf.position();
|
||||
|
||||
if (limitAfter != limitBefore) {
|
||||
System.out.println("FAIL: Buffer's limit has been chenged.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (positonAfter != limitAfter) {
|
||||
System.out.println("FAIL: "
|
||||
+ "Buffer's position isn't equal to its limit");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty ByteBuffer test case. Generates an empty ByteBuffer. Perform MAC
|
||||
* operation. No exceptions are expected.
|
||||
*
|
||||
* @param theMac
|
||||
* @return true - test case pass; exception otherwise
|
||||
*/
|
||||
protected boolean emptyByteBufferTest(Mac theMac) {
|
||||
ByteBuffer buf = generateRandomByteBuffer(0);
|
||||
theMac.update(buf);
|
||||
theMac.doFinal();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* NULL ByteBuffer test case. Pass NULL ByteBuffer to Mac.update(ByteBuffer
|
||||
* buffer) method. An IllegalArgumentException expected.
|
||||
*
|
||||
* @param theMac Mac object to test.
|
||||
* @return true - test case pass; false - otherwise.
|
||||
*/
|
||||
protected boolean nullByteBufferTest(Mac theMac) {
|
||||
try {
|
||||
ByteBuffer buf = null;
|
||||
theMac.update(buf);
|
||||
theMac.doFinal();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected exception has been thrown
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println("FAIL: "
|
||||
+ "IllegalArgumentException hasn't been thrown as expected");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SecretKey for the given PBKDF2 algorithm.
|
||||
*
|
||||
* @param thePBKDF2Algorithm - PBKDF2 algorithm
|
||||
* @return SecretKey according to thePBKDF2Algorithm
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeySpecException
|
||||
*/
|
||||
protected SecretKey getSecretKey(String thePBKDF2Algorithm)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
// Prepare salt
|
||||
byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation
|
||||
new SecureRandom().nextBytes(salt);
|
||||
|
||||
// Generate secret key
|
||||
PBEKeySpec pbeKeySpec = new PBEKeySpec(
|
||||
"A #pwd# implied to be hidden!".toCharArray(),
|
||||
salt, 1000, 128);
|
||||
SecretKeyFactory keyFactory
|
||||
= SecretKeyFactory.getInstance(thePBKDF2Algorithm);
|
||||
return keyFactory.generateSecret(pbeKeySpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* An utility method to generate a random ByteBuffer of the requested size.
|
||||
*
|
||||
* @param size size of the ByteBuffer.
|
||||
* @return ByteBuffer populated random data;
|
||||
*/
|
||||
private ByteBuffer generateRandomByteBuffer(int size) {
|
||||
// generate randome byte array
|
||||
byte[] data = new byte[size];
|
||||
new Random().nextBytes(data);
|
||||
|
||||
// create ByteBuffer
|
||||
ByteBuffer bb = ByteBuffer.wrap(data);
|
||||
|
||||
return bb;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8041787
|
||||
* @summary Check if doFinal and update operation result in same PBMac
|
||||
* @author Alexander Fomin
|
||||
* @run main PBMacDoFinalVsUpdate
|
||||
*/
|
||||
public class PBMacDoFinalVsUpdate {
|
||||
|
||||
public static void main(String[] args) {
|
||||
String[] PBMAC1Algorithms = {
|
||||
"HmacPBESHA1",
|
||||
"PBEWithHmacSHA1",
|
||||
"PBEWithHmacSHA224",
|
||||
"PBEWithHmacSHA256",
|
||||
"PBEWithHmacSHA384",
|
||||
"PBEWithHmacSHA512"
|
||||
};
|
||||
|
||||
String[] PBKDF2Algorithms = {
|
||||
"PBKDF2WithHmacSHA1",
|
||||
"PBKDF2WithHmacSHA224",
|
||||
"PBKDF2WithHmacSHA256",
|
||||
"PBKDF2WithHmacSHA384",
|
||||
"PBKDF2WithHmacSHA512"
|
||||
};
|
||||
|
||||
PBMacDoFinalVsUpdate testRunner = new PBMacDoFinalVsUpdate();
|
||||
boolean failed = false;
|
||||
|
||||
for (String thePBMacAlgo : PBMAC1Algorithms) {
|
||||
|
||||
for (String thePBKDF2Algo : PBKDF2Algorithms) {
|
||||
|
||||
System.out.println("Running test with " + thePBMacAlgo
|
||||
+ " and " + thePBKDF2Algo + ":");
|
||||
try {
|
||||
if (!testRunner.doTest(thePBMacAlgo, thePBKDF2Algo)) {
|
||||
failed = true;
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException |
|
||||
InvalidKeySpecException e) {
|
||||
failed = true;
|
||||
e.printStackTrace(System.out);
|
||||
System.out.println("Test FAILED.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
throw new RuntimeException("One or more tests failed....");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a random generator to initialize a message, instantiate a Mac object
|
||||
* according to the given PBMAC1 algorithm, initialize the object with a
|
||||
* SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),
|
||||
* feed the message into the Mac object all at once and get the output MAC
|
||||
* as result1. Reset the Mac object, chop the message into three pieces,
|
||||
* feed into the Mac object sequentially, and get the output MAC as result2.
|
||||
* Finally, compare result1 and result2 and see if they are the same.
|
||||
*
|
||||
* @param theMacAlgo PBMAC algorithm to test
|
||||
* @param thePBKDF2Algo PBKDF2 algorithm to test
|
||||
* @return true - the test is passed; false - otherwise.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
* @throws InvalidKeySpecException
|
||||
*/
|
||||
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException,
|
||||
InvalidKeySpecException {
|
||||
int OFFSET = 5;
|
||||
|
||||
// Some message for which a MAC result will be calculated
|
||||
byte[] plain = new byte[25];
|
||||
new SecureRandom().nextBytes(plain);
|
||||
|
||||
// Form tail - is one of the three pieces
|
||||
byte[] tail = new byte[plain.length - OFFSET];
|
||||
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
|
||||
|
||||
// Obtain a SecretKey using PBKDF2
|
||||
SecretKey key = getSecretKey(thePBKDF2Algo);
|
||||
|
||||
// Instantiate Mac object and init it with a SecretKey and calc result1
|
||||
Mac theMac = Mac.getInstance(theMacAlgo);
|
||||
theMac.init(key);
|
||||
byte[] result1 = theMac.doFinal(plain);
|
||||
|
||||
if (!isMacLengthExpected(theMacAlgo, result1.length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset Mac and calculate result2
|
||||
theMac.reset();
|
||||
theMac.update(plain[0]);
|
||||
theMac.update(plain, 1, OFFSET - 1);
|
||||
byte[] result2 = theMac.doFinal(tail);
|
||||
|
||||
// Return result
|
||||
if (!java.util.Arrays.equals(result1, result2)) {
|
||||
System.out.println("result1 and result2 are not the same:");
|
||||
System.out.println("result1: " + dumpByteArray(result1));
|
||||
System.out.println("result2: " + dumpByteArray(result2));
|
||||
return false;
|
||||
} else {
|
||||
System.out.println("Resulted MAC with update and doFinal is same");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SecretKey for the given PBKDF2 algorithm.
|
||||
*
|
||||
* @param thePBKDF2Algorithm - PBKDF2 algorithm
|
||||
* @return SecretKey according to thePBKDF2Algorithm
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeySpecException
|
||||
*/
|
||||
protected SecretKey getSecretKey(String thePBKDF2Algorithm)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
// Prepare salt
|
||||
byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation
|
||||
new SecureRandom().nextBytes(salt);
|
||||
|
||||
// Generate secret key
|
||||
PBEKeySpec pbeKeySpec = new PBEKeySpec(
|
||||
"A #pwd# implied to be hidden!".toCharArray(),
|
||||
salt, 1000, 128);
|
||||
SecretKeyFactory keyFactory
|
||||
= SecretKeyFactory.getInstance(thePBKDF2Algorithm);
|
||||
return keyFactory.generateSecret(pbeKeySpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the lengthToCheck is expected length for the given MACAlgo.
|
||||
*
|
||||
* @param MACAlgo PBMAC algorithm
|
||||
* @param lengthToCheck the length of MAC need to check
|
||||
* @return true - lengthToCheck is expected length for the MACAlgo; false -
|
||||
* otherwise.
|
||||
*/
|
||||
protected boolean isMacLengthExpected(String MACAlgo, int lengthToCheck) {
|
||||
java.util.regex.Pattern p = java.util.regex.Pattern.compile("(\\d+)",
|
||||
java.util.regex.Pattern.CASE_INSENSITIVE);
|
||||
java.util.regex.Matcher m = p.matcher(MACAlgo);
|
||||
int val = 0;
|
||||
|
||||
if (m.find()) {
|
||||
val = Integer.parseInt(m.group(1));
|
||||
}
|
||||
|
||||
// HmacPBESHA1 should return MAC 20 byte length
|
||||
if ((val == 1) && (lengthToCheck == 20)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (val / 8) == lengthToCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* An utility method to dump a byte array for debug output.
|
||||
*
|
||||
* @param theByteArray the byte array to dump
|
||||
* @return string representation of the theByteArray in Hex.
|
||||
*/
|
||||
protected String dumpByteArray(byte[] theByteArray) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
for (byte b : theByteArray) {
|
||||
buf.append(Integer.toHexString(b));
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8041787
|
||||
* @summary Verify that for PBEWithMD5AndDES cipher, only CBC mode and
|
||||
* PKCS#5Padding is allowed
|
||||
* @author Yun Ke
|
||||
* @author Bill Situ
|
||||
* @author Yu-Ching (Valerie) PENG
|
||||
* @run main TestCipherKeyWrapperPBEKey
|
||||
*/
|
||||
public class TestCipherPBECons {
|
||||
|
||||
private static final String[] PBEAlgorithms = {"pbeWithMD5ANDdes",
|
||||
"PBEWithMD5AndTripleDES"};
|
||||
private static final String[] cipherModes = {"ECb", "cbC", "cFB", "Cfb32",
|
||||
"OfB", "oFb64", "pCbC"};
|
||||
private static final String[] cipherPaddings = {"Pkcs5Padding", "NoPaDDing"};
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestCipherPBECons test = new TestCipherPBECons();
|
||||
Provider sunjce = Security.getProvider("SunJCE");
|
||||
|
||||
if (!test.runAll(sunjce, System.out)) {
|
||||
throw new RuntimeException("One or more tests have failed....");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean runAll(Provider p, PrintStream out) {
|
||||
boolean finalResult = true;
|
||||
|
||||
for (String algorithm : PBEAlgorithms) {
|
||||
for (String mode : cipherModes) {
|
||||
for (String padding : cipherPaddings) {
|
||||
out.println("Running test with " + algorithm
|
||||
+ "/" + mode + "/" + padding);
|
||||
try {
|
||||
if (!runTest(p, algorithm, mode, padding, out)) {
|
||||
finalResult = false;
|
||||
out.println("STATUS: Failed");
|
||||
} else {
|
||||
out.println("STATUS: Passed");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
finalResult = false;
|
||||
ex.printStackTrace(out);
|
||||
out.println("STATUS:Failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finalResult;
|
||||
}
|
||||
|
||||
public boolean runTest(Provider p, String algo, String mo, String pad,
|
||||
PrintStream out) throws Exception {
|
||||
try {
|
||||
// Initialization
|
||||
Cipher ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, p);
|
||||
|
||||
// No exception thrown, must be of the right mode and right
|
||||
// padding scheme
|
||||
return (mo.equalsIgnoreCase("CBC"))
|
||||
&& (pad.equalsIgnoreCase("PKCS5Padding"));
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
if (p.getName().compareTo("SunJCE") == 0) {
|
||||
if (!(mo.equalsIgnoreCase("CBC")
|
||||
&& pad.equalsIgnoreCase("PKCS5Padding"))) {
|
||||
out.println("NoSuchAlgorithmException is as expected");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
out.println("Caught exception: " + ex.getMessage());
|
||||
throw ex;
|
||||
} catch (NoSuchPaddingException ex) {
|
||||
if (mo.equalsIgnoreCase("CBC")
|
||||
&& pad.equalsIgnoreCase("NoPadding")) {
|
||||
out.println("NoSuchPaddingException is as expected");
|
||||
return true;
|
||||
} else {
|
||||
out.println("Caught unexpected exception: " + ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user