Path: blob/master/test/jdk/java/security/MessageDigest/TestDigestIOStream.java
41149 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.ByteArrayInputStream;24import java.io.ByteArrayOutputStream;25import java.io.PrintStream;26import java.security.DigestInputStream;27import java.security.DigestOutputStream;28import java.security.MessageDigest;29import java.security.NoSuchAlgorithmException;30import java.security.Security;31import java.util.Arrays;32import java.util.Random;33import jdk.test.lib.RandomFactory;34import static java.lang.System.out;3536/**37* @test38* @bug 8050370 815605939* @summary MessageDigest tests with DigestIOStream40* @author Kevin Liu41* @key randomness42* @library /test/lib43* @build jdk.test.lib.RandomFactory44* @run main/timeout=180 TestDigestIOStream45*/4647enum ReadModel {48READ, BUFFER_READ, MIX_READ49}5051public class TestDigestIOStream {5253private static final int[] DATA_LEN_ARRAY = { 1, 50, 2500, 125000,546250000 };55private static final String[] ALGORITHM_ARRAY = { "MD2", "MD5", "SHA1",56"SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA3-224", "SHA3-256",57"SHA3-384", "SHA3-512" };5859private static byte[] data;6061private static MessageDigest md = null;6263public static void main(String argv[]) throws Exception {64TestDigestIOStream test = new TestDigestIOStream();65test.run();66}6768public void run() throws Exception {69for (String algorithm : ALGORITHM_ARRAY) {70md = MessageDigest.getInstance(algorithm);71for (int length : DATA_LEN_ARRAY) {7273Random rdm = RandomFactory.getRandom();74data = new byte[length];75rdm.nextBytes(data);7677if (!testMDChange(algorithm, length)) {78throw new RuntimeException("testMDChange failed at:"79+ algorithm + "/" + length);80}81if (!testMDShare(algorithm, length)) {82throw new RuntimeException("testMDShare failed at:"83+ algorithm + "/" + length);84}85for (ReadModel readModel : ReadModel.values()) {86// test Digest function when digest switch on87if (!testDigestOnOff(algorithm, readModel, true,88length)) {89throw new RuntimeException(90"testDigestOn failed at:" + algorithm + "/"91+ length + "/" + readModel);92}93// test Digest function when digest switch off94if (!testDigestOnOff(algorithm, readModel, false,95length)) {96throw new RuntimeException(97"testDigestOff failed at:" + algorithm + "/"98+ length + "/" + readModel);99}100}101}102}103int testNumber = ALGORITHM_ARRAY.length * ReadModel.values().length104* DATA_LEN_ARRAY.length * 2105+ ALGORITHM_ARRAY.length * DATA_LEN_ARRAY.length * 2;106out.println("All " + testNumber + " Tests Passed");107}108109/**110* Test DigestInputStream and DigestOutputStream digest function when digest111* set on and off112*113* @param algo114* Message Digest algorithm115* @param readModel116* which read method used(READ, BUFFER_READ, MIX_READ)117* @param on118* digest switch(on and off)119* @param dataLength120* plain test data length.121* @exception Exception122* throw unexpected exception123*/124public boolean testDigestOnOff(String algo, ReadModel readModel, boolean on,125int dataLength) throws Exception {126127// Generate the DigestInputStream/DigestOutputStream object128try (ByteArrayInputStream bais = new ByteArrayInputStream(data);129DigestInputStream dis = new DigestInputStream(bais,130MessageDigest.getInstance(algo));131ByteArrayOutputStream baos = new ByteArrayOutputStream();132DigestOutputStream dos = new DigestOutputStream(baos,133MessageDigest.getInstance(algo));134ByteArrayOutputStream baOut = new ByteArrayOutputStream();) {135136// Perform the update using all available/possible update methods137int k = 0;138byte[] buffer = new byte[5];139boolean enDigest = true;140// Make sure the digest function is on (default)141dis.on(enDigest);142dos.on(enDigest);143144switch (readModel) {145case READ: // use only read()146while ((k = dis.read()) != -1) {147if (on) {148dos.write(k);149} else {150dos.write(k);151if (enDigest) {152baOut.write(k);153}154enDigest = !enDigest;155dos.on(enDigest);156dis.on(enDigest);157}158}159break;160case BUFFER_READ: // use only read(byte[], int, int)161while ((k = dis.read(buffer, 0, buffer.length)) != -1) {162if (on) {163dos.write(buffer, 0, k);164} else {165dos.write(buffer, 0, k);166if (enDigest) {167baOut.write(buffer, 0, k);168}169enDigest = !enDigest;170dis.on(enDigest);171dos.on(enDigest);172}173}174break;175case MIX_READ: // use both read() and read(byte[], int, int)176while ((k = dis.read()) != -1) {177if (on) {178dos.write(k);179if ((k = dis.read(buffer, 0, buffer.length)) != -1) {180dos.write(buffer, 0, k);181}182} else {183dos.write(k);184if (enDigest) {185baOut.write(k);186}187enDigest = !enDigest;188dis.on(enDigest);189dos.on(enDigest);190if ((k = dis.read(buffer, 0, buffer.length)) != -1) {191dos.write(buffer, 0, k);192if (enDigest) {193baOut.write(buffer, 0, k);194}195enDigest = !enDigest;196dis.on(enDigest);197dos.on(enDigest);198}199}200}201break;202default:203out.println("ERROR: Invalid read/write combination choice!");204return false;205}206207// Get the output and the "correct" digest values208byte[] output1 = dis.getMessageDigest().digest();209byte[] output2 = dos.getMessageDigest().digest();210byte[] standard;211if (on) {212standard = md.digest(data);213} else {214byte[] dataDigested = baOut.toByteArray();215standard = md.digest(dataDigested);216}217218// Compare the output byte array value to the input data219if (!MessageDigest.isEqual(data, baos.toByteArray())) {220out.println("ERROR of " + readModel221+ ": output and input data unexpectedly changed");222return false;223}224// Compare generated digest values225if (!MessageDigest.isEqual(output1, standard)226|| !MessageDigest.isEqual(output2, standard)) {227out.println("ERROR" + readModel228+ ": generated digest data unexpectedly changed");229return false;230}231232return true;233} catch (Exception ex) {234out.println("testDigestOnOff failed at:" + algo + "/" + readModel235+ "/" + dataLength + " with unexpected exception");236throw ex;237}238}239240/**241* Test DigestInputStream and DigestOutputStream digest function when Swap242* the message digest engines between DigestIn/OutputStream243*244* @param algo245* Message Digest algorithm246* @param dataLength247* plain test data length.248* @exception Exception249* throw unexpected exception250*/251public boolean testMDChange(String algo, int dataLength) throws Exception {252// Generate the DigestInputStream/DigestOutputStream object253MessageDigest mdIn = MessageDigest.getInstance(algo);254MessageDigest mdOut = MessageDigest.getInstance(algo);255try (ByteArrayInputStream bais = new ByteArrayInputStream(data);256DigestInputStream dis = new DigestInputStream(bais, mdIn);257ByteArrayOutputStream baos = new ByteArrayOutputStream();258DigestOutputStream dos = new DigestOutputStream(baos, mdOut);) {259260// Perform the update using all available/possible update methods261int k = 0;262byte[] buffer = new byte[10];263264// use both read() and read(byte[], int, int)265while ((k = dis.read()) != -1) {266dos.write(k);267if ((k = dis.read(buffer, 0, buffer.length)) != -1) {268dos.write(buffer, 0, k);269}270271// Swap the message digest engines between272// DigestIn/OutputStream objects273dis.setMessageDigest(mdOut);274dos.setMessageDigest(mdIn);275mdIn = dis.getMessageDigest();276mdOut = dos.getMessageDigest();277}278279// Get the output and the "correct" digest values280byte[] output1 = mdIn.digest();281byte[] output2 = mdOut.digest();282byte[] standard = md.digest(data);283284// Compare generated digest values285return MessageDigest.isEqual(output1, standard)286&& MessageDigest.isEqual(output2, standard);287} catch (Exception ex) {288out.println("testMDChange failed at:" + algo + "/" + dataLength289+ " with unexpected exception");290throw ex;291}292}293294/**295* Test DigestInputStream and DigestOutputStream digest function when use296* same message digest object.297*298* @param algo299* Message Digest algorithm300* @param dataLength301* plain test data length.302* @exception Exception303* throw unexpected exception304*/305public boolean testMDShare(String algo, int dataLength) throws Exception {306MessageDigest mdCommon = MessageDigest.getInstance(algo);307// Generate the DigestInputStream/DigestOutputStream object308try (ByteArrayInputStream bais = new ByteArrayInputStream(data);309DigestInputStream dis = new DigestInputStream(bais, mdCommon);310ByteArrayOutputStream baos = new ByteArrayOutputStream();311DigestOutputStream dos = new DigestOutputStream(baos,312mdCommon);) {313314// Perform the update using all available/possible update methods315int k = 0;316byte[] buffer = new byte[10];317318// use both read() and read(byte[], int, int)319while (k < data.length) {320int len = dis.read(buffer, 0, buffer.length);321if (len != -1) {322k += len;323if (k < data.length) {324dos.write(data[k]);325k++;326dis.skip(1);327}328}329}330331// Get the output and the "correct" digest values332byte[] output = mdCommon.digest();333byte[] standard = md.digest(data);334335// Compare generated digest values336return MessageDigest.isEqual(output, standard);337} catch (Exception ex) {338out.println("TestMDShare failed at:" + algo + "/" + dataLength339+ " with unexpected exception");340throw ex;341}342}343}344345346