--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/MessageDigest/TestDigestIOStream.java Tue Aug 26 15:10:29 2014 +0800
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2003, 2014, 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.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.security.DigestInputStream;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Random;
+import static java.lang.System.out;
+
+/**
+ * @test
+ * @bug 8050370
+ * @summary MessageDigest tests with DigestIOStream
+ * @author Kevin Liu
+ */
+
+enum ReadModel {
+ READ, BUFFER_READ, MIX_READ
+}
+
+public class TestDigestIOStream {
+
+ private static final int[] DATA_LEN_ARRAY = {
+ 1, 50, 2500, 125000, 6250000
+ };
+ private static final String[] ALGORITHM_ARRAY = {
+ "MD2", "MD5", "SHA1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"
+ };
+
+ private static byte[] data;
+
+ private static MessageDigest md = null;
+
+ public static void main(String argv[]) throws Exception {
+ TestDigestIOStream test = new TestDigestIOStream();
+ test.run();
+ }
+
+ public void run() throws Exception {
+ for (String algorithm: ALGORITHM_ARRAY) {
+
+ md = MessageDigest.getInstance(algorithm);
+
+ for (int length: DATA_LEN_ARRAY) {
+
+ Random rdm = new Random();
+ data = new byte[length];
+ rdm.nextBytes(data);
+
+ if (!testMDChange(algorithm, length)) {
+ throw new RuntimeException("testMDChange failed at:"
+ + algorithm + "/" + length);
+ }
+ if (!testMDShare(algorithm, length)) {
+ throw new RuntimeException("testMDShare failed at:"
+ + algorithm + "/" + length);
+ }
+ for (ReadModel readModel: ReadModel.values()) {
+ // test Digest function when digest switch on
+ if (!testDigestOnOff(algorithm, readModel, true, length)) {
+ throw new RuntimeException("testDigestOn failed at:"
+ + algorithm + "/" + length + "/" + readModel);
+ }
+ // test Digest function when digest switch off
+ if (!testDigestOnOff(algorithm, readModel, false, length)) {
+ throw new RuntimeException("testDigestOff failed at:"
+ + algorithm + "/" + length + "/" + readModel);
+ }
+ }
+ }
+ }
+ int testNumber = ALGORITHM_ARRAY.length * ReadModel.values().length
+ * DATA_LEN_ARRAY.length * 2 + ALGORITHM_ARRAY.length
+ * DATA_LEN_ARRAY.length * 2;
+ out.println("All " + testNumber + " Tests Passed");
+ }
+
+ /**
+ * Test DigestInputStream and DigestOutputStream digest function when digest
+ * set on and off
+ *
+ * @param algo
+ * Message Digest algorithm
+ * @param readModel
+ * which read method used(READ, BUFFER_READ, MIX_READ)
+ * @param on
+ * digest switch(on and off)
+ * @param dataLength
+ * plain test data length.
+ * @exception Exception
+ * throw unexpected exception
+ */
+ public boolean testDigestOnOff(String algo, ReadModel readModel,
+ boolean on, int dataLength) throws Exception {
+
+ // Generate the DigestInputStream/DigestOutputStream object
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ DigestInputStream dis = new DigestInputStream(bais,
+ MessageDigest.getInstance(algo));
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DigestOutputStream dos = new DigestOutputStream(baos,
+ MessageDigest.getInstance(algo));
+ ByteArrayOutputStream baOut = new ByteArrayOutputStream();) {
+
+ // Perform the update using all available/possible update methods
+ int k = 0;
+ byte[] buffer = new byte[5];
+ boolean enDigest = true;
+ // Make sure the digest function is on (default)
+ dis.on(enDigest);
+ dos.on(enDigest);
+
+ switch (readModel) {
+ case READ: // use only read()
+ while ((k = dis.read()) != -1) {
+ if (on) {
+ dos.write(k);
+ } else {
+ dos.write(k);
+ if (enDigest) {
+ baOut.write(k);
+ }
+ enDigest = !enDigest;
+ dos.on(enDigest);
+ dis.on(enDigest);
+ }
+ }
+ break;
+ case BUFFER_READ: // use only read(byte[], int, int)
+ while ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+ if (on) {
+ dos.write(buffer, 0, k);
+ } else {
+ dos.write(buffer, 0, k);
+ if (enDigest) {
+ baOut.write(buffer, 0, k);
+ }
+ enDigest = !enDigest;
+ dis.on(enDigest);
+ dos.on(enDigest);
+ }
+ }
+ break;
+ case MIX_READ: // use both read() and read(byte[], int, int)
+ while ((k = dis.read()) != -1) {
+ if (on) {
+ dos.write(k);
+ if ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+ dos.write(buffer, 0, k);
+ }
+ } else {
+ dos.write(k);
+ if (enDigest) {
+ baOut.write(k);
+ }
+ enDigest = !enDigest;
+ dis.on(enDigest);
+ dos.on(enDigest);
+ if ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+ dos.write(buffer, 0, k);
+ if (enDigest) {
+ baOut.write(buffer, 0, k);
+ }
+ enDigest = !enDigest;
+ dis.on(enDigest);
+ dos.on(enDigest);
+ }
+ }
+ }
+ break;
+ default:
+ out.println("ERROR: Invalid read/write combination choice!");
+ return false;
+ }
+
+ // Get the output and the "correct" digest values
+ byte[] output1 = dis.getMessageDigest().digest();
+ byte[] output2 = dos.getMessageDigest().digest();
+ byte[] standard;
+ if (on) {
+ standard = md.digest(data);
+ } else {
+ byte[] dataDigested = baOut.toByteArray();
+ standard = md.digest(dataDigested);
+ }
+
+ // Compare the output byte array value to the input data
+ if (!MessageDigest.isEqual(data, baos.toByteArray())) {
+ out.println("ERROR of " + readModel
+ + ": output and input data unexpectedly changed");
+ return false;
+ }
+ // Compare generated digest values
+ if (!MessageDigest.isEqual(output1, standard)
+ || !MessageDigest.isEqual(output2, standard)) {
+ out.println("ERROR" + readModel
+ + ": generated digest data unexpectedly changed");
+ return false;
+ }
+
+ return true;
+ } catch (Exception ex) {
+ out.println("testDigestOnOff failed at:" + algo + "/" + readModel
+ + "/" + dataLength + " with unexpected exception");
+ throw ex;
+ }
+ }
+
+ /**
+ * Test DigestInputStream and DigestOutputStream digest function when Swap
+ * the message digest engines between DigestIn/OutputStream
+ *
+ * @param algo
+ * Message Digest algorithm
+ * @param dataLength
+ * plain test data length.
+ * @exception Exception
+ * throw unexpected exception
+ */
+ public boolean testMDChange(String algo, int dataLength) throws Exception {
+ // Generate the DigestInputStream/DigestOutputStream object
+ MessageDigest mdIn = MessageDigest.getInstance(algo);
+ MessageDigest mdOut = MessageDigest.getInstance(algo);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ DigestInputStream dis = new DigestInputStream(bais, mdIn);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DigestOutputStream dos = new DigestOutputStream(baos, mdOut);) {
+
+ // Perform the update using all available/possible update methods
+ int k = 0;
+ byte[] buffer = new byte[10];
+
+ // use both read() and read(byte[], int, int)
+ while ((k = dis.read()) != -1) {
+ dos.write(k);
+ if ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+ dos.write(buffer, 0, k);
+ }
+
+ // Swap the message digest engines between
+ // DigestIn/OutputStream objects
+ dis.setMessageDigest(mdOut);
+ dos.setMessageDigest(mdIn);
+ mdIn = dis.getMessageDigest();
+ mdOut = dos.getMessageDigest();
+ }
+
+ // Get the output and the "correct" digest values
+ byte[] output1 = mdIn.digest();
+ byte[] output2 = mdOut.digest();
+ byte[] standard = md.digest(data);
+
+ // Compare generated digest values
+ return MessageDigest.isEqual(output1, standard)
+ && MessageDigest.isEqual(output2, standard);
+ } catch (Exception ex) {
+ out.println("testMDChange failed at:" + algo + "/" + dataLength
+ + " with unexpected exception");
+ throw ex;
+ }
+ }
+
+ /**
+ * Test DigestInputStream and DigestOutputStream digest function when use
+ * same message digest object.
+ *
+ * @param algo
+ * Message Digest algorithm
+ * @param dataLength
+ * plain test data length.
+ * @exception Exception
+ * throw unexpected exception
+ */
+ public boolean testMDShare(String algo, int dataLength) throws Exception {
+ MessageDigest mdCommon = MessageDigest.getInstance(algo);
+ // Generate the DigestInputStream/DigestOutputStream object
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ DigestInputStream dis = new DigestInputStream(bais, mdCommon);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DigestOutputStream dos = new DigestOutputStream(baos, mdCommon);) {
+
+ // Perform the update using all available/possible update methods
+ int k = 0;
+ byte[] buffer = new byte[10];
+
+ // use both read() and read(byte[], int, int)
+ while (k < data.length) {
+ int len = dis.read(buffer, 0, buffer.length);
+ if (len != -1) {
+ k += len;
+ if (k < data.length) {
+ dos.write(data[k]);
+ k++;
+ dis.skip(1);
+ }
+ }
+ }
+
+ // Get the output and the "correct" digest values
+ byte[] output = mdCommon.digest();
+ byte[] standard = md.digest(data);
+
+ // Compare generated digest values
+ return MessageDigest.isEqual(output, standard);
+ } catch (Exception ex) {
+ out.println("TestMDShare failed at:" + algo + "/" + dataLength
+ + " with unexpected exception");
+ throw ex;
+ }
+ }
+}