4a75fd462c
Co-authored-by: Francisco Ferrari Bihurriet <fferrari@redhat.com> Co-authored-by: Martin Balao <mbalao@openjdk.org> Reviewed-by: valeriep
518 lines
24 KiB
Java
518 lines
24 KiB
Java
/*
|
|
* Copyright (c) 2023, Red Hat, Inc.
|
|
*
|
|
* 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.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.ReflectiveOperationException;
|
|
import java.math.BigInteger;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.security.InvalidKeyException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.Provider;
|
|
import java.security.Security;
|
|
import java.security.spec.InvalidKeySpecException;
|
|
import java.security.spec.KeySpec;
|
|
import java.util.Arrays;
|
|
|
|
import javax.crypto.SecretKey;
|
|
import javax.crypto.SecretKeyFactory;
|
|
import javax.crypto.interfaces.PBEKey;
|
|
import javax.crypto.spec.PBEKeySpec;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8301553
|
|
* @summary test key derivation on a SunPKCS11 SecretKeyFactory service
|
|
* @library /test/lib ..
|
|
* @modules java.base/com.sun.crypto.provider:open
|
|
* @run main/othervm/timeout=30 TestPBKD
|
|
*/
|
|
|
|
public final class TestPBKD extends PKCS11Test {
|
|
private static final String sep = "======================================" +
|
|
"===================================";
|
|
|
|
private enum Configuration {
|
|
// Pass password, salt and iterations to a
|
|
// SecretKeyFactory through a PBEKeySpec.
|
|
PBEKeySpec,
|
|
|
|
// Pass password, salt and iterations and iterations to a
|
|
// SecretKeyFactory through an anonymous class implementing
|
|
// the javax.crypto.interfaces.PBEKey interface.
|
|
AnonymousPBEKey,
|
|
}
|
|
|
|
private static Provider sunJCE = Security.getProvider("SunJCE");
|
|
|
|
private static BigInteger i(byte[] data) {
|
|
return new BigInteger(1, data);
|
|
}
|
|
|
|
private record AssertionData(String algo, PBEKeySpec keySpec,
|
|
BigInteger expectedKey) {}
|
|
|
|
private static AssertionData p12PBKDAssertionData(String algo,
|
|
char[] password, int keyLen, String hashAlgo, int blockLen,
|
|
String staticExpectedKeyString) {
|
|
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, keyLen);
|
|
BigInteger staticExpectedKey = new BigInteger(staticExpectedKeyString,
|
|
16);
|
|
BigInteger expectedKey;
|
|
try {
|
|
// Since we need to access an internal
|
|
// SunJCE API, we use reflection.
|
|
Class<?> PKCS12PBECipherCore = Class.forName(
|
|
"com.sun.crypto.provider.PKCS12PBECipherCore");
|
|
|
|
Field macKeyField = PKCS12PBECipherCore.getDeclaredField("MAC_KEY");
|
|
macKeyField.setAccessible(true);
|
|
int MAC_KEY = (int) macKeyField.get(null);
|
|
|
|
Method deriveMethod = PKCS12PBECipherCore.getDeclaredMethod(
|
|
"derive", char[].class, byte[].class, int.class,
|
|
int.class, int.class, String.class, int.class);
|
|
deriveMethod.setAccessible(true);
|
|
expectedKey = i((byte[]) deriveMethod.invoke(null,
|
|
keySpec.getPassword(), keySpec.getSalt(),
|
|
keySpec.getIterationCount(), keySpec.getKeyLength() / 8,
|
|
MAC_KEY, hashAlgo, blockLen));
|
|
checkAssertionValues(expectedKey, staticExpectedKey);
|
|
} catch (ReflectiveOperationException ignored) {
|
|
expectedKey = staticExpectedKey;
|
|
}
|
|
return new AssertionData(algo, keySpec, expectedKey);
|
|
}
|
|
|
|
private static AssertionData pbkd2AssertionData(String algo,
|
|
char[] password, int keyLen, String kdfAlgo,
|
|
String staticExpectedKeyString) {
|
|
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, keyLen);
|
|
BigInteger staticExpectedKey = new BigInteger(staticExpectedKeyString,
|
|
16);
|
|
BigInteger expectedKey = null;
|
|
if (sunJCE != null) {
|
|
try {
|
|
expectedKey = i(SecretKeyFactory.getInstance(kdfAlgo, sunJCE)
|
|
.generateSecret(keySpec).getEncoded());
|
|
checkAssertionValues(expectedKey, staticExpectedKey);
|
|
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
|
// Move to staticExpectedKey as it's unlikely
|
|
// that any of the algorithms are available.
|
|
sunJCE = null;
|
|
}
|
|
}
|
|
if (expectedKey == null) {
|
|
expectedKey = staticExpectedKey;
|
|
}
|
|
return new AssertionData(algo, keySpec, expectedKey);
|
|
}
|
|
|
|
private static void checkAssertionValues(BigInteger expectedValue,
|
|
BigInteger staticExpectedValue) {
|
|
if (!expectedValue.equals(staticExpectedValue)) {
|
|
printHex("SunJCE value", expectedValue);
|
|
printHex("Static value", staticExpectedValue);
|
|
throw new Error("Static and SunJCE values do not match.");
|
|
}
|
|
}
|
|
|
|
private static final char[] pwd = "123456\uA4F7".toCharArray();
|
|
private static final char[] emptyPwd = new char[0];
|
|
private static final byte[] salt = "abcdefgh".getBytes(
|
|
StandardCharsets.UTF_8);
|
|
private static final int iterations = 1000;
|
|
|
|
// Generated with SunJCE. Keep a reference to some
|
|
// entries for tests executing invalid conditions.
|
|
private static final AssertionData hmacPBESHA1Data =
|
|
p12PBKDAssertionData("HmacPBESHA1", pwd, 160, "SHA-1", 64,
|
|
"13156c6bee8e13ef568231e0174651afa5a358b0");
|
|
private static final AssertionData hmacPBESHA224Data =
|
|
p12PBKDAssertionData("HmacPBESHA224", pwd, 224, "SHA-224", 64,
|
|
"d93acf4b3bea8a89d098e290928840c0b693a30cad0117f70ace50c2");
|
|
private static final AssertionData pbeWithHmacSHA512AndAES256Data =
|
|
pbkd2AssertionData("PBEWithHmacSHA512AndAES_256", pwd, 256,
|
|
"PBKDF2WithHmacSHA512", "845560159e2f3f51dad8d6e0feccc898" +
|
|
"7e3077595f90b60ab96d4f29203927b0");
|
|
private static final AssertionData pbkdf2WithHmacSHA256Data =
|
|
pbkd2AssertionData("PBKDF2WithHmacSHA256", pwd, 384,
|
|
"PBKDF2WithHmacSHA256", "6851e387278dd5a3a0d05e4d742f59d8" +
|
|
"44984e3e9b619488a42b93dd6453f630ae3e2ad7ed809fa9e98a7921" +
|
|
"87d62e84");
|
|
private static final AssertionData[] assertionData = new AssertionData[]{
|
|
hmacPBESHA1Data,
|
|
hmacPBESHA224Data,
|
|
p12PBKDAssertionData("HmacPBESHA256", pwd, 256, "SHA-256", 64,
|
|
"1bb3ed1ffb784ed32f59b4d7515971699af99cf67a2e574000964c8e" +
|
|
"1eba1c45"),
|
|
p12PBKDAssertionData("HmacPBESHA384", pwd, 384, "SHA-384", 128,
|
|
"d4ce121d3cec88a8c8b0c6225f7f996b72d76017c2d91bc51fd47985" +
|
|
"86d1012d1ad03a39fdcd0fdc438d164ab50259fc"),
|
|
p12PBKDAssertionData("HmacPBESHA512", pwd, 512, "SHA-512", 128,
|
|
"5f80b350986e5156669193eaa42a107e7d6636d82fb550f67af5b2c2" +
|
|
"f546d977b70e52bbbcb6bb8976f9d3f0eaf9bfef5306c50ee5ccda3e" +
|
|
"e4c4c7c8421fe4d"),
|
|
pbkd2AssertionData("PBEWithHmacSHA1AndAES_128", pwd, 128,
|
|
"PBKDF2WithHmacSHA1", "29958f3f1c942e50903189eb7f1ba09d"),
|
|
pbkd2AssertionData("PBEWithHmacSHA224AndAES_128", pwd, 128,
|
|
"PBKDF2WithHmacSHA224", "e328140e31f4ffb15af806986c23ee4e"),
|
|
pbkd2AssertionData("PBEWithHmacSHA256AndAES_128", pwd, 128,
|
|
"PBKDF2WithHmacSHA256", "6851e387278dd5a3a0d05e4d742f59d8"),
|
|
pbkd2AssertionData("PBEWithHmacSHA384AndAES_128", pwd, 128,
|
|
"PBKDF2WithHmacSHA384", "5570e2fb1a664910f055b71643b52351"),
|
|
pbkd2AssertionData("PBEWithHmacSHA512AndAES_128", pwd, 128,
|
|
"PBKDF2WithHmacSHA512", "845560159e2f3f51dad8d6e0feccc898"),
|
|
pbkd2AssertionData("PBEWithHmacSHA1AndAES_256", pwd, 256,
|
|
"PBKDF2WithHmacSHA1", "29958f3f1c942e50903189eb7f1ba09d40" +
|
|
"b5552da5e645dad4b5911ce0f2f06b"),
|
|
pbkd2AssertionData("PBEWithHmacSHA224AndAES_256", pwd, 256,
|
|
"PBKDF2WithHmacSHA224", "e328140e31f4ffb15af806986c23ee4e" +
|
|
"7daa2119fee8c64aef7c1f4c1871724e"),
|
|
pbkd2AssertionData("PBEWithHmacSHA256AndAES_256", pwd, 256,
|
|
"PBKDF2WithHmacSHA256", "6851e387278dd5a3a0d05e4d742f59d8" +
|
|
"44984e3e9b619488a42b93dd6453f630"),
|
|
pbkd2AssertionData("PBEWithHmacSHA384AndAES_256", pwd, 256,
|
|
"PBKDF2WithHmacSHA384", "5570e2fb1a664910f055b71643b52351" +
|
|
"d7d0ad3a18912086f80d974f2acc2efb"),
|
|
pbeWithHmacSHA512AndAES256Data,
|
|
pbkd2AssertionData("PBKDF2WithHmacSHA1", pwd, 240,
|
|
"PBKDF2WithHmacSHA1", "29958f3f1c942e50903189eb7f1ba09d40" +
|
|
"b5552da5e645dad4b5911ce0f2"),
|
|
pbkd2AssertionData("PBKDF2WithHmacSHA224", pwd, 336,
|
|
"PBKDF2WithHmacSHA224", "e328140e31f4ffb15af806986c23ee4e" +
|
|
"7daa2119fee8c64aef7c1f4c1871724e0ea628577e0ab54fa7c6"),
|
|
pbkdf2WithHmacSHA256Data,
|
|
pbkd2AssertionData("PBKDF2WithHmacSHA384", pwd, 576,
|
|
"PBKDF2WithHmacSHA384", "5570e2fb1a664910f055b71643b52351" +
|
|
"d7d0ad3a18912086f80d974f2acc2efba52650d4bf872455820f24c8" +
|
|
"46742161da84a1b4c3f197f4347308e8841a8971cf686aef29107396"),
|
|
pbkd2AssertionData("PBKDF2WithHmacSHA512", pwd, 768,
|
|
"PBKDF2WithHmacSHA512", "845560159e2f3f51dad8d6e0feccc898" +
|
|
"7e3077595f90b60ab96d4f29203927b00aa1a11e4d19d4f275a7f453" +
|
|
"14be500dacc3c1de9f704827b396463ccaa8957344d41bd64d9d09ff" +
|
|
"474e776469d326b1ee6ee5a5d854b86d3d7a25084afd6d6f"),
|
|
p12PBKDAssertionData("HmacPBESHA512", emptyPwd, 512, "SHA-512",
|
|
128, "90b6e088490c6c5e6b6e81209bd769d27df3868cae79591577a" +
|
|
"c35b46e4c6ebcc4b90f4943e3cb165f9d1789d938235f4b35ba74df9" +
|
|
"e509fbbb7aa329a432445"),
|
|
pbkd2AssertionData("PBEWithHmacSHA512AndAES_256", emptyPwd, 256,
|
|
"PBKDF2WithHmacSHA512", "3a5c5fd11e4d381b32e11baa93d7b128" +
|
|
"09e016e48e0542c5d3453fc240a0fa76"),
|
|
};
|
|
|
|
public void main(Provider sunPKCS11) throws Exception {
|
|
System.out.println("SunPKCS11: " + sunPKCS11.getName());
|
|
|
|
// Test valid cases.
|
|
for (Configuration conf : Configuration.values()) {
|
|
for (AssertionData data : assertionData) {
|
|
testValidWith(sunPKCS11, data, conf);
|
|
}
|
|
}
|
|
|
|
// Test invalid cases.
|
|
testInvalidTranslateKey(sunPKCS11);
|
|
testInvalidGenerateSecret(sunPKCS11);
|
|
testInvalidGetKeySpec(sunPKCS11);
|
|
|
|
System.out.println("TEST PASS - OK");
|
|
}
|
|
|
|
private static void testValidWith(Provider sunPKCS11, AssertionData data,
|
|
Configuration conf) throws Exception {
|
|
System.out.println(sep + System.lineSeparator() + data.algo
|
|
+ " (with " + conf.name() + ")");
|
|
|
|
SecretKeyFactory skf = SecretKeyFactory.getInstance(data.algo,
|
|
sunPKCS11);
|
|
SecretKey derivedKey = switch (conf) {
|
|
case PBEKeySpec -> skf.generateSecret(data.keySpec);
|
|
case AnonymousPBEKey -> skf.translateKey(getAnonymousPBEKey(
|
|
data.algo, data.keySpec));
|
|
};
|
|
BigInteger derivedKeyValue = i(derivedKey.getEncoded());
|
|
printHex("Derived Key", derivedKeyValue);
|
|
|
|
if (!derivedKeyValue.equals(data.expectedKey)) {
|
|
printHex("Expected Derived Key", data.expectedKey);
|
|
throw new Exception("Expected Derived Key did not match");
|
|
}
|
|
|
|
if (skf.translateKey(derivedKey) != derivedKey) {
|
|
throw new Exception("SecretKeyFactory::translateKey must return " +
|
|
"the same key when a P11PBEKey from the same token is " +
|
|
"passed");
|
|
}
|
|
|
|
testGetKeySpec(data, skf, derivedKey);
|
|
if (sunJCE != null && data.algo.startsWith("PBKDF2")) {
|
|
testTranslateP11PBEKeyToSunJCE(data.algo, (PBEKey) derivedKey);
|
|
}
|
|
}
|
|
|
|
private static SecretKey getAnonymousPBEKey(String algorithm,
|
|
PBEKeySpec keySpec) {
|
|
return new PBEKey() {
|
|
public byte[] getSalt() { return keySpec.getSalt(); }
|
|
public int getIterationCount() {
|
|
return keySpec.getIterationCount();
|
|
}
|
|
public String getAlgorithm() { return algorithm; }
|
|
public String getFormat() { return "RAW"; }
|
|
public char[] getPassword() { return keySpec.getPassword(); }
|
|
public byte[] getEncoded() {
|
|
return new byte[keySpec.getKeyLength() / 8];
|
|
}
|
|
};
|
|
}
|
|
|
|
private static void printHex(String title, BigInteger b) {
|
|
String repr = (b == null) ? "buffer is null" : b.toString(16);
|
|
System.out.println(title + ": " + repr + System.lineSeparator());
|
|
}
|
|
|
|
private static void testGetKeySpec(AssertionData data,
|
|
SecretKeyFactory skf, SecretKey derivedKey) throws Exception {
|
|
System.out.println(sep + System.lineSeparator()
|
|
+ "SecretKeyFactory::getKeySpec() (for " + data.algo + ")");
|
|
KeySpec skfKeySpec = skf.getKeySpec(derivedKey, PBEKeySpec.class);
|
|
if (skfKeySpec instanceof PBEKeySpec skfPBEKeySpec) {
|
|
char[] specPassword = skfPBEKeySpec.getPassword();
|
|
byte[] specSalt = skfPBEKeySpec.getSalt();
|
|
int specIterations = skfPBEKeySpec.getIterationCount();
|
|
int specKeyLength = skfPBEKeySpec.getKeyLength();
|
|
System.out.println(" spec key length (bits): " + specKeyLength);
|
|
System.out.println(" spec password: "
|
|
+ String.valueOf(specPassword));
|
|
System.out.println(" spec iteration count: " + specIterations);
|
|
printHex(" spec salt", i(specSalt));
|
|
|
|
if (!Arrays.equals(specPassword, data.keySpec.getPassword())) {
|
|
throw new Exception("Password differs");
|
|
}
|
|
if (!Arrays.equals(specSalt, data.keySpec.getSalt())) {
|
|
throw new Exception("Salt differs");
|
|
}
|
|
if (specIterations != data.keySpec.getIterationCount()) {
|
|
throw new Exception("Iteration count differs");
|
|
}
|
|
if (specKeyLength != data.keySpec.getKeyLength()) {
|
|
throw new Exception("Key length differs");
|
|
}
|
|
} else {
|
|
throw new Exception("Invalid key spec type: " + skfKeySpec);
|
|
}
|
|
|
|
// Test extracting key bytes with a SecretKeySpec.
|
|
SecretKeySpec secretKeySpec = (SecretKeySpec)
|
|
skf.getKeySpec(derivedKey, SecretKeySpec.class);
|
|
if (!Arrays.equals(secretKeySpec.getEncoded(),
|
|
derivedKey.getEncoded())) {
|
|
throw new Exception("Unable to extract key bytes with a " +
|
|
"SecretKeySpec");
|
|
}
|
|
}
|
|
|
|
private static void testTranslateP11PBEKeyToSunJCE(String algorithm,
|
|
PBEKey p11PbeK) throws Exception {
|
|
System.out.println(sep + System.lineSeparator()
|
|
+ "Translate P11PBEKey to SunJCE (for " + algorithm + ")");
|
|
SecretKey jceK = SecretKeyFactory.getInstance(algorithm, sunJCE)
|
|
.translateKey(p11PbeK);
|
|
BigInteger jceEncoded = i(jceK.getEncoded());
|
|
printHex(" translated to SunJCE", jceEncoded);
|
|
if (jceK instanceof PBEKey jcePbeK) {
|
|
if (!Arrays.equals(jcePbeK.getPassword(), p11PbeK.getPassword())) {
|
|
throw new Exception("Password differs");
|
|
}
|
|
if (!Arrays.equals(jcePbeK.getSalt(), p11PbeK.getSalt())) {
|
|
throw new Exception("Salt differs");
|
|
}
|
|
if (jcePbeK.getIterationCount() != p11PbeK.getIterationCount()) {
|
|
throw new Exception("Iteration count differs");
|
|
}
|
|
if (!jceEncoded.equals(i(p11PbeK.getEncoded()))) {
|
|
throw new Exception("Encoded key differs");
|
|
}
|
|
} else {
|
|
throw new Exception("Unexpected key type for SunJCE key: "
|
|
+ jceK.getClass().getName());
|
|
}
|
|
}
|
|
|
|
@FunctionalInterface
|
|
private interface Action {
|
|
void run() throws Exception;
|
|
}
|
|
|
|
private static void assertThrows(Class<?> expectedExc, String expectedMsg,
|
|
Action action) throws Exception {
|
|
String shtExpected = "Should have thrown '"
|
|
+ expectedExc.getSimpleName() + ": " + expectedMsg + "'";
|
|
try {
|
|
action.run();
|
|
} catch (Exception e) {
|
|
if (expectedExc.isAssignableFrom(e.getClass()) &&
|
|
e.getMessage().equals(expectedMsg)) {
|
|
return;
|
|
}
|
|
e.printStackTrace();
|
|
throw new Exception(shtExpected + ", but threw '" +
|
|
e.getClass().getSimpleName() + ": " + e.getMessage() + "'");
|
|
}
|
|
throw new Exception(shtExpected + ", but it didn't throw");
|
|
}
|
|
|
|
private static void testInvalidTranslateKey(Provider sunPKCS11)
|
|
throws Exception {
|
|
System.out.println(sep + System.lineSeparator()
|
|
+ "Invalid SecretKeyFactory::translateKey tests");
|
|
|
|
SecretKeyFactory skf1 = SecretKeyFactory.getInstance(
|
|
hmacPBESHA1Data.algo, sunPKCS11);
|
|
SecretKeyFactory skf2 = SecretKeyFactory.getInstance("AES", sunPKCS11);
|
|
SecretKeyFactory skf3 = SecretKeyFactory.getInstance(
|
|
pbkdf2WithHmacSHA256Data.algo, sunPKCS11);
|
|
PBEKey p11PbeKey = (PBEKey) skf1.translateKey(getAnonymousPBEKey(
|
|
skf1.getAlgorithm(), hmacPBESHA1Data.keySpec));
|
|
Class<?> e = InvalidKeyException.class;
|
|
|
|
System.out.println(" * Non-PBEKey key to PBE SecretKeyFactory");
|
|
assertThrows(e, "PBE service requires a PBE key",
|
|
() -> skf1.translateKey(new SecretKeySpec(
|
|
new byte[10], hmacPBESHA1Data.algo)));
|
|
|
|
System.out.println(" * PBEKey key to PBE SecretKeyFactory of a " +
|
|
"different algorithm");
|
|
assertThrows(e, "Cannot use a " + hmacPBESHA1Data.algo + " key for a " +
|
|
hmacPBESHA224Data.algo + " service",
|
|
() -> SecretKeyFactory.getInstance(hmacPBESHA224Data.algo,
|
|
sunPKCS11).translateKey(p11PbeKey));
|
|
|
|
System.out.println(" * Non-AES PBEKey key to AES SecretKeyFactory");
|
|
assertThrows(e, "Cannot use a " + hmacPBESHA1Data.algo + " key for a " +
|
|
skf2.getAlgorithm() + " service",
|
|
() -> skf2.translateKey(p11PbeKey));
|
|
|
|
System.out.println(" * Inconsistent key length between key and " +
|
|
"algorithm");
|
|
PBEKeySpec kSpec1 = new PBEKeySpec(pwd, salt, 1, 16);
|
|
assertThrows(e, InvalidKeySpecException.class.getName() + ": Key " +
|
|
"length is invalid for " + skf1.getAlgorithm() + " (expecting" +
|
|
" " + hmacPBESHA1Data.keySpec.getKeyLength() + " but was " +
|
|
kSpec1.getKeyLength() + ")",
|
|
() -> skf1.translateKey(getAnonymousPBEKey(
|
|
skf1.getAlgorithm(), kSpec1)));
|
|
|
|
System.out.println(" * Invalid key length in bits");
|
|
PBEKeySpec kSpec2 = new PBEKeySpec(pwd, salt, 1);
|
|
assertThrows(e, InvalidKeySpecException.class.getName() + ": Key " +
|
|
"length must be multiple of 8 and greater than zero",
|
|
() -> skf3.translateKey(getAnonymousPBEKey(
|
|
skf3.getAlgorithm(), kSpec2)));
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
private static void testInvalidGenerateSecret(Provider sunPKCS11)
|
|
throws Exception {
|
|
System.out.println(sep + System.lineSeparator()
|
|
+ "Invalid SecretKeyFactory::generateSecret tests");
|
|
|
|
SecretKeyFactory skf1 = SecretKeyFactory.getInstance(
|
|
hmacPBESHA1Data.algo, sunPKCS11);
|
|
SecretKeyFactory skf2 = SecretKeyFactory.getInstance(
|
|
pbeWithHmacSHA512AndAES256Data.algo, sunPKCS11);
|
|
SecretKeyFactory skf3 = SecretKeyFactory.getInstance(
|
|
"PBKDF2WithHmacSHA512", sunPKCS11);
|
|
SecretKeyFactory skf4 = SecretKeyFactory.getInstance("AES", sunPKCS11);
|
|
Class<?> e = InvalidKeySpecException.class;
|
|
|
|
System.out.println(" * Missing salt and iteration count");
|
|
assertThrows(e, "Salt not found",
|
|
() -> skf1.generateSecret(new PBEKeySpec(pwd)));
|
|
|
|
System.out.println(" * Inconsistent key length between spec and " +
|
|
"algorithm");
|
|
PBEKeySpec kSpec = new PBEKeySpec(pwd, salt, 1, 16);
|
|
assertThrows(e, "Key length is invalid for " + skf1.getAlgorithm() +
|
|
" (expecting " + hmacPBESHA1Data.keySpec.getKeyLength() +
|
|
" but was " + kSpec.getKeyLength() + ")",
|
|
() -> skf1.generateSecret(kSpec));
|
|
assertThrows(e, "Key length is invalid for " + skf2.getAlgorithm() +
|
|
" (expecting " + pbeWithHmacSHA512AndAES256Data.keySpec
|
|
.getKeyLength() + " but was " + kSpec.getKeyLength() + ")",
|
|
() -> skf2.generateSecret(kSpec));
|
|
|
|
System.out.println(" * Invalid key length in bits");
|
|
String msg = "Key length must be multiple of 8 and greater than zero";
|
|
assertThrows(e, msg,
|
|
() -> skf3.generateSecret(new PBEKeySpec(pwd, salt, 1)));
|
|
assertThrows(e, msg,
|
|
() -> skf3.generateSecret(new PBEKeySpec(pwd, salt, 1, 3)));
|
|
|
|
System.out.println(" * PBEKeySpec to non-PBE SecretKeyFactory");
|
|
assertThrows(e, "Unsupported spec: javax.crypto.spec.PBEKeySpec",
|
|
() -> skf4.generateSecret(kSpec));
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
private static void testInvalidGetKeySpec(Provider sunPKCS11)
|
|
throws Exception {
|
|
System.out.println(sep + System.lineSeparator()
|
|
+ "Invalid SecretKeyFactory::getKeySpec tests");
|
|
|
|
SecretKeyFactory skf1 = SecretKeyFactory.getInstance(
|
|
hmacPBESHA1Data.algo, sunPKCS11);
|
|
SecretKeyFactory skf2 = SecretKeyFactory.getInstance(
|
|
"AES", sunPKCS11);
|
|
PBEKey p11PbeKey = (PBEKey) skf1.translateKey(getAnonymousPBEKey(
|
|
skf1.getAlgorithm(), hmacPBESHA1Data.keySpec));
|
|
Class<?> e = InvalidKeySpecException.class;
|
|
|
|
System.out.println(" * null KeySpec class");
|
|
assertThrows(e, "key and keySpec must not be null",
|
|
() -> skf1.getKeySpec(p11PbeKey, null));
|
|
|
|
System.out.println(" * Invalid key type for PBEKeySpec");
|
|
assertThrows(e, "Unsupported spec: " + PBEKeySpec.class.getName(),
|
|
() -> skf1.getKeySpec(new SecretKeySpec(new byte[16],
|
|
skf1.getAlgorithm()), PBEKeySpec.class));
|
|
|
|
System.out.println(" * Invalid PBE key and PBEKeySpec for " +
|
|
skf2.getAlgorithm() + " SecretKeyFactory");
|
|
assertThrows(e, "Unsupported spec: " + PBEKeySpec.class.getName(),
|
|
() -> skf2.getKeySpec(p11PbeKey, PBEKeySpec.class));
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
main(new TestPBKD());
|
|
}
|
|
}
|