8002277: Refactor two PBE classes to simplify maintenance
Reviewed-by: weijun
This commit is contained in:
parent
141ef68f82
commit
61ddbef368
src/java.base/share/classes/com/sun/crypto/provider
test/jdk/com/sun/crypto/provider/Cipher/PBE
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, 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
|
||||
@ -47,7 +47,8 @@ import javax.crypto.*;
|
||||
* @since 1.5
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
public final class ARCFOURCipher extends CipherSpi {
|
||||
public sealed class ARCFOURCipher extends CipherSpi
|
||||
permits PKCS12PBECipherCore.PBEWithSHA1AndRC4 {
|
||||
|
||||
// state array S, 256 entries. The entries are 8-bit, but we use an int[]
|
||||
// because int arithmetic is much faster than in Java than bytes.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, 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
|
||||
@ -44,7 +44,8 @@ import javax.crypto.spec.*;
|
||||
* @see DESCipher
|
||||
*/
|
||||
|
||||
public final class DESedeCipher extends CipherSpi {
|
||||
public sealed class DESedeCipher extends CipherSpi
|
||||
permits PKCS12PBECipherCore.PBEWithSHA1AndDESede {
|
||||
|
||||
/*
|
||||
* internal CipherCore object which does the real work.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, 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
|
||||
@ -166,6 +166,24 @@ abstract class PBES2Core extends CipherSpi {
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] check(byte[] salt)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (salt != null && salt.length < 8) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Salt must be at least 8 bytes long");
|
||||
}
|
||||
return salt;
|
||||
}
|
||||
|
||||
private static int check(int iCount)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (iCount < 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Iteration count must be a positive number");
|
||||
}
|
||||
return iCount == 0 ? DEFAULT_COUNT : iCount;
|
||||
}
|
||||
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
@ -177,6 +195,10 @@ abstract class PBES2Core extends CipherSpi {
|
||||
|
||||
byte[] passwdBytes = key.getEncoded();
|
||||
char[] passwdChars = null;
|
||||
salt = null;
|
||||
iCount = 0;
|
||||
ivSpec = null;
|
||||
|
||||
PBEKeySpec pbeSpec;
|
||||
try {
|
||||
if ((passwdBytes == null) ||
|
||||
@ -184,89 +206,58 @@ abstract class PBES2Core extends CipherSpi {
|
||||
throw new InvalidKeyException("Missing password");
|
||||
}
|
||||
|
||||
// TBD: consolidate the salt, ic and IV parameter checks below
|
||||
boolean doEncrypt = ((opmode == Cipher.ENCRYPT_MODE) ||
|
||||
(opmode == Cipher.WRAP_MODE));
|
||||
|
||||
// Extract salt and iteration count from the key, if present
|
||||
if (key instanceof javax.crypto.interfaces.PBEKey) {
|
||||
salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
|
||||
if (salt != null && salt.length < 8) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Salt must be at least 8 bytes long");
|
||||
}
|
||||
iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
|
||||
if (iCount == 0) {
|
||||
iCount = DEFAULT_COUNT;
|
||||
} else if (iCount < 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Iteration count must be a positive number");
|
||||
}
|
||||
}
|
||||
|
||||
// Extract salt, iteration count and IV from the params, if present
|
||||
if (params == null) {
|
||||
if (salt == null) {
|
||||
// generate random salt and use default iteration count
|
||||
salt = new byte[DEFAULT_SALT_LENGTH];
|
||||
random.nextBytes(salt);
|
||||
iCount = DEFAULT_COUNT;
|
||||
}
|
||||
if ((opmode == Cipher.ENCRYPT_MODE) ||
|
||||
(opmode == Cipher.WRAP_MODE)) {
|
||||
// generate random IV
|
||||
byte[] ivBytes = new byte[blkSize];
|
||||
random.nextBytes(ivBytes);
|
||||
ivSpec = new IvParameterSpec(ivBytes);
|
||||
}
|
||||
} else {
|
||||
if (!(params instanceof PBEParameterSpec)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong parameter type: PBE expected");
|
||||
}
|
||||
// salt and iteration count from the params take precedence
|
||||
byte[] specSalt = ((PBEParameterSpec) params).getSalt();
|
||||
if (specSalt != null && specSalt.length < 8) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Salt must be at least 8 bytes long");
|
||||
}
|
||||
salt = specSalt;
|
||||
int specICount = ((PBEParameterSpec) params).getIterationCount();
|
||||
if (specICount == 0) {
|
||||
specICount = DEFAULT_COUNT;
|
||||
} else if (specICount < 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Iteration count must be a positive number");
|
||||
}
|
||||
iCount = specICount;
|
||||
|
||||
AlgorithmParameterSpec specParams =
|
||||
((PBEParameterSpec) params).getParameterSpec();
|
||||
if (specParams != null) {
|
||||
if (specParams instanceof IvParameterSpec) {
|
||||
ivSpec = (IvParameterSpec)specParams;
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Wrong parameter type: IV expected");
|
||||
}
|
||||
} else if ((opmode == Cipher.ENCRYPT_MODE) ||
|
||||
(opmode == Cipher.WRAP_MODE)) {
|
||||
// Extract from the supplied PBE params, if present
|
||||
if (params instanceof PBEParameterSpec pbeParams) {
|
||||
// salt should be non-null per PBEParameterSpec
|
||||
salt = check(pbeParams.getSalt());
|
||||
iCount = check(pbeParams.getIterationCount());
|
||||
AlgorithmParameterSpec ivParams = pbeParams.getParameterSpec();
|
||||
if (ivParams instanceof IvParameterSpec iv) {
|
||||
ivSpec = iv;
|
||||
} else if (ivParams == null && doEncrypt) {
|
||||
// generate random IV
|
||||
byte[] ivBytes = new byte[blkSize];
|
||||
random.nextBytes(ivBytes);
|
||||
ivSpec = new IvParameterSpec(ivBytes);
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Missing parameter type: IV expected");
|
||||
"Wrong parameter type: IV expected");
|
||||
}
|
||||
} else if (params == null && doEncrypt) {
|
||||
// Try extracting from the key if present. If unspecified,
|
||||
// PBEKey returns null and 0 respectively.
|
||||
if (key instanceof javax.crypto.interfaces.PBEKey pbeKey) {
|
||||
salt = check(pbeKey.getSalt());
|
||||
iCount = check(pbeKey.getIterationCount());
|
||||
}
|
||||
if (salt == null) {
|
||||
// generate random salt
|
||||
salt = new byte[DEFAULT_SALT_LENGTH];
|
||||
random.nextBytes(salt);
|
||||
}
|
||||
if (iCount == 0) {
|
||||
// use default iteration count
|
||||
iCount = DEFAULT_COUNT;
|
||||
}
|
||||
// generate random IV
|
||||
byte[] ivBytes = new byte[blkSize];
|
||||
random.nextBytes(ivBytes);
|
||||
ivSpec = new IvParameterSpec(ivBytes);
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Wrong parameter type: PBE expected");
|
||||
}
|
||||
|
||||
passwdChars = new char[passwdBytes.length];
|
||||
for (int i = 0; i < passwdChars.length; i++)
|
||||
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
|
||||
|
||||
pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
|
||||
} finally {
|
||||
// password char[] was cloned in PBEKeySpec constructor,
|
||||
// so we can zero it out here
|
||||
} finally {
|
||||
if (passwdChars != null) Arrays.fill(passwdChars, '\0');
|
||||
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, 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
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
@ -44,15 +46,9 @@ import javax.security.auth.DestroyFailedException;
|
||||
* @see javax.crypto.CipherSpi
|
||||
*/
|
||||
final class PKCS12PBECipherCore {
|
||||
|
||||
// TBD: replace CipherCore with a CipherSpi object to simplify maintenance
|
||||
|
||||
private CipherCore cipher;
|
||||
private int blockSize;
|
||||
private int keySize;
|
||||
private int keyLength; // in bits
|
||||
private String algo = null;
|
||||
private String pbeAlgo = null;
|
||||
private final int keySize; // in bytes
|
||||
private final String algo;
|
||||
private final String pbeAlgo;
|
||||
private byte[] salt = null;
|
||||
private int iCount = 0;
|
||||
|
||||
@ -171,63 +167,31 @@ final class PKCS12PBECipherCore {
|
||||
System.arraycopy(src, 0, dst, off + start, len - off);
|
||||
}
|
||||
|
||||
PKCS12PBECipherCore(String symmCipherAlg, int defKeySize)
|
||||
throws NoSuchAlgorithmException {
|
||||
// holder for the derived key and iv
|
||||
private record KeyAndIv(SecretKey key, IvParameterSpec iv)
|
||||
implements Closeable {
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
key.destroy();
|
||||
} catch (DestroyFailedException e) {
|
||||
// Ignore the failure
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PKCS12PBECipherCore(String symmCipherAlg, int keySizeInBits)
|
||||
throws NoSuchAlgorithmException {
|
||||
|
||||
algo = symmCipherAlg;
|
||||
keyLength = defKeySize * 8;
|
||||
if (algo.equals("RC4")) {
|
||||
pbeAlgo = "PBEWithSHA1AndRC4_" + keyLength;
|
||||
} else {
|
||||
SymmetricCipher symmCipher = null;
|
||||
if (algo.equals("DESede")) {
|
||||
symmCipher = new DESedeCrypt();
|
||||
pbeAlgo = "PBEWithSHA1AndDESede";
|
||||
keyLength = 112; // effective key length
|
||||
} else if (algo.equals("RC2")) {
|
||||
symmCipher = new RC2Crypt();
|
||||
pbeAlgo = "PBEWithSHA1AndRC2_" + keyLength;
|
||||
} else {
|
||||
throw new NoSuchAlgorithmException("No Cipher implementation " +
|
||||
"for PBEWithSHA1And" + algo);
|
||||
}
|
||||
blockSize = symmCipher.getBlockSize();
|
||||
cipher = new CipherCore(symmCipher, blockSize);
|
||||
cipher.setMode("CBC");
|
||||
try {
|
||||
cipher.setPadding("PKCS5Padding");
|
||||
} catch (NoSuchPaddingException nspe) {
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
keySize = defKeySize;
|
||||
}
|
||||
|
||||
void implSetMode(String mode) throws NoSuchAlgorithmException {
|
||||
if ((mode != null) && (!mode.equalsIgnoreCase("CBC"))) {
|
||||
throw new NoSuchAlgorithmException("Invalid cipher mode: "
|
||||
+ mode);
|
||||
}
|
||||
}
|
||||
|
||||
void implSetPadding(String padding) throws NoSuchPaddingException {
|
||||
if ((padding != null) &&
|
||||
(!padding.equalsIgnoreCase("PKCS5Padding"))) {
|
||||
throw new NoSuchPaddingException("Invalid padding scheme: " +
|
||||
padding);
|
||||
}
|
||||
}
|
||||
|
||||
int implGetBlockSize() {
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
int implGetOutputSize(int inLen) {
|
||||
return cipher.getOutputSize(inLen);
|
||||
}
|
||||
|
||||
byte[] implGetIV() {
|
||||
return cipher.getIV();
|
||||
pbeAlgo = switch (algo) {
|
||||
case "RC4" -> "PBEWithSHA1AndRC4_" + keySizeInBits;
|
||||
case "DESede" -> "PBEWithSHA1AndDESede";
|
||||
case "RC2" -> "PBEWithSHA1AndRC2_" + keySizeInBits;
|
||||
default -> throw new NoSuchAlgorithmException(
|
||||
"No Cipher implementation for PBEWithSHA1And" + algo);
|
||||
};
|
||||
keySize = keySizeInBits >> 3;
|
||||
}
|
||||
|
||||
AlgorithmParameters implGetParameters() {
|
||||
@ -256,16 +220,10 @@ final class PKCS12PBECipherCore {
|
||||
return params;
|
||||
}
|
||||
|
||||
void implInit(int opmode, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws InvalidKeyException,
|
||||
InvalidAlgorithmParameterException {
|
||||
implInit(opmode, key, params, random, null);
|
||||
}
|
||||
|
||||
void implInit(int opmode, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random, CipherSpi cipherImpl)
|
||||
throws InvalidKeyException,
|
||||
InvalidAlgorithmParameterException {
|
||||
// returns derived Key and Iv
|
||||
KeyAndIv implInit(int opmode, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
char[] passwdChars = null;
|
||||
salt = null;
|
||||
iCount = 0;
|
||||
@ -345,495 +303,240 @@ final class PKCS12PBECipherCore {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("IterationCount must be a positive number");
|
||||
}
|
||||
|
||||
byte[] derivedKey = derive(passwdChars, salt, iCount,
|
||||
keySize, CIPHER_KEY);
|
||||
SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
|
||||
Arrays.fill(derivedKey, (byte)0);
|
||||
|
||||
try {
|
||||
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
|
||||
((ARCFOURCipher) cipherImpl).engineInit(opmode, cipherKey, random);
|
||||
|
||||
} else {
|
||||
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
|
||||
CIPHER_IV);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
|
||||
|
||||
// initialize the underlying cipher
|
||||
cipher.init(opmode, cipherKey, ivSpec, random);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
cipherKey.destroy();
|
||||
} catch (DestroyFailedException e) {
|
||||
// Ignore the failure
|
||||
}
|
||||
}
|
||||
return switch (algo) {
|
||||
case "RC4" -> new KeyAndIv(cipherKey, null);
|
||||
case "RC2", "DESede" -> new KeyAndIv(cipherKey,
|
||||
new IvParameterSpec(derive(passwdChars, salt, iCount, 8,
|
||||
CIPHER_IV)));
|
||||
default ->
|
||||
throw new ProviderException("Unsupported cipher impl: "
|
||||
+ algo);
|
||||
};
|
||||
} finally {
|
||||
Arrays.fill(passwdChars, '\0');
|
||||
}
|
||||
}
|
||||
|
||||
void implInit(int opmode, Key key, AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
implInit(opmode, key, params, random, null);
|
||||
}
|
||||
|
||||
void implInit(int opmode, Key key, AlgorithmParameters params,
|
||||
SecureRandom random, CipherSpi cipherImpl)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
AlgorithmParameterSpec paramSpec = null;
|
||||
if (params != null) {
|
||||
try {
|
||||
paramSpec = params.getParameterSpec(PBEParameterSpec.class);
|
||||
} catch (InvalidParameterSpecException ipse) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"requires PBE parameters");
|
||||
}
|
||||
private static final PBEParameterSpec toParamSpec(AlgorithmParameters ap)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (ap == null) {
|
||||
return null;
|
||||
}
|
||||
implInit(opmode, key, paramSpec, random, cipherImpl);
|
||||
}
|
||||
|
||||
void implInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
implInit(opmode, key, random, null);
|
||||
}
|
||||
|
||||
void implInit(int opmode, Key key, SecureRandom random,
|
||||
CipherSpi cipherImpl) throws InvalidKeyException {
|
||||
try {
|
||||
implInit(opmode, key, (AlgorithmParameterSpec) null, random,
|
||||
cipherImpl);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
throw new InvalidKeyException("requires PBE parameters");
|
||||
return ap.getParameterSpec(PBEParameterSpec.class);
|
||||
} catch (InvalidParameterSpecException ipse) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"requires PBE parameters");
|
||||
}
|
||||
}
|
||||
|
||||
byte[] implUpdate(byte[] in, int inOff, int inLen) {
|
||||
return cipher.update(in, inOff, inLen);
|
||||
}
|
||||
|
||||
int implUpdate(byte[] in, int inOff, int inLen, byte[] out, int outOff)
|
||||
throws ShortBufferException {
|
||||
return cipher.update(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
|
||||
byte[] implDoFinal(byte[] in, int inOff, int inLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return cipher.doFinal(in, inOff, inLen);
|
||||
}
|
||||
|
||||
int implDoFinal(byte[] in, int inOff, int inLen, byte[] out, int outOff)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
return cipher.doFinal(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
|
||||
int implGetKeySize(Key key) throws InvalidKeyException {
|
||||
return keyLength;
|
||||
return keySize << 3; // in bits
|
||||
}
|
||||
|
||||
byte[] implWrap(Key key) throws IllegalBlockSizeException,
|
||||
InvalidKeyException {
|
||||
return cipher.wrap(key);
|
||||
}
|
||||
|
||||
Key implUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return cipher.unwrap(wrappedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
|
||||
public static final class PBEWithSHA1AndDESede extends CipherSpi {
|
||||
public static final class PBEWithSHA1AndDESede extends DESedeCipher {
|
||||
private final PKCS12PBECipherCore core;
|
||||
|
||||
public PBEWithSHA1AndDESede() throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("DESede", 24);
|
||||
}
|
||||
protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return core.implDoFinal(in, inOff, inLen);
|
||||
}
|
||||
protected int engineDoFinal(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
return core.implDoFinal(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected int engineGetBlockSize() {
|
||||
return core.implGetBlockSize();
|
||||
}
|
||||
protected byte[] engineGetIV() {
|
||||
return core.implGetIV();
|
||||
try {
|
||||
super.engineSetMode("CBC");
|
||||
super.engineSetPadding("PKCS5Padding");
|
||||
} catch (NoSuchPaddingException nspe) {
|
||||
// should never happen
|
||||
}
|
||||
core = new PKCS12PBECipherCore("DESede", 192);
|
||||
}
|
||||
@Override
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
return core.implGetKeySize(key);
|
||||
}
|
||||
protected int engineGetOutputSize(int inLen) {
|
||||
return core.implGetOutputSize(inLen);
|
||||
return 112; // effective key size
|
||||
}
|
||||
@Override
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
return core.implGetParameters();
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random);
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
try (var derived = core.implInit(opmode, key, params, random)) {
|
||||
super.engineInit(opmode, derived.key(), derived.iv(), random);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random);
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
engineInit(opmode, key, toParamSpec(params), random);
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
core.implInit(opmode, key, random);
|
||||
throws InvalidKeyException {
|
||||
try {
|
||||
engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {
|
||||
core.implSetMode(mode);
|
||||
throws NoSuchAlgorithmException {
|
||||
if (!"CBC".equalsIgnoreCase(mode)) {
|
||||
throw new NoSuchAlgorithmException("Unsupported mode: " + mode);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineSetPadding(String paddingScheme)
|
||||
throws NoSuchPaddingException {
|
||||
core.implSetPadding(paddingScheme);
|
||||
}
|
||||
protected Key engineUnwrap(byte[] wrappedKey,
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
|
||||
return core.implUpdate(in, inOff, inLen);
|
||||
}
|
||||
protected int engineUpdate(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException {
|
||||
return core.implUpdate(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected byte[] engineWrap(Key key)
|
||||
throws IllegalBlockSizeException, InvalidKeyException {
|
||||
return core.implWrap(key);
|
||||
throws NoSuchPaddingException {
|
||||
if (!"PKCS5Padding".equalsIgnoreCase(paddingScheme)) {
|
||||
throw new NoSuchPaddingException("Unsupported padding: " +
|
||||
paddingScheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PBEWithSHA1AndRC2_40 extends CipherSpi {
|
||||
static sealed class PBEWithSHA1AndRC2 extends RC2Cipher {
|
||||
private final PKCS12PBECipherCore core;
|
||||
|
||||
public PBEWithSHA1AndRC2(int keysize) throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("RC2", keysize);
|
||||
try {
|
||||
super.engineSetMode("CBC");
|
||||
super.engineSetPadding("PKCS5Padding");
|
||||
} catch (NoSuchPaddingException nspe) {
|
||||
// should never happen
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
return core.implGetParameters();
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
try (var derived = core.implInit(opmode, key, params, random)) {
|
||||
super.engineInit(opmode, derived.key(), derived.iv(), random);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
engineInit(opmode, key, toParamSpec(params), random);
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
try {
|
||||
engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {
|
||||
if (!"CBC".equalsIgnoreCase(mode)) {
|
||||
throw new NoSuchAlgorithmException("Unsupported mode: " + mode);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineSetPadding(String paddingScheme)
|
||||
throws NoSuchPaddingException {
|
||||
if (!"PKCS5Padding".equalsIgnoreCase(paddingScheme)) {
|
||||
throw new NoSuchPaddingException("Unsupported padding: " +
|
||||
paddingScheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PBEWithSHA1AndRC2_40 extends PBEWithSHA1AndRC2 {
|
||||
public PBEWithSHA1AndRC2_40() throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("RC2", 5);
|
||||
}
|
||||
protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return core.implDoFinal(in, inOff, inLen);
|
||||
}
|
||||
protected int engineDoFinal(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
return core.implDoFinal(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected int engineGetBlockSize() {
|
||||
return core.implGetBlockSize();
|
||||
}
|
||||
protected byte[] engineGetIV() {
|
||||
return core.implGetIV();
|
||||
}
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
return core.implGetKeySize(key);
|
||||
}
|
||||
protected int engineGetOutputSize(int inLen) {
|
||||
return core.implGetOutputSize(inLen);
|
||||
}
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
return core.implGetParameters();
|
||||
}
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random);
|
||||
}
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random);
|
||||
}
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
core.implInit(opmode, key, random);
|
||||
}
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {
|
||||
core.implSetMode(mode);
|
||||
}
|
||||
protected void engineSetPadding(String paddingScheme)
|
||||
throws NoSuchPaddingException {
|
||||
core.implSetPadding(paddingScheme);
|
||||
}
|
||||
protected Key engineUnwrap(byte[] wrappedKey,
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
|
||||
return core.implUpdate(in, inOff, inLen);
|
||||
}
|
||||
protected int engineUpdate(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException {
|
||||
return core.implUpdate(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected byte[] engineWrap(Key key)
|
||||
throws IllegalBlockSizeException, InvalidKeyException {
|
||||
return core.implWrap(key);
|
||||
super(40);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PBEWithSHA1AndRC2_128 extends CipherSpi {
|
||||
private final PKCS12PBECipherCore core;
|
||||
public static final class PBEWithSHA1AndRC2_128 extends PBEWithSHA1AndRC2 {
|
||||
public PBEWithSHA1AndRC2_128() throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("RC2", 16);
|
||||
super(128);
|
||||
}
|
||||
protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return core.implDoFinal(in, inOff, inLen);
|
||||
}
|
||||
protected int engineDoFinal(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
return core.implDoFinal(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected int engineGetBlockSize() {
|
||||
return core.implGetBlockSize();
|
||||
}
|
||||
protected byte[] engineGetIV() {
|
||||
return core.implGetIV();
|
||||
}
|
||||
|
||||
static sealed class PBEWithSHA1AndRC4 extends ARCFOURCipher {
|
||||
private final PKCS12PBECipherCore core;
|
||||
|
||||
public PBEWithSHA1AndRC4(int keysize) throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("RC4", keysize);
|
||||
}
|
||||
@Override
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
return core.implGetKeySize(key);
|
||||
}
|
||||
protected int engineGetOutputSize(int inLen) {
|
||||
return core.implGetOutputSize(inLen);
|
||||
}
|
||||
@Override
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
return core.implGetParameters();
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random);
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
try (var derived = core.implInit(opmode, key, params, random)) {
|
||||
super.engineInit(opmode, derived.key(), derived.iv(), random);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random);
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
engineInit(opmode, key, toParamSpec(params), random);
|
||||
}
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
core.implInit(opmode, key, random);
|
||||
throws InvalidKeyException {
|
||||
try {
|
||||
engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
|
||||
} catch (InvalidAlgorithmParameterException iape) {
|
||||
// should never happen
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {
|
||||
core.implSetMode(mode);
|
||||
throws NoSuchAlgorithmException {
|
||||
if (!"ECB".equalsIgnoreCase(mode)) {
|
||||
throw new NoSuchAlgorithmException("Unsupported mode: " + mode);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void engineSetPadding(String paddingScheme)
|
||||
throws NoSuchPaddingException {
|
||||
core.implSetPadding(paddingScheme);
|
||||
}
|
||||
protected Key engineUnwrap(byte[] wrappedKey,
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
|
||||
return core.implUpdate(in, inOff, inLen);
|
||||
}
|
||||
protected int engineUpdate(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException {
|
||||
return core.implUpdate(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected byte[] engineWrap(Key key)
|
||||
throws IllegalBlockSizeException, InvalidKeyException {
|
||||
return core.implWrap(key);
|
||||
throws NoSuchPaddingException {
|
||||
if (!"NoPadding".equalsIgnoreCase(paddingScheme)) {
|
||||
throw new NoSuchPaddingException("Unsupported padding: " +
|
||||
paddingScheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PBEWithSHA1AndRC4_40 extends CipherSpi {
|
||||
private static final int RC4_KEYSIZE = 5;
|
||||
private final PKCS12PBECipherCore core;
|
||||
private final ARCFOURCipher cipher;
|
||||
|
||||
public static final class PBEWithSHA1AndRC4_40 extends PBEWithSHA1AndRC4 {
|
||||
public PBEWithSHA1AndRC4_40() throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE);
|
||||
cipher = new ARCFOURCipher();
|
||||
}
|
||||
protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return cipher.engineDoFinal(in, inOff, inLen);
|
||||
}
|
||||
protected int engineDoFinal(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
return cipher.engineDoFinal(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected int engineGetBlockSize() {
|
||||
return cipher.engineGetBlockSize();
|
||||
}
|
||||
protected byte[] engineGetIV() {
|
||||
return cipher.engineGetIV();
|
||||
}
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
return RC4_KEYSIZE;
|
||||
}
|
||||
protected int engineGetOutputSize(int inLen) {
|
||||
return cipher.engineGetOutputSize(inLen);
|
||||
}
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
return core.implGetParameters();
|
||||
}
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random, cipher);
|
||||
}
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random, cipher);
|
||||
}
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
core.implInit(opmode, key, random, cipher);
|
||||
}
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {
|
||||
if (mode.equalsIgnoreCase("ECB") == false) {
|
||||
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
||||
}
|
||||
}
|
||||
protected void engineSetPadding(String paddingScheme)
|
||||
throws NoSuchPaddingException {
|
||||
if (paddingScheme.equalsIgnoreCase("NoPadding") == false) {
|
||||
throw new NoSuchPaddingException("Padding must be NoPadding");
|
||||
}
|
||||
}
|
||||
protected Key engineUnwrap(byte[] wrappedKey,
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
|
||||
return cipher.engineUpdate(in, inOff, inLen);
|
||||
}
|
||||
protected int engineUpdate(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException {
|
||||
return cipher.engineUpdate(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected byte[] engineWrap(Key key)
|
||||
throws IllegalBlockSizeException, InvalidKeyException {
|
||||
return cipher.engineWrap(key);
|
||||
super(40);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PBEWithSHA1AndRC4_128 extends CipherSpi {
|
||||
private static final int RC4_KEYSIZE = 16;
|
||||
private final PKCS12PBECipherCore core;
|
||||
private final ARCFOURCipher cipher;
|
||||
|
||||
public static final class PBEWithSHA1AndRC4_128 extends PBEWithSHA1AndRC4 {
|
||||
public PBEWithSHA1AndRC4_128() throws NoSuchAlgorithmException {
|
||||
core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE);
|
||||
cipher = new ARCFOURCipher();
|
||||
}
|
||||
protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return cipher.engineDoFinal(in, inOff, inLen);
|
||||
}
|
||||
protected int engineDoFinal(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
return cipher.engineDoFinal(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected int engineGetBlockSize() {
|
||||
return cipher.engineGetBlockSize();
|
||||
}
|
||||
protected byte[] engineGetIV() {
|
||||
return cipher.engineGetIV();
|
||||
}
|
||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||
return RC4_KEYSIZE;
|
||||
}
|
||||
protected int engineGetOutputSize(int inLen) {
|
||||
return cipher.engineGetOutputSize(inLen);
|
||||
}
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
return core.implGetParameters();
|
||||
}
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random, cipher);
|
||||
}
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
core.implInit(opmode, key, params, random, cipher);
|
||||
}
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
core.implInit(opmode, key, random, cipher);
|
||||
}
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {
|
||||
if (mode.equalsIgnoreCase("ECB") == false) {
|
||||
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
||||
}
|
||||
}
|
||||
protected void engineSetPadding(String paddingScheme)
|
||||
throws NoSuchPaddingException {
|
||||
if (paddingScheme.equalsIgnoreCase("NoPadding") == false) {
|
||||
throw new NoSuchPaddingException("Padding must be NoPadding");
|
||||
}
|
||||
}
|
||||
protected Key engineUnwrap(byte[] wrappedKey,
|
||||
String wrappedKeyAlgorithm,
|
||||
int wrappedKeyType)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
|
||||
wrappedKeyType);
|
||||
}
|
||||
protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
|
||||
return cipher.engineUpdate(in, inOff, inLen);
|
||||
}
|
||||
protected int engineUpdate(byte[] in, int inOff, int inLen,
|
||||
byte[] out, int outOff)
|
||||
throws ShortBufferException {
|
||||
return cipher.engineUpdate(in, inOff, inLen, out, outOff);
|
||||
}
|
||||
protected byte[] engineWrap(Key key)
|
||||
throws IllegalBlockSizeException, InvalidKeyException {
|
||||
return cipher.engineWrap(key);
|
||||
super(128);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, 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
|
||||
@ -39,7 +39,8 @@ import javax.crypto.spec.RC2ParameterSpec;
|
||||
* @since 1.5
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
public final class RC2Cipher extends CipherSpi {
|
||||
public sealed class RC2Cipher extends CipherSpi
|
||||
permits PKCS12PBECipherCore.PBEWithSHA1AndRC2 {
|
||||
|
||||
// internal CipherCore & RC2Crypt objects which do the real work.
|
||||
private final CipherCore core;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4953553
|
||||
* @bug 4953553 8002277
|
||||
* @summary Ensure that InvalidKeyException is thrown when decrypting
|
||||
* without parameters as javadoc has stated.
|
||||
* @author Valerie Peng
|
||||
@ -32,22 +32,108 @@
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
import javax.crypto.interfaces.PBEKey;
|
||||
|
||||
public class DecryptWithoutParameters {
|
||||
|
||||
public static void main(String argv[]) throws Exception {
|
||||
String algo = "PBEWithMD5AndDES";
|
||||
Cipher cipher = Cipher.getInstance(algo, "SunJCE");
|
||||
SecretKey key = new SecretKeySpec(new byte[5], algo);
|
||||
private static String[] PBES1ALGOS = {
|
||||
"PBEWithMD5AndDES",
|
||||
"PBEWithSHA1AndDESede",
|
||||
"PBEWithSHA1AndRC2_40",
|
||||
"PBEWithSHA1AndRC2_128",
|
||||
"PBEWithSHA1AndRC4_40",
|
||||
"PBEWithSHA1AndRC4_128",
|
||||
};
|
||||
|
||||
private static String[] PBES2ALGOS = {
|
||||
"PBEWithHmacSHA1AndAES_128",
|
||||
"PBEWithHmacSHA224AndAES_128",
|
||||
"PBEWithHmacSHA256AndAES_128",
|
||||
"PBEWithHmacSHA384AndAES_128",
|
||||
"PBEWithHmacSHA512AndAES_128",
|
||||
};
|
||||
|
||||
// return true if Cipher.init() fails with
|
||||
// InvalidAlgorithmParameterException
|
||||
private static boolean test(Cipher c, SecretKey key,
|
||||
AlgorithmParameterSpec spec) throws InvalidKeyException {
|
||||
System.out.println("Testing " + c.getAlgorithm());
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, key);
|
||||
throw new Exception("Should throw InvalidKeyException when " +
|
||||
"decrypting without parameters");
|
||||
} catch (InvalidKeyException ike) {
|
||||
System.out.println("Test Passed: InvalidKeyException thrown");
|
||||
c.init(Cipher.DECRYPT_MODE, key, spec);
|
||||
System.out.println("=> failed");
|
||||
return false;
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
System.out.println("=> ok, got expected IAPE " + e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static final class MyPBEKey implements PBEKey {
|
||||
private String algo;
|
||||
private PBEKeySpec spec;
|
||||
|
||||
MyPBEKey(String algo, PBEKeySpec spec) {
|
||||
this.algo = algo;
|
||||
this.spec = spec;
|
||||
}
|
||||
public int getIterationCount() {
|
||||
return spec.getIterationCount();
|
||||
}
|
||||
public char[] getPassword() {
|
||||
return spec.getPassword();
|
||||
}
|
||||
public byte[] getSalt() {
|
||||
return spec.getSalt();
|
||||
}
|
||||
public void destroy() {
|
||||
spec.clearPassword();
|
||||
spec = null;
|
||||
}
|
||||
public boolean isDestroyed() {
|
||||
return spec == null;
|
||||
}
|
||||
public String getAlgorithm() {
|
||||
return algo;
|
||||
}
|
||||
public byte[] getEncoded() {
|
||||
return new byte[5];
|
||||
}
|
||||
public String getFormat() {
|
||||
// not used
|
||||
return "Proprietary";
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String argv[]) throws Exception {
|
||||
boolean status = true;
|
||||
|
||||
for (String algo : PBES1ALGOS) {
|
||||
Cipher cipher = Cipher.getInstance(algo, "SunJCE");
|
||||
SecretKey key = new SecretKeySpec(new byte[5], algo);
|
||||
status = status && test(cipher, key, null);
|
||||
}
|
||||
|
||||
byte[] salt = "atleast8bytes".getBytes();
|
||||
int iterCount = 123456;
|
||||
PBEParameterSpec spec = new PBEParameterSpec(salt, iterCount);
|
||||
for (String algo : PBES2ALGOS) {
|
||||
Cipher cipher = Cipher.getInstance(algo, "SunJCE");
|
||||
SecretKey key = new SecretKeySpec(new byte[5], algo);
|
||||
PBEKey key2 = new MyPBEKey(algo,
|
||||
new PBEKeySpec("phrase".toCharArray(), salt, iterCount));
|
||||
// null param
|
||||
status = status && test(cipher, key, null);
|
||||
status = status && test(cipher, key2, null);
|
||||
// param has salt and iterCount but missing iv
|
||||
status = status && test(cipher, key, spec);
|
||||
status = status && test(cipher, key2, spec);
|
||||
}
|
||||
if (!status) {
|
||||
throw new Exception("One or more test failed");
|
||||
}
|
||||
System.out.println("All tests passed");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user