754 lines
29 KiB
Java
754 lines
29 KiB
Java
|
/*
|
||
|
* Copyright (c) 2007, 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 java.nio.ByteBuffer;
|
||
|
import java.security.AlgorithmParameters;
|
||
|
import java.security.Provider;
|
||
|
import java.security.Security;
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.List;
|
||
|
import javax.crypto.SecretKey;
|
||
|
import javax.crypto.Cipher;
|
||
|
import javax.crypto.KeyGenerator;
|
||
|
|
||
|
/*
|
||
|
* @test
|
||
|
* @bug 8048596
|
||
|
* @summary AEAD encryption/decryption test
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* The test does the following:
|
||
|
* - create an input text and additional data
|
||
|
* - generate a secret key
|
||
|
* - instantiate a cipher according to the GCM transformation
|
||
|
* - generate an outputText using a single-part encryption/decryption
|
||
|
* in AEAD mode
|
||
|
* - perform 16 different combinations of multiple-part encryption/decryption
|
||
|
* operation in AEAD mode (in encryption mode new Cipher object is created
|
||
|
* and initialized with the same secret key and parameters)
|
||
|
* - check that all 17 results are equal
|
||
|
*
|
||
|
* Combinations:
|
||
|
*
|
||
|
* combination #1
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int)
|
||
|
* doFinal(byte[], int, int)
|
||
|
*
|
||
|
* combination #2
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*
|
||
|
* combination #3
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int)
|
||
|
*
|
||
|
* combination #4
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*
|
||
|
* combination #5 - #8 are similar to #1 -#4,
|
||
|
* but with updateAAD(byte[] src, int offset, int len)
|
||
|
*
|
||
|
* combination #9 - #12 are similar to #1 - #4,
|
||
|
* but with updateAAD(ByteBuffer src)
|
||
|
*
|
||
|
* combination #13 - #16 are similar to #9 - #12 but with directly allocated
|
||
|
* ByteBuffer and update(ByteBuffer input, ByteBuffer output)
|
||
|
*
|
||
|
*/
|
||
|
public class Encrypt {
|
||
|
|
||
|
private static final String ALGORITHMS[] = { "AES", "Rijndael" };
|
||
|
private static final int KEY_STRENGTHS[] = { 128, 192, 256 };
|
||
|
private static final int TEXT_LENGTHS[] = { 0, 256, 1024 };
|
||
|
private static final int AAD_LENGTHS[] = { 0, 8, 128, 256, 1024 };
|
||
|
private static final int ARRAY_OFFSET = 8;
|
||
|
|
||
|
private final String transformation;
|
||
|
private final Provider provider;
|
||
|
private final SecretKey key;
|
||
|
private final int textLength;
|
||
|
private final int AADLength;
|
||
|
|
||
|
/**
|
||
|
* @param provider Security provider
|
||
|
* @param algorithm Security algorithm to test
|
||
|
* @param mode The mode (GCM is only expected)
|
||
|
* @param padding Algorithm padding
|
||
|
* @param keyStrength key length
|
||
|
* @param textLength Plain text length
|
||
|
* @param AADLength Additional data length
|
||
|
*/
|
||
|
public Encrypt(Provider provider, String algorithm, String mode,
|
||
|
String padding, int keyStrength, int textLength, int AADLength)
|
||
|
throws Exception {
|
||
|
|
||
|
// init a secret Key
|
||
|
KeyGenerator kg = KeyGenerator.getInstance(algorithm, provider);
|
||
|
kg.init(keyStrength);
|
||
|
key = kg.generateKey();
|
||
|
|
||
|
this.provider = provider;
|
||
|
this.transformation = algorithm + "/" + mode + "/" + padding;
|
||
|
this.textLength = textLength;
|
||
|
this.AADLength = AADLength;
|
||
|
}
|
||
|
|
||
|
public static void main(String[] args) throws Exception {
|
||
|
Provider p = Security.getProvider("SunJCE");
|
||
|
for (String alg : ALGORITHMS) {
|
||
|
for (int keyStrength : KEY_STRENGTHS) {
|
||
|
if (keyStrength > Cipher.getMaxAllowedKeyLength(alg)) {
|
||
|
// skip this if this key length is larger than what's
|
||
|
// configured in the JCE jurisdiction policy files
|
||
|
continue;
|
||
|
}
|
||
|
for (int textLength : TEXT_LENGTHS) {
|
||
|
for (int AADLength : AAD_LENGTHS) {
|
||
|
Encrypt test = new Encrypt(p, alg,
|
||
|
"GCM", "NoPadding", keyStrength, textLength,
|
||
|
AADLength);
|
||
|
Cipher cipher = test.createCipher(Cipher.ENCRYPT_MODE,
|
||
|
null);
|
||
|
AlgorithmParameters params = cipher.getParameters();
|
||
|
test.doTest(params);
|
||
|
System.out.println("Test " + alg + ":"
|
||
|
+ keyStrength + ":" + textLength + ":"
|
||
|
+ AADLength + " passed");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void doTest(AlgorithmParameters params) throws Exception {
|
||
|
System.out.println("Test transformation = " + transformation
|
||
|
+ ", textLength = " + textLength
|
||
|
+ ", AADLength = " + AADLength);
|
||
|
byte[] input = Helper.generateBytes(textLength);
|
||
|
byte[] AAD = Helper.generateBytes(AADLength);
|
||
|
byte[] result = execute(Cipher.ENCRYPT_MODE, AAD, input, params);
|
||
|
result = execute(Cipher.DECRYPT_MODE, AAD, result, params);
|
||
|
if (!Arrays.equals(input, result)) {
|
||
|
throw new RuntimeException("Test failed");
|
||
|
}
|
||
|
System.out.println("Test passed");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Create a Cipher object for the requested encryption/decryption mode.
|
||
|
*
|
||
|
* @param mode encryption or decryption mode
|
||
|
* @return Cipher object initiated to perform requested mode operation
|
||
|
*/
|
||
|
private Cipher createCipher(int mode, AlgorithmParameters params)
|
||
|
throws Exception {
|
||
|
Cipher ci;
|
||
|
if (Cipher.ENCRYPT_MODE == mode) {
|
||
|
// create a new Cipher object for encryption
|
||
|
ci = Cipher.getInstance(transformation, provider);
|
||
|
|
||
|
// initiate it with the saved parameters
|
||
|
if (params != null) {
|
||
|
ci.init(Cipher.ENCRYPT_MODE, key, params);
|
||
|
} else {
|
||
|
// initiate the cipher without parameters
|
||
|
ci.init(Cipher.ENCRYPT_MODE, key);
|
||
|
}
|
||
|
} else {
|
||
|
// it is expected that parameters already generated
|
||
|
// before decryption
|
||
|
ci = Cipher.getInstance(transformation, provider);
|
||
|
ci.init(Cipher.DECRYPT_MODE, key, params);
|
||
|
}
|
||
|
|
||
|
return ci;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test AEAD combinations
|
||
|
*
|
||
|
* @param mode decryption or encryption
|
||
|
* @param AAD additional data for AEAD operations
|
||
|
* @param inputText plain text to decrypt/encrypt
|
||
|
* @return output text after encrypt/decrypt
|
||
|
*/
|
||
|
public byte[] execute(int mode, byte[] AAD, byte[] inputText,
|
||
|
AlgorithmParameters params) throws Exception {
|
||
|
|
||
|
Cipher cipher = createCipher(mode, params);
|
||
|
|
||
|
// results of each combination will be saved in the outputTexts
|
||
|
List<byte[]> outputTexts = new ArrayList<>();
|
||
|
|
||
|
// generate a standard outputText using a single-part en/de-cryption
|
||
|
cipher.updateAAD(AAD);
|
||
|
byte[] output = cipher.doFinal(inputText);
|
||
|
|
||
|
// execute multiple-part encryption/decryption combinations
|
||
|
combination_1(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_2(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_3(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_4(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_5(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_6(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_7(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_8(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_9(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_10(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_11(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_12(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_13(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_14(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_15(outputTexts, mode, AAD, inputText, params);
|
||
|
combination_16(outputTexts, mode, AAD, inputText, params);
|
||
|
|
||
|
for (int k = 0; k < outputTexts.size(); k++) {
|
||
|
if (!Arrays.equals(output, outputTexts.get(k))) {
|
||
|
throw new RuntimeException("Combination #" + k + " failed");
|
||
|
}
|
||
|
}
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #1:
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int)
|
||
|
* doFinal(byte[], int, int)
|
||
|
*/
|
||
|
private void combination_1(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
c.updateAAD(AAD);
|
||
|
byte[] part11 = c.update(plainText, 0, plainText.length);
|
||
|
int part11_length = part11 == null ? 0 : part11.length;
|
||
|
byte[] part12 = c.doFinal();
|
||
|
byte[] outputText1 = new byte[part11_length + part12.length];
|
||
|
if (part11 != null) {
|
||
|
System.arraycopy(part11, 0, outputText1, 0, part11_length);
|
||
|
}
|
||
|
System.arraycopy(part12, 0, outputText1, part11_length, part12.length);
|
||
|
results.add(outputText1);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #2:
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*/
|
||
|
private void combination_2(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
c.updateAAD(AAD);
|
||
|
int t = 0;
|
||
|
int offset = 0;
|
||
|
if (plainText.length > ARRAY_OFFSET) {
|
||
|
t = plainText.length - ARRAY_OFFSET;
|
||
|
offset = ARRAY_OFFSET;
|
||
|
}
|
||
|
byte[] part21 = c.update(plainText, 0, t);
|
||
|
byte[] part22 = new byte[c.getOutputSize(plainText.length)];
|
||
|
int len2 = c.doFinal(plainText, t, offset, part22, 0);
|
||
|
int part21Length = part21 != null ? part21.length : 0;
|
||
|
byte[] outputText2 = new byte[part21Length + len2];
|
||
|
if (part21 != null) {
|
||
|
System.arraycopy(part21, 0, outputText2, 0, part21Length);
|
||
|
}
|
||
|
System.arraycopy(part22, 0, outputText2, part21Length, len2);
|
||
|
results.add(outputText2);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #3
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int)
|
||
|
*/
|
||
|
private void combination_3(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher ci = createCipher(mode, params);
|
||
|
ci.updateAAD(AAD);
|
||
|
byte[] part31 = new byte[ci.getOutputSize(plainText.length)];
|
||
|
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
|
||
|
int len = ci.update(plainText, 0, plainText.length - offset, part31, 0);
|
||
|
byte[] part32 = ci.doFinal(plainText, plainText.length - offset,
|
||
|
offset);
|
||
|
byte[] outputText3 = new byte[len + part32.length];
|
||
|
System.arraycopy(part31, 0, outputText3, 0, len);
|
||
|
System.arraycopy(part32, 0, outputText3, len, part32.length);
|
||
|
results.add(outputText3);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #4:
|
||
|
* updateAAD(byte[] src)
|
||
|
* update(byte[], int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*/
|
||
|
private void combination_4(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher ci = createCipher(mode, params);
|
||
|
ci.updateAAD(AAD);
|
||
|
byte[] part41 = new byte[ci.getOutputSize(plainText.length)];
|
||
|
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
|
||
|
int len = ci.update(plainText, 0, plainText.length - offset, part41, 0);
|
||
|
int rest4 = ci.doFinal(plainText, plainText.length - offset, offset,
|
||
|
part41, len);
|
||
|
byte[] outputText4 = new byte[len + rest4];
|
||
|
System.arraycopy(part41, 0, outputText4, 0, outputText4.length);
|
||
|
results.add(outputText4);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #5:
|
||
|
* updateAAD(byte[] src, int offset, int len)
|
||
|
* update(byte[], int, int)
|
||
|
* doFinal(byte[], int, int)
|
||
|
*/
|
||
|
private void combination_5(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
c.updateAAD(AAD, 0, AAD.length);
|
||
|
byte[] part51 = c.update(plainText, 0, plainText.length);
|
||
|
byte[] part52 = c.doFinal();
|
||
|
int part51Length = part51 != null ? part51.length : 0;
|
||
|
byte[] outputText5 = new byte[part51Length + part52.length];
|
||
|
if (part51 != null) {
|
||
|
System.arraycopy(part51, 0, outputText5, 0, part51Length);
|
||
|
}
|
||
|
System.arraycopy(part52, 0, outputText5, part51Length, part52.length);
|
||
|
results.add(outputText5);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #6:
|
||
|
* updateAAD(byte[] src, int offset, int len)
|
||
|
* updateAAD(byte[] src, int offset, int len)
|
||
|
* update(byte[], int, int) doFinal(byte[], int, int, byte[], int)
|
||
|
*/
|
||
|
private void combination_6(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
c.updateAAD(AAD, 0, AAD.length / 2);
|
||
|
c.updateAAD(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
|
||
|
int t = 0;
|
||
|
int offset = 0;
|
||
|
if (plainText.length > ARRAY_OFFSET) {
|
||
|
t = plainText.length - ARRAY_OFFSET;
|
||
|
offset = ARRAY_OFFSET;
|
||
|
}
|
||
|
byte[] part61 = c.update(plainText, 0, t);
|
||
|
byte[] part62 = new byte[c.getOutputSize(plainText.length)];
|
||
|
int len = c.doFinal(plainText, t, offset, part62, 0);
|
||
|
int part61Length = part61 != null ? part61.length : 0;
|
||
|
byte[] outputText6 = new byte[part61Length + len];
|
||
|
if (part61 != null) {
|
||
|
System.arraycopy(part61, 0, outputText6, 0, part61Length);
|
||
|
}
|
||
|
System.arraycopy(part62, 0, outputText6, part61Length, len);
|
||
|
results.add(outputText6);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #7
|
||
|
* updateAAD(byte[] src, int offset, int len)
|
||
|
* updateAAD(byte[] src, src.length, 0)
|
||
|
* update(byte[], int, int, byte[], int) doFinal(byte[],int, int)
|
||
|
*/
|
||
|
private void combination_7(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher ci = createCipher(mode, params);
|
||
|
ci.updateAAD(AAD, 0, AAD.length);
|
||
|
ci.updateAAD(AAD, AAD.length, 0);
|
||
|
byte[] part71 = new byte[ci.getOutputSize(plainText.length)];
|
||
|
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
|
||
|
int len = ci.update(plainText, 0, plainText.length - offset, part71, 0);
|
||
|
byte[] part72 = ci.doFinal(plainText, plainText.length - offset, offset);
|
||
|
byte[] outputText7 = new byte[len + part72.length];
|
||
|
System.arraycopy(part71, 0, outputText7, 0, len);
|
||
|
System.arraycopy(part72, 0, outputText7, len, part72.length);
|
||
|
results.add(outputText7);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #8:
|
||
|
* updateAAD(byte[] src, 0, 0)
|
||
|
* updateAAD(byte[] src, 0, src.length)
|
||
|
* update(byte[], int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*/
|
||
|
private void combination_8(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher ci = createCipher(mode, params);
|
||
|
ci.updateAAD(AAD, 0, 0);
|
||
|
ci.updateAAD(AAD, 0, AAD.length);
|
||
|
byte[] part81 = new byte[ci.getOutputSize(plainText.length)];
|
||
|
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
|
||
|
int len = ci.update(plainText, 0, plainText.length - offset, part81, 0);
|
||
|
int rest = ci.doFinal(plainText, plainText.length - offset, offset,
|
||
|
part81, len);
|
||
|
byte[] outputText8 = new byte[len + rest];
|
||
|
System.arraycopy(part81, 0, outputText8, 0, outputText8.length);
|
||
|
results.add(outputText8);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #9:
|
||
|
* updateAAD(ByteBuffer src)
|
||
|
* update(byte[], int, int) doFinal(byte[], int, int)
|
||
|
*/
|
||
|
private void combination_9(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
|
||
|
// prepare ByteBuffer to test
|
||
|
ByteBuffer buf = ByteBuffer.allocate(AAD.length);
|
||
|
buf.put(AAD);
|
||
|
buf.position(0);
|
||
|
buf.limit(AAD.length);
|
||
|
|
||
|
// Get Cipher object and do the combination
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
c.updateAAD(buf);
|
||
|
byte[] part91 = c.update(plainText, 0, plainText.length);
|
||
|
int part91_length = part91 == null ? 0 : part91.length;
|
||
|
byte[] part92 = c.doFinal();
|
||
|
byte[] outputText9 = new byte[part91_length + part92.length];
|
||
|
|
||
|
// form result of the combination
|
||
|
if (part91 != null) {
|
||
|
System.arraycopy(part91, 0, outputText9, 0, part91_length);
|
||
|
}
|
||
|
System.arraycopy(part92, 0, outputText9, part91_length, part92.length);
|
||
|
results.add(outputText9);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #10:
|
||
|
* updateAAD(ByteBuffer src)
|
||
|
* updateAAD(ByteBuffer src) update(byte[], int, int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*/
|
||
|
private void combination_10(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
|
||
|
// prepare ByteBuffer to test
|
||
|
ByteBuffer buf = ByteBuffer.allocate(AAD.length);
|
||
|
buf.put(AAD);
|
||
|
buf.position(0);
|
||
|
buf.limit(AAD.length / 2);
|
||
|
|
||
|
// get a Cipher object and do the combination
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
|
||
|
// process the first half of AAD data
|
||
|
c.updateAAD(buf);
|
||
|
|
||
|
// process the rest of AAD data
|
||
|
buf.limit(AAD.length);
|
||
|
c.updateAAD(buf);
|
||
|
|
||
|
// prapare variables for the combination
|
||
|
int t = 0;
|
||
|
int offset = 0;
|
||
|
if (plainText.length > ARRAY_OFFSET) {
|
||
|
t = plainText.length - ARRAY_OFFSET;
|
||
|
offset = ARRAY_OFFSET;
|
||
|
}
|
||
|
|
||
|
// encrypt the text
|
||
|
byte[] part10_1 = c.update(plainText, 0, t);
|
||
|
int part10_1_Length = part10_1 != null ? part10_1.length : 0;
|
||
|
byte[] part10_2 = new byte[c.getOutputSize(plainText.length)];
|
||
|
int len2 = c.doFinal(plainText, t, offset, part10_2, 0);
|
||
|
|
||
|
// form the combination's result
|
||
|
byte[] outputText10 = new byte[part10_1_Length + len2];
|
||
|
if (part10_1 != null) {
|
||
|
System.arraycopy(part10_1, 0, outputText10, 0, part10_1_Length);
|
||
|
}
|
||
|
System.arraycopy(part10_2, 0, outputText10, part10_1_Length, len2);
|
||
|
results.add(outputText10);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #11
|
||
|
* updateAAD(ByteBuffer src1)
|
||
|
* updateAAD(ByteBuffer src2)
|
||
|
* update(byte[],int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int)
|
||
|
*/
|
||
|
private void combination_11(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
|
||
|
// prepare ByteBuffer1 to test
|
||
|
ByteBuffer buf1 = ByteBuffer.allocate(AAD.length / 2);
|
||
|
buf1.put(AAD, 0, AAD.length / 2);
|
||
|
buf1.position(0);
|
||
|
buf1.limit(AAD.length / 2);
|
||
|
|
||
|
// get a Cipher object and do combination
|
||
|
Cipher ci = createCipher(mode, params);
|
||
|
|
||
|
// process the first half of AAD data
|
||
|
ci.updateAAD(buf1);
|
||
|
|
||
|
// prepare ByteBuffer2 to test
|
||
|
ByteBuffer buf2 = ByteBuffer.allocate(AAD.length - AAD.length / 2);
|
||
|
buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
|
||
|
buf2.position(0);
|
||
|
buf2.limit(AAD.length - AAD.length / 2);
|
||
|
|
||
|
// process the rest of AAD data
|
||
|
ci.updateAAD(buf2);
|
||
|
|
||
|
// encrypt plain text
|
||
|
byte[] part11_1 = new byte[ci.getOutputSize(plainText.length)];
|
||
|
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
|
||
|
int len_11 = ci.update(plainText, 0, plainText.length - offset,
|
||
|
part11_1, 0);
|
||
|
byte[] part11_2 = ci.doFinal(plainText, plainText.length - offset,
|
||
|
offset);
|
||
|
byte[] outputText11 = new byte[len_11 + part11_2.length];
|
||
|
System.arraycopy(part11_1, 0, outputText11, 0, len_11);
|
||
|
System.arraycopy(part11_2, 0, outputText11, len_11, part11_2.length);
|
||
|
results.add(outputText11);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #12:
|
||
|
* updateAAD(ByteBuffer src)
|
||
|
* updateAAD(ByteBuffer emptyByteBuffer)
|
||
|
* update(byte[], int, int, byte[], int)
|
||
|
* doFinal(byte[], int, int, byte[], int)
|
||
|
*/
|
||
|
private void combination_12(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
|
||
|
// prepare ByteBuffer to test
|
||
|
ByteBuffer buf = ByteBuffer.allocate(AAD.length);
|
||
|
buf.put(AAD);
|
||
|
buf.position(0);
|
||
|
buf.limit(AAD.length);
|
||
|
Cipher ci = createCipher(mode, params);
|
||
|
ci.updateAAD(buf);
|
||
|
|
||
|
// prepare an empty ByteBuffer
|
||
|
ByteBuffer emptyBuf = ByteBuffer.allocate(0);
|
||
|
emptyBuf.put(new byte[0]);
|
||
|
ci.updateAAD(emptyBuf);
|
||
|
byte[] part12_1 = new byte[ci.getOutputSize(plainText.length)];
|
||
|
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
|
||
|
int len12 = ci.update(plainText, 0, plainText.length - offset,
|
||
|
part12_1, 0);
|
||
|
int rest12 = ci.doFinal(plainText, plainText.length - offset, offset,
|
||
|
part12_1, len12);
|
||
|
byte[] outputText12 = new byte[len12 + rest12];
|
||
|
System.arraycopy(part12_1, 0, outputText12, 0, outputText12.length);
|
||
|
results.add(outputText12);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #13:
|
||
|
* updateAAD(ByteBuffer src), where src is directly allocated
|
||
|
* update(ByteBuffer input, ByteBuffer out)
|
||
|
* doFinal(ByteBuffer input, ByteBuffer out)
|
||
|
*/
|
||
|
private void combination_13(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
|
||
|
// prepare ByteBuffer to test
|
||
|
ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
|
||
|
buf.put(AAD);
|
||
|
buf.position(0);
|
||
|
buf.limit(AAD.length);
|
||
|
c.updateAAD(buf);
|
||
|
|
||
|
// prepare buffers to encrypt/decrypt
|
||
|
ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
|
||
|
in.put(plainText);
|
||
|
in.position(0);
|
||
|
in.limit(plainText.length);
|
||
|
ByteBuffer output = ByteBuffer.allocateDirect(
|
||
|
c.getOutputSize(in.limit()));
|
||
|
output.position(0);
|
||
|
output.limit(c.getOutputSize(in.limit()));
|
||
|
|
||
|
// process input text
|
||
|
c.update(in, output);
|
||
|
c.doFinal(in, output);
|
||
|
int resultSize = output.position();
|
||
|
byte[] result13 = new byte[resultSize];
|
||
|
output.position(0);
|
||
|
output.limit(resultSize);
|
||
|
output.get(result13, 0, resultSize);
|
||
|
results.add(result13);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #14:
|
||
|
* updateAAD(ByteBuffer src) updateAAD(ByteBuffer src),
|
||
|
* where src is directly allocated
|
||
|
* update(ByteBuffer input, ByteBuffer out)
|
||
|
* doFinal(ByteBuffer input, ByteBuffer out)
|
||
|
*/
|
||
|
private void combination_14(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
// prepare ByteBuffer to test
|
||
|
ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
|
||
|
buf.put(AAD);
|
||
|
|
||
|
// process the first half of AAD data
|
||
|
buf.position(0);
|
||
|
buf.limit(AAD.length / 2);
|
||
|
c.updateAAD(buf);
|
||
|
|
||
|
// process the rest of AAD data
|
||
|
buf.limit(AAD.length);
|
||
|
c.updateAAD(buf);
|
||
|
|
||
|
// prepare buffers to encrypt/decrypt
|
||
|
ByteBuffer in = ByteBuffer.allocate(plainText.length);
|
||
|
in.put(plainText);
|
||
|
in.position(0);
|
||
|
in.limit(plainText.length);
|
||
|
ByteBuffer out = ByteBuffer.allocate(c.getOutputSize(in.limit()));
|
||
|
out.position(0);
|
||
|
out.limit(c.getOutputSize(in.limit()));
|
||
|
|
||
|
// process input text
|
||
|
c.update(in, out);
|
||
|
c.doFinal(in, out);
|
||
|
int resultSize = out.position();
|
||
|
byte[] result14 = new byte[resultSize];
|
||
|
out.position(0);
|
||
|
out.limit(resultSize);
|
||
|
out.get(result14, 0, resultSize);
|
||
|
results.add(result14);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #15
|
||
|
* updateAAD(ByteBuffer src1), where src1 is directly allocated
|
||
|
* updateAAD(ByteBuffer src2), where src2 is directly allocated
|
||
|
* doFinal(ByteBuffer input, ByteBuffer out)
|
||
|
*/
|
||
|
private void combination_15(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
|
||
|
// prepare ByteBuffer1 to test
|
||
|
ByteBuffer buf1 = ByteBuffer.allocateDirect(AAD.length / 2);
|
||
|
buf1.put(AAD, 0, AAD.length / 2);
|
||
|
buf1.position(0);
|
||
|
buf1.limit(AAD.length / 2);
|
||
|
|
||
|
// process the first half of AAD data
|
||
|
c.updateAAD(buf1);
|
||
|
|
||
|
// prepare ByteBuffer2 to test
|
||
|
ByteBuffer buf2 = ByteBuffer.allocateDirect(
|
||
|
AAD.length - AAD.length / 2);
|
||
|
buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
|
||
|
buf2.position(0);
|
||
|
buf2.limit(AAD.length - AAD.length / 2);
|
||
|
|
||
|
// process the rest of AAD data
|
||
|
c.updateAAD(buf2);
|
||
|
|
||
|
// prepare buffers to encrypt/decrypt
|
||
|
ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
|
||
|
in.put(plainText);
|
||
|
in.position(0);
|
||
|
in.limit(plainText.length);
|
||
|
ByteBuffer output = ByteBuffer.allocateDirect(
|
||
|
c.getOutputSize(in.limit()));
|
||
|
output.position(0);
|
||
|
output.limit(c.getOutputSize(in.limit()));
|
||
|
|
||
|
// process input text
|
||
|
c.doFinal(in, output);
|
||
|
int resultSize = output.position();
|
||
|
byte[] result15 = new byte[resultSize];
|
||
|
output.position(0);
|
||
|
output.limit(resultSize);
|
||
|
output.get(result15, 0, resultSize);
|
||
|
results.add(result15);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Execute multiple-part encryption/decryption combination #16:
|
||
|
* updateAAD(ByteBuffer src)
|
||
|
* updateAAD(ByteBuffer emptyByteBuffer)
|
||
|
* update(ByteBuffer input, ByteBuffer out)
|
||
|
* doFinal(EmptyByteBuffer, ByteBuffer out)
|
||
|
*/
|
||
|
private void combination_16(List<byte[]> results, int mode, byte[] AAD,
|
||
|
byte[] plainText, AlgorithmParameters params) throws Exception {
|
||
|
Cipher c = createCipher(mode, params);
|
||
|
|
||
|
// prepare ByteBuffer to test
|
||
|
ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
|
||
|
buf.put(AAD);
|
||
|
buf.position(0);
|
||
|
buf.limit(AAD.length);
|
||
|
c.updateAAD(buf);
|
||
|
|
||
|
// prepare empty ByteBuffer
|
||
|
ByteBuffer emptyBuf = ByteBuffer.allocateDirect(0);
|
||
|
emptyBuf.put(new byte[0]);
|
||
|
c.updateAAD(emptyBuf);
|
||
|
|
||
|
// prepare buffers to encrypt/decrypt
|
||
|
ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
|
||
|
in.put(plainText);
|
||
|
in.position(0);
|
||
|
in.limit(plainText.length);
|
||
|
ByteBuffer output = ByteBuffer.allocateDirect(
|
||
|
c.getOutputSize(in.limit()));
|
||
|
output.position(0);
|
||
|
output.limit(c.getOutputSize(in.limit()));
|
||
|
|
||
|
// process input text with an empty buffer
|
||
|
c.update(in, output);
|
||
|
ByteBuffer emptyBuf2 = ByteBuffer.allocate(0);
|
||
|
emptyBuf2.put(new byte[0]);
|
||
|
c.doFinal(emptyBuf2, output);
|
||
|
int resultSize = output.position();
|
||
|
byte[] result16 = new byte[resultSize];
|
||
|
output.position(0);
|
||
|
output.limit(resultSize);
|
||
|
output.get(result16, 0, resultSize);
|
||
|
results.add(result16);
|
||
|
}
|
||
|
}
|