/* * 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.nio.ByteBuffer; import java.security.DigestException; import java.security.MessageDigest; import java.util.Random; /** * @test * @bug 8050371 * @summary Check md.digest(data) value whether same with digest output value * with various update/digest methods. * @author Kevin Liu * @key randomness */ public class TestSameValue { public static void main(String[] args) throws Exception { TestSameValue test1 = new TestSameValue(); test1.run(); } private void run() throws Exception { byte[] data = new byte[6706]; MessageDigest md = null; // Initialize input data new Random().nextBytes(data); String[] providers = { null, "SUN" }; String[] algorithmArr = { "SHA", "Sha", "MD5", "md5", "SHA-224", "SHA-256", "SHA-384", "SHA-512" }; for (String algorithm: algorithmArr) { for (String provider: providers) { if (provider != null) { md = MessageDigest.getInstance(algorithm, provider); } else { md = MessageDigest.getInstance(algorithm); } for (UpdateDigestMethod updateMethod: UpdateDigestMethod .values()) { byte[] output = updateMethod.updateDigest(data, md); // Get the output and the "correct" one byte[] standard = md.digest(data); // Compare input and output if (!MessageDigest.isEqual(output, standard)) { throw new RuntimeException( "Test failed at algorithm/provider/numUpdate:" + algorithm + "/" + provider + "/" + updateMethod); } } } } out.println("All " + algorithmArr.length * UpdateDigestMethod.values().length * providers.length + " tests Passed"); } private static enum UpdateDigestMethod { /* * update the data one by one using method update(byte input) then * do digest (giving the output buffer, offset, and the number of * bytes to put in the output buffer) */ UPDATE_DIGEST_BUFFER { @Override public byte[] updateDigest(byte[] data, MessageDigest md) throws DigestException { for (byte element: data) { md.update(element); } byte[] output = new byte[md.getDigestLength()]; int len = md.digest(output, 0, output.length); if (len != output.length) { throw new RuntimeException( "ERROR" + ": digest length differs!"); } return output; } }, /* * update the data one by one using method update(byte input) * then do digest */ UPDATE_DIGEST { @Override public byte[] updateDigest(byte[] data, MessageDigest md) { for (byte element: data) { md.update(element); } return md.digest(); } }, /* * update all the data at once as a block, then do digest ( giving the * output buffer, offset, and the number of bytes to put in the output * buffer) */ UPDATE_BLOCK_DIGEST_BUFFER { @Override public byte[] updateDigest(byte[] data, MessageDigest md) throws DigestException { md.update(data); byte[] output = new byte[md.getDigestLength()]; int len = md.digest(output, 0, output.length); if (len != output.length) { throw new RuntimeException( "ERROR" + ": digest length differs!"); } return output; } }, // update all the data at once as a block, then do digest UPDATE_BLOCK_DIGEST { @Override public byte[] updateDigest(byte[] data, MessageDigest md) { md.update(data); return md.digest(); } }, /* * update the leading bytes (length is "data.length-LASTNBYTES") * at once as a block, then do digest (do a final update using * the left LASTNBYTES bytes which is passed as a parameter for * the digest method, then complete the digest) */ UPDATE_LEADING_BLOCK_DIGEST_REMAIN { @Override public byte[] updateDigest(byte[] data, MessageDigest md) { byte[] mainPart = new byte[data.length - LASTNBYTES]; for (int i = 0; i < mainPart.length; i++) { mainPart[i] = data[i]; } for (int j = 0; j < LASTNBYTES; j++) { REMAIN[j] = data[data.length - LASTNBYTES + j]; } md.update(mainPart); return md.digest(REMAIN); } }, /* * update the data 2 bytes each time, after finishing updating, * do digest (giving the output buffer, offset, and the number * of bytes to put in the output buffer) */ UPDATE_BYTES_DIGEST_BUFFER { @Override public byte[] updateDigest(byte[] data, MessageDigest md) throws DigestException { for (int i = 0; i < data.length / 2; i++) { md.update(data, i * 2, 2); } byte[] output = new byte[md.getDigestLength()]; int len = md.digest(output, 0, output.length); if (len != output.length) { throw new RuntimeException( "ERROR" + ": digest length differs!"); } return output; } }, /* * update the data 2 bytes each time, after finishing updating, * do digest */ UPDATE_BYTES_DIGEST { @Override public byte[] updateDigest(byte[] data, MessageDigest md) { for (int i=0;i