blob: f58217244b75632d0ff576ff5d7ee65057e1ea72 [file] [log] [blame]
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 0000000
* @summary Makes sure that Cipher.doFinal() returns the right number
* of bytes written
* @author Jan Luehe
*/
import java.security.*;
import java.security.interfaces.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class DoFinalReturnLen {
static byte[] dataToEncrypt = {
(byte)0x02, (byte)0xA4, (byte)0x20, (byte)0x87,
(byte)0xB6, (byte)0xC4, (byte)0x54, (byte)0x89,
(byte)0xA2, (byte)0xA4, (byte)0x10, (byte)0x87,
(byte)0xCD, (byte)0x76, (byte)0x43, (byte)0xF0,
(byte)0x72, (byte)0xA4, (byte)0xA0, (byte)0x82,
(byte)0x26, (byte)0xC4, (byte)0x54, (byte)0x19,
(byte)0x09, (byte)0xAC, (byte)0x2A, (byte)0xE7,
(byte)0x1D, (byte)0x74, (byte)0x13, (byte)0x20,
(byte)0xAD, (byte)0xD4, (byte)0xD0, (byte)0x87,
(byte)0xB6, (byte)0xC5, (byte)0x24, (byte)0x89,
(byte)0x02, (byte)0xF4, (byte)0x90, (byte)0x8E,
(byte)0x5D, (byte)0x76, (byte)0x43, (byte)0x2F,
(byte)0x03, (byte)0xAD, (byte)0x20, (byte)0x8C,
(byte)0xB5, (byte)0xC4, (byte)0xA4, (byte)0x39,
(byte)0xD2, (byte)0xA4, (byte)0xE0, (byte)0x87,
(byte)0xCD, (byte)0x56, (byte)0x53, (byte)0x20
};
static byte[] dataToEncryptUneven = {
(byte)0x02, (byte)0xA4, (byte)0x20, (byte)0x87,
(byte)0xB6, (byte)0xC4, (byte)0x54, (byte)0x89,
(byte)0xA2, (byte)0xA4, (byte)0x10, (byte)0x87,
(byte)0xCD, (byte)0x76, (byte)0x43, (byte)0xF0,
(byte)0x72, (byte)0xA4, (byte)0xA0, (byte)0x82,
(byte)0x26, (byte)0xC4, (byte)0x54, (byte)0x19,
(byte)0x09, (byte)0xAC, (byte)0x2A, (byte)0xE7,
(byte)0x1D, (byte)0x74, (byte)0x13, (byte)0x20,
(byte)0xAD, (byte)0xD4, (byte)0xD0, (byte)0x87,
(byte)0xB6, (byte)0xC5, (byte)0x24, (byte)0x89,
(byte)0x02, (byte)0xF4, (byte)0x90, (byte)0x8E,
(byte)0x5D, (byte)0x76, (byte)0x43, (byte)0x2F,
(byte)0x03, (byte)0xAD, (byte)0x20, (byte)0x8C,
(byte)0xB5, (byte)0xC4, (byte)0xA4, (byte)0x39,
(byte)0xD2, (byte)0xA4, (byte)0xE0, (byte)0x87,
(byte)0xCD, (byte)0x56, (byte)0x53, (byte)0x20,
(byte)0x22
};
static byte[] iv = {
(byte)0x03, (byte)0xAD, (byte)0x20, (byte)0x8C,
(byte)0xB5, (byte)0xC4, (byte)0xA4, (byte)0x39
};
public static void main (String args[]) throws Exception {
byte[] encryptedData = null;
byte[] decryptedData = null;
Cipher newDES = null;
IvParameterSpec IvParamSpec = null;
SecretKey sKey = null;
// Step 0: add providers
Provider sun = new com.sun.crypto.provider.SunJCE();
Security.addProvider(sun);
Provider[] theProviders = Security.getProviders();
for (int index = 0; index < theProviders.length; index++) {
System.out.println(theProviders[index].getName());
System.out.println(theProviders[index].getVersion());
System.out.println(theProviders[index].getInfo());
}
// Cipher Object
newDES = Cipher.getInstance("DES/CBC/PKCS5Padding",
"SunJCE");
byte[] keyData = {
(byte)0x46, (byte)0x19, (byte)0x20, (byte)0x5e,
(byte)0xef, (byte)0x0b, (byte)0x7c, (byte)0x45
};
// Generate secret key
SecretKeyFactory desFactory
= SecretKeyFactory.getInstance("DES", "SunJCE");
DESKeySpec keySpec = new DESKeySpec(keyData);
sKey = desFactory.generateSecret(keySpec);
// encrypt data
System.out.println("DataToEncrypt:");
printBuffer(dataToEncrypt);
IvParamSpec = new IvParameterSpec(iv, 0, 8);
newDES.init(Cipher.ENCRYPT_MODE, sKey, IvParamSpec);
encryptedData =
new byte[newDES.getOutputSize(dataToEncrypt.length)];
int outputLenUpdate = newDES.update(dataToEncrypt, 0,
dataToEncrypt.length,
encryptedData);
int outputLenFinal = newDES.doFinal(encryptedData,
outputLenUpdate);
System.out.println("ENCRYPT : Update " + outputLenUpdate
+ " bytes");
System.out.println("ENCRYPT : Final " + outputLenFinal
+ " bytes");
System.out.println("Encrypted data:");
printBuffer(encryptedData);
// decrypt data
newDES.init(Cipher.DECRYPT_MODE, sKey, IvParamSpec);
decryptedData =
new byte[newDES.getOutputSize(encryptedData.length)];
System.out.println("encrLen: " + encryptedData.length);
System.out.println("decrLen: " + decryptedData.length);
outputLenUpdate = newDES.update(encryptedData, 0,
encryptedData.length,
decryptedData, 0);
outputLenFinal = newDES.doFinal(decryptedData,
outputLenUpdate);
System.out.println("DECRYPT : Update " + outputLenUpdate
+ " bytes");
System.out.println("DECRYPT : Final " + outputLenFinal
+ " bytes");
System.out.println("Decrypted data:");
printBuffer(decryptedData);
int len = 0;
if (dataToEncrypt.length >= decryptedData.length)
len = decryptedData.length;
else
len = dataToEncrypt.length;
for (int i=0; i<len; i++)
if (dataToEncrypt[i] != decryptedData[i])
throw new Exception("Original and recovered data differ");
// decrypt data with exact output buffer length
newDES.init(Cipher.DECRYPT_MODE, sKey, IvParamSpec);
decryptedData = new byte[dataToEncrypt.length];
System.out.println("encrLen: " + encryptedData.length);
System.out.println("decrLen: " + decryptedData.length);
outputLenUpdate = newDES.update(encryptedData, 0,
encryptedData.length,
decryptedData, 0);
outputLenFinal = newDES.doFinal(decryptedData,
outputLenUpdate);
System.out.println("DECRYPT : Update " + outputLenUpdate
+ " bytes");
System.out.println("DECRYPT : Final " + outputLenFinal
+ " bytes");
System.out.println("Decrypted data:");
printBuffer(decryptedData);
len = 0;
if (dataToEncrypt.length >= decryptedData.length)
len = decryptedData.length;
else
len = dataToEncrypt.length;
for (int i=0; i<len; i++)
if (dataToEncrypt[i] != decryptedData[i])
throw new Exception("Original and recovered data differ");
//
// run the same test for the input data with uneven number of bytes
//
// encrypt data
System.out.println();
System.out.println("DataToEncrypt:");
printBuffer(dataToEncryptUneven);
newDES.init(Cipher.ENCRYPT_MODE, sKey, IvParamSpec);
encryptedData =
new byte[newDES.getOutputSize(dataToEncryptUneven.length)];
outputLenUpdate = newDES.update(dataToEncryptUneven, 0,
dataToEncryptUneven.length,
encryptedData);
outputLenFinal = newDES.doFinal(encryptedData,
outputLenUpdate);
System.out.println("ENCRYPT : Update " + outputLenUpdate
+ " bytes");
System.out.println("ENCRYPT : Final " + outputLenFinal
+ " bytes");
System.out.println("Encrypted data:");
printBuffer(encryptedData);
// decrypt data
newDES.init(Cipher.DECRYPT_MODE, sKey, IvParamSpec);
decryptedData =
new byte[newDES.getOutputSize(encryptedData.length)];
System.out.println("encrLen: " + encryptedData.length);
System.out.println("decrLen: " + decryptedData.length);
outputLenUpdate = newDES.update(encryptedData, 0,
encryptedData.length,
decryptedData, 0);
outputLenFinal = newDES.doFinal(decryptedData,
outputLenUpdate);
System.out.println("DECRYPT : Update " + outputLenUpdate
+ " bytes");
System.out.println("DECRYPT : Final " + outputLenFinal
+ " bytes");
System.out.println("Decrypted data:");
printBuffer(decryptedData);
len = 0;
if (dataToEncryptUneven.length >= decryptedData.length)
len = decryptedData.length;
else
len = dataToEncryptUneven.length;
for (int i=0; i<len; i++)
if (dataToEncryptUneven[i] != decryptedData[i])
throw new Exception("Original and recovered data differ");
// decrypt data with exact output buffer length
newDES.init(Cipher.DECRYPT_MODE, sKey, IvParamSpec);
decryptedData = new byte[dataToEncryptUneven.length];
System.out.println("encrLen: " + encryptedData.length);
System.out.println("decrLen: " + decryptedData.length);
outputLenUpdate = newDES.update(encryptedData, 0,
encryptedData.length,
decryptedData, 0);
outputLenFinal = newDES.doFinal(decryptedData,
outputLenUpdate);
System.out.println("DECRYPT : Update " + outputLenUpdate
+ " bytes");
System.out.println("DECRYPT : Final " + outputLenFinal
+ " bytes");
System.out.println("Decrypted data:");
printBuffer(decryptedData);
len = 0;
if (dataToEncryptUneven.length >= decryptedData.length)
len = decryptedData.length;
else
len = dataToEncryptUneven.length;
for (int i=0; i<len; i++)
if (dataToEncryptUneven[i] != decryptedData[i])
throw new Exception("Original and recovered data differ");
System.out.println();
System.out.println("Test succeeded");
}
// These methods print out a byte array in a reasonably pretty format.
private static void printBuffer(byte[] byteArray) {
printBuffer(byteArray, byteArray.length);
}
private static void printBuffer(byte[] byteArray, int length) {
StringBuffer textLine = new StringBuffer(" ");
System.out.print("; 00000000: ");
for (int i=0; i < length; i++) {
if (((i%16) == 0) && i != 0) {
System.out.println("[" + textLine + "]");
System.out.print("; ");
hexPrint(i, 8);
System.out.print(": ");
for(int j=0; j<16; j++) {
textLine.setCharAt(j,' ');
}
}
hexPrint((int) byteArray[i], 2);
System.out.print(" ");
if ((byteArray[i] < 32) || (byteArray[i] > 127)) {
textLine.setCharAt(i%16, '.');
} else {
textLine.setCharAt(i%16,(char)byteArray[i]);
}
}
if (((length % 16) != 0) || (length == 0)) {
for (int i = 0; i < 16 - (length % 16); i++) {
System.out.print(" ");
}
}
System.out.println("[" + textLine + "]");
}
private static void hexPrint(int value, int padding) {
String hexString = new String("0123456789ABCDEF");
for (int i = (padding - 1); i >= 0; i--) {
System.out.print(hexString.charAt((value >> (i*4)) & 0xF));
}
}
}