3789983e89
Reviewed-by: darcy, ihse
173 lines
6.7 KiB
Java
173 lines
6.7 KiB
Java
/*
|
|
* Copyright (c) 2015, 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 static java.lang.System.out;
|
|
|
|
import java.security.InvalidAlgorithmParameterException;
|
|
import java.security.InvalidKeyException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.spec.AlgorithmParameterSpec;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import javax.crypto.BadPaddingException;
|
|
import javax.crypto.IllegalBlockSizeException;
|
|
import javax.crypto.SecretKey;
|
|
import javax.crypto.ShortBufferException;
|
|
import javax.crypto.Cipher;
|
|
import javax.crypto.KeyGenerator;
|
|
import javax.crypto.NoSuchPaddingException;
|
|
import javax.crypto.spec.IvParameterSpec;
|
|
|
|
/**
|
|
* Wrapper class to test a given DES algorithm.
|
|
*/
|
|
public class DESCipherWrapper {
|
|
|
|
private final Cipher ci;
|
|
private final byte[] iv;
|
|
private final SecretKey key;
|
|
private final String algo;
|
|
private final String mode;
|
|
private final String pad;
|
|
private final int keyStrength;
|
|
private byte[] resultText = null;
|
|
|
|
public DESCipherWrapper(String algo, String mode, String pad)
|
|
throws NoSuchAlgorithmException, NoSuchPaddingException {
|
|
ci = Cipher.getInstance(algo + "/" + mode + "/" + pad);
|
|
|
|
iv = new byte[8];
|
|
for (int i = 0; i < 8; i++) {
|
|
iv[i] = (byte) (i & 0xff);
|
|
}
|
|
|
|
KeyGenerator kg = KeyGenerator.getInstance(algo);
|
|
key = kg.generateKey();
|
|
keyStrength = algo.equalsIgnoreCase("DESede") ? 112
|
|
: key.getEncoded().length * 8;
|
|
|
|
this.algo = algo;
|
|
this.mode = mode;
|
|
this.pad = pad;
|
|
}
|
|
|
|
public byte[] getResult() {
|
|
return resultText.clone();
|
|
}
|
|
|
|
public void execute(int edMode, byte[] inputText)
|
|
throws InvalidKeyException, InvalidAlgorithmParameterException,
|
|
IllegalBlockSizeException, BadPaddingException,
|
|
ShortBufferException, NoSuchAlgorithmException {
|
|
AlgorithmParameterSpec aps = null;
|
|
|
|
try {
|
|
if (!mode.equalsIgnoreCase("ECB")) {
|
|
aps = new IvParameterSpec(iv);
|
|
}
|
|
ci.init(edMode, key, aps);
|
|
|
|
// Generate a resultText using a single-part enc/dec
|
|
resultText = ci.doFinal(inputText);
|
|
|
|
// Generate outputText for each multi-part en/de-cryption
|
|
/* Combination #1:
|
|
update(byte[], int, int)
|
|
doFinal(byte[], int, int)
|
|
*/
|
|
byte[] part11 = ci.update(inputText, 0, inputText.length);
|
|
byte[] part12 = ci.doFinal();
|
|
byte[] outputText1 = new byte[part11.length + part12.length];
|
|
System.arraycopy(part11, 0, outputText1, 0, part11.length);
|
|
System.arraycopy(part12, 0, outputText1, part11.length,
|
|
part12.length);
|
|
|
|
List<byte[]> outputTexts = new ArrayList<>(4);
|
|
outputTexts.add(outputText1);
|
|
|
|
/* Combination #2:
|
|
update(byte[], int, int)
|
|
doFinal(byte[], int, int, byte[], int)
|
|
*/
|
|
byte[] part21 = ci.update(inputText, 0, inputText.length - 5);
|
|
byte[] part22 = new byte[ci.getOutputSize(inputText.length)];
|
|
int len2 = ci
|
|
.doFinal(inputText, inputText.length - 5, 5, part22, 0);
|
|
byte[] outputText2 = new byte[part21.length + len2];
|
|
System.arraycopy(part21, 0, outputText2, 0, part21.length);
|
|
System.arraycopy(part22, 0, outputText2, part21.length, len2);
|
|
|
|
outputTexts.add(outputText2);
|
|
|
|
/* Combination #3:
|
|
update(byte[], int, int, byte[], int)
|
|
doFinal(byte[], int, int)
|
|
*/
|
|
byte[] part31 = new byte[ci.getOutputSize(inputText.length)];
|
|
int len3 = ci.update(inputText, 0, inputText.length - 8, part31, 0);
|
|
byte[] part32 = ci.doFinal(inputText, inputText.length - 8, 8);
|
|
byte[] outputText3 = new byte[len3 + part32.length];
|
|
System.arraycopy(part31, 0, outputText3, 0, len3);
|
|
System.arraycopy(part32, 0, outputText3, len3, part32.length);
|
|
|
|
outputTexts.add(outputText3);
|
|
|
|
/* Combination #4:
|
|
update(byte[], int, int, byte[], int)
|
|
doFinal(byte[], int, int, byte[], int)
|
|
*/
|
|
byte[] part41 = new byte[ci.getOutputSize(inputText.length)];
|
|
int len4 = ci.update(inputText, 0, inputText.length - 8, part41, 0);
|
|
int rest4 = ci.doFinal(inputText, inputText.length - 8, 8, part41,
|
|
len4);
|
|
byte[] outputText4 = new byte[len4 + rest4];
|
|
System.arraycopy(part41, 0, outputText4, 0, outputText4.length);
|
|
|
|
outputTexts.add(outputText4);
|
|
|
|
// Compare results
|
|
for (int k = 0; k < outputTexts.size(); k++) {
|
|
if (!Arrays.equals(resultText, outputTexts.get(k))) {
|
|
out.println(" Testing: " + algo + "/" + mode + "/" + pad);
|
|
throw new RuntimeException(
|
|
"Compare value of resultText and combination " + k
|
|
+ " are not same. Test failed.");
|
|
}
|
|
}
|
|
if (keyStrength > Cipher.getMaxAllowedKeyLength(algo)) {
|
|
throw new RuntimeException(
|
|
"Expected exception uncaught, keyStrength "
|
|
+ keyStrength);
|
|
}
|
|
} catch (InvalidKeyException ex) {
|
|
if (keyStrength <= Cipher.getMaxAllowedKeyLength(algo)) {
|
|
out.println("Unexpected exception in " + algo + "/" + mode
|
|
+ "/" + pad + " , KeySize " + keyStrength);
|
|
throw ex;
|
|
}
|
|
out.println("Caught InvalidKeyException as expected");
|
|
}
|
|
}
|
|
}
|