1 /* 2 * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import static java.lang.System.out; 25 import java.nio.ByteBuffer; 26 import java.security.DigestException; 27 import java.security.MessageDigest; 28 import java.security.NoSuchAlgorithmException; 29 import java.security.Security; 30 import jdk.test.lib.RandomFactory; 31 32 /** 33 * @test 34 * @bug 8050371 8156059 35 * @summary Check md.digest(data) value whether same with digest output value 36 * with various update/digest methods. 37 * @author Kevin Liu 38 * @key randomness 39 * @library /test/lib 40 * @build jdk.test.lib.RandomFactory 41 * @run main TestSameValue 42 */ 43 44 public class TestSameValue { 45 46 public static void main(String[] args) throws Exception { 47 TestSameValue test1 = new TestSameValue(); 48 test1.run(); 49 } 50 51 private void run() throws Exception { 52 53 byte[] data = new byte[6706]; 54 MessageDigest md = null; 55 // Initialize input data 56 RandomFactory.getRandom().nextBytes(data); 57 58 String[] algorithmArr = { "SHA", "Sha", "MD5", "md5", "SHA-224", 59 "SHA-256", "SHA-384", "SHA-512", "SHA3-224", "SHA3-256", 60 "SHA3-384", "SHA3-512" }; 61 62 for (String algorithm : algorithmArr) { 63 md = MessageDigest.getInstance(algorithm); 64 65 for (UpdateDigestMethod updateMethod : UpdateDigestMethod 66 .values()) { 67 byte[] output = updateMethod.updateDigest(data, md); 68 // Get the output and the "correct" one 69 byte[] standard = md.digest(data); 70 // Compare input and output 71 if (!MessageDigest.isEqual(output, standard)) { 72 throw new RuntimeException( 73 "Test failed at algorithm/provider/numUpdate:" 74 + algorithm + "/" + md.getProvider() 75 + "/" + updateMethod); 76 } 77 } 78 } 79 80 out.println("All " 81 + algorithmArr.length * UpdateDigestMethod.values().length 82 + " tests Passed"); 83 } 84 85 private static enum UpdateDigestMethod { 86 87 /* 88 * update the data one by one using method update(byte input) then do 89 * digest (giving the output buffer, offset, and the number of bytes to 90 * put in the output buffer) 91 */ 92 UPDATE_DIGEST_BUFFER { 93 @Override 94 public byte[] updateDigest(byte[] data, MessageDigest md) 95 throws DigestException { 96 for (byte element : data) { 97 md.update(element); 98 } 99 byte[] output = new byte[md.getDigestLength()]; 100 int len = md.digest(output, 0, output.length); 101 if (len != output.length) { 102 throw new RuntimeException( 103 "ERROR" + ": digest length differs!"); 104 } 105 return output; 106 } 107 }, 108 109 /* 110 * update the data one by one using method update(byte input) then do 111 * digest 112 */ 113 UPDATE_DIGEST { 114 @Override 115 public byte[] updateDigest(byte[] data, MessageDigest md) { 116 for (byte element : data) { 117 md.update(element); 118 } 119 return md.digest(); 120 } 121 }, 122 123 /* 124 * update all the data at once as a block, then do digest ( giving the 125 * output buffer, offset, and the number of bytes to put in the output 126 * buffer) 127 */ 128 UPDATE_BLOCK_DIGEST_BUFFER { 129 @Override 130 public byte[] updateDigest(byte[] data, MessageDigest md) 131 throws DigestException { 132 md.update(data); 133 byte[] output = new byte[md.getDigestLength()]; 134 int len = md.digest(output, 0, output.length); 135 if (len != output.length) { 136 throw new RuntimeException( 137 "ERROR" + ": digest length differs!"); 138 } 139 return output; 140 } 141 }, 142 143 // update all the data at once as a block, then do digest 144 UPDATE_BLOCK_DIGEST { 145 @Override 146 public byte[] updateDigest(byte[] data, MessageDigest md) { 147 md.update(data); 148 return md.digest(); 149 } 150 }, 151 152 /* 153 * update the leading bytes (length is "data.length-LASTNBYTES") at once 154 * as a block, then do digest (do a final update using the left 155 * LASTNBYTES bytes which is passed as a parameter for the digest 156 * method, then complete the digest) 157 */ 158 UPDATE_LEADING_BLOCK_DIGEST_REMAIN { 159 @Override 160 public byte[] updateDigest(byte[] data, MessageDigest md) { 161 byte[] mainPart = new byte[data.length - LASTNBYTES]; 162 for (int i = 0; i < mainPart.length; i++) { 163 mainPart[i] = data[i]; 164 } 165 for (int j = 0; j < LASTNBYTES; j++) { 166 REMAIN[j] = data[data.length - LASTNBYTES + j]; 167 } 168 md.update(mainPart); 169 return md.digest(REMAIN); 170 } 171 }, 172 173 /* 174 * update the data 2 bytes each time, after finishing updating, do 175 * digest (giving the output buffer, offset, and the number of bytes to 176 * put in the output buffer) 177 */ 178 UPDATE_BYTES_DIGEST_BUFFER { 179 @Override 180 public byte[] updateDigest(byte[] data, MessageDigest md) 181 throws DigestException { 182 183 for (int i = 0; i < data.length / 2; i++) { 184 md.update(data, i * 2, 2); 185 } 186 byte[] output = new byte[md.getDigestLength()]; 187 int len = md.digest(output, 0, output.length); 188 if (len != output.length) { 189 throw new RuntimeException( 190 "ERROR" + ": digest length differs!"); 191 } 192 return output; 193 } 194 }, 195 196 /* 197 * update the data 2 bytes each time, after finishing updating, do 198 * digest 199 */ 200 UPDATE_BYTES_DIGEST { 201 @Override 202 public byte[] updateDigest(byte[] data, MessageDigest md) { 203 for (int i = 0; i < data.length / 2; i++) { 204 md.update(data, i * 2, 2); 205 } 206 return md.digest(); 207 } 208 }, 209 210 /* 211 * update the data one by one using method update(byte[] input, int 212 * offset, int len) for the leading bytes (length is 213 * "data.length-LASTNBYTES"), then do digest (do a final update using 214 * the left LASTNBYTES bytes which is passed as a parameter for digest 215 * method then complete the digest) 216 */ 217 UPDATE_BUFFER_LEADING_DIGEST_REMAIN { 218 @Override 219 public byte[] updateDigest(byte[] data, MessageDigest md) { 220 for (int i = 0; i < data.length - LASTNBYTES; i++) { 221 md.update(data, i, 1); 222 } 223 for (int j = 0; j < LASTNBYTES; j++) { 224 REMAIN[j] = data[data.length - LASTNBYTES + j]; 225 } 226 return md.digest(REMAIN); 227 } 228 }, 229 230 /* 231 * update the data one by one using method update(byte input) for the 232 * leading bytes (length is "data.length-LASTNBYTES"), then do digest 233 * (do a final update using the left LASTNBYTES bytes which is passed as 234 * a parameter for digest method, then complete the digest) 235 */ 236 UPDATE_LEADING_DIGEST_REMAIN { 237 @Override 238 public byte[] updateDigest(byte[] data, MessageDigest md) { 239 for (int i = 0; i < data.length - LASTNBYTES; i++) { 240 md.update(data[i]); 241 } 242 for (int j = 0; j < LASTNBYTES; j++) { 243 REMAIN[j] = data[data.length - LASTNBYTES + j]; 244 } 245 return md.digest(REMAIN); 246 } 247 }, 248 249 /* 250 * update all the data at once as a ByteBuffer, then do digest (giving 251 * the output buffer, offset, and the number of bytes to put in the 252 * output buffer) 253 */ 254 UPDATE_BYTE_BUFFER_DIGEST_BUFFER { 255 @Override 256 public byte[] updateDigest(byte[] data, MessageDigest md) 257 throws DigestException { 258 md.update(ByteBuffer.wrap(data)); 259 byte[] output = new byte[md.getDigestLength()]; 260 int len = md.digest(output, 0, output.length); 261 if (len != output.length) { 262 throw new RuntimeException( 263 "ERROR" + ": digest length differs!"); 264 } 265 return output; 266 } 267 }, 268 269 // update all the data at once as a ByteBuffer, then do digest 270 UPDATE_BYTE_BUFFER_DIGEST { 271 @Override 272 public byte[] updateDigest(byte[] data, MessageDigest md) { 273 md.update(ByteBuffer.wrap(data)); 274 return md.digest(); 275 } 276 }, 277 278 /* 279 * update the leading bytes (length is "data.length-LASTNBYTES") at once 280 * as a ByteBuffer, then do digest (do a final update using the left 281 * LASTNBYTES bytes which is passed as a parameter for the digest 282 * method, then complete the digest) 283 */ 284 UPDATE_BYTE_BUFFER_LEADING_DIGEST_REMAIN { 285 @Override 286 public byte[] updateDigest(byte[] data, MessageDigest md) { 287 byte[] mainPart = new byte[data.length - LASTNBYTES]; 288 for (int i = 0; i < mainPart.length; i++) { 289 mainPart[i] = data[i]; 290 } 291 for (int j = 0; j < LASTNBYTES; j++) { 292 REMAIN[j] = data[data.length - LASTNBYTES + j]; 293 } 294 md.update(ByteBuffer.wrap(mainPart)); 295 return md.digest(REMAIN); 296 } 297 }; 298 299 private static final int LASTNBYTES = 5; 300 private static final byte[] REMAIN = new byte[LASTNBYTES]; 301 302 public abstract byte[] updateDigest(byte[] data, MessageDigest md) 303 throws DigestException; 304 } 305 }