1 /* 2 * Copyright (c) 2015, 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 26 import java.nio.ByteBuffer; 27 import java.security.DigestException; 28 import java.security.MessageDigest; 29 import java.util.Random; 30 31 /** 32 * @test 33 * @bug 8050371 34 * @summary Check md.digest(data) value whether same with digest output value 35 * with various update/digest methods. 36 * @author Kevin Liu 37 * @key randomness 38 */ 39 40 public class TestSameValue { 41 42 public static void main(String[] args) throws Exception { 43 TestSameValue test1 = new TestSameValue(); 44 test1.run(); 45 } 46 47 private void run() throws Exception { 48 49 byte[] data = new byte[6706]; 50 MessageDigest md = null; 51 // Initialize input data 52 new Random().nextBytes(data); 53 54 String[] providers = { 55 null, "SUN" 56 }; 57 String[] algorithmArr = { 58 "SHA", "Sha", "MD5", "md5", "SHA-224", "SHA-256", "SHA-384", 59 "SHA-512" 60 }; 61 62 for (String algorithm: algorithmArr) { 63 for (String provider: providers) { 64 if (provider != null) { 65 md = MessageDigest.getInstance(algorithm, provider); 66 } else { 67 md = MessageDigest.getInstance(algorithm); 68 } 69 for (UpdateDigestMethod updateMethod: UpdateDigestMethod 70 .values()) { 71 byte[] output = updateMethod.updateDigest(data, md); 72 // Get the output and the "correct" one 73 byte[] standard = md.digest(data); 74 // Compare input and output 75 if (!MessageDigest.isEqual(output, standard)) { 76 throw new RuntimeException( 77 "Test failed at algorithm/provider/numUpdate:" 78 + algorithm + "/" + provider + "/" 79 + updateMethod); 80 } 81 } 82 } 83 } 84 85 out.println("All " + algorithmArr.length 86 * UpdateDigestMethod.values().length * providers.length 87 + " tests Passed"); 88 } 89 90 private static enum UpdateDigestMethod { 91 92 /* 93 * update the data one by one using method update(byte input) then 94 * do digest (giving the output buffer, offset, and the number of 95 * bytes to put in the output buffer) 96 */ 97 UPDATE_DIGEST_BUFFER { 98 @Override 99 public byte[] updateDigest(byte[] data, MessageDigest md) 100 throws DigestException { 101 for (byte element: data) { 102 md.update(element); 103 } 104 byte[] output = new byte[md.getDigestLength()]; 105 int len = md.digest(output, 0, output.length); 106 if (len != output.length) { 107 throw new RuntimeException( 108 "ERROR" + ": digest length differs!"); 109 } 110 return output; 111 } 112 }, 113 114 /* 115 * update the data one by one using method update(byte input) 116 * then do digest 117 */ 118 UPDATE_DIGEST { 119 @Override 120 public byte[] updateDigest(byte[] data, MessageDigest md) { 121 for (byte element: data) { 122 md.update(element); 123 } 124 return md.digest(); 125 } 126 }, 127 128 /* 129 * update all the data at once as a block, then do digest ( giving the 130 * output buffer, offset, and the number of bytes to put in the output 131 * buffer) 132 */ 133 UPDATE_BLOCK_DIGEST_BUFFER { 134 @Override 135 public byte[] updateDigest(byte[] data, MessageDigest md) 136 throws DigestException { 137 md.update(data); 138 byte[] output = new byte[md.getDigestLength()]; 139 int len = md.digest(output, 0, output.length); 140 if (len != output.length) { 141 throw new RuntimeException( 142 "ERROR" + ": digest length differs!"); 143 } 144 return output; 145 } 146 }, 147 148 // update all the data at once as a block, then do digest 149 UPDATE_BLOCK_DIGEST { 150 @Override 151 public byte[] updateDigest(byte[] data, MessageDigest md) { 152 md.update(data); 153 return md.digest(); 154 } 155 }, 156 157 /* 158 * update the leading bytes (length is "data.length-LASTNBYTES") 159 * at once as a block, then do digest (do a final update using 160 * the left LASTNBYTES bytes which is passed as a parameter for 161 * the digest method, then complete the digest) 162 */ 163 UPDATE_LEADING_BLOCK_DIGEST_REMAIN { 164 @Override 165 public byte[] updateDigest(byte[] data, MessageDigest md) { 166 byte[] mainPart = new byte[data.length - LASTNBYTES]; 167 for (int i = 0; i < mainPart.length; i++) { 168 mainPart[i] = data[i]; 169 } 170 for (int j = 0; j < LASTNBYTES; j++) { 171 REMAIN[j] = data[data.length - LASTNBYTES + j]; 172 } 173 md.update(mainPart); 174 return md.digest(REMAIN); 175 } 176 }, 177 178 /* 179 * update the data 2 bytes each time, after finishing updating, 180 * do digest (giving the output buffer, offset, and the number 181 * of bytes to put in the output buffer) 182 */ 183 UPDATE_BYTES_DIGEST_BUFFER { 184 @Override 185 public byte[] updateDigest(byte[] data, MessageDigest md) 186 throws DigestException { 187 188 for (int i = 0; i < data.length / 2; i++) { 189 md.update(data, i * 2, 2); 190 } 191 byte[] output = new byte[md.getDigestLength()]; 192 int len = md.digest(output, 0, output.length); 193 if (len != output.length) { 194 throw new RuntimeException( 195 "ERROR" + ": digest length differs!"); 196 } 197 return output; 198 } 199 }, 200 201 /* 202 * update the data 2 bytes each time, after finishing updating, 203 * do digest 204 */ 205 UPDATE_BYTES_DIGEST { 206 @Override 207 public byte[] updateDigest(byte[] data, MessageDigest md) { 208 for (int i=0;i<data.length/2;i++){ 209 md.update(data,i*2,2); 210 } 211 return md.digest(); 212 } 213 }, 214 215 /* 216 * update the data one by one using method update(byte[] input, 217 * int offset, int len) for the leading bytes (length is 218 * "data.length-LASTNBYTES"), then do digest (do a final 219 * update using the left LASTNBYTES bytes which is passed 220 * as a parameter for digest method then complete the digest) 221 */ 222 UPDATE_BUFFER_LEADING_DIGEST_REMAIN { 223 @Override 224 public byte[] updateDigest(byte[] data, MessageDigest md) { 225 for (int i = 0; i < data.length - LASTNBYTES; i++) { 226 md.update(data, i, 1); 227 } 228 for (int j = 0; j < LASTNBYTES; j++) { 229 REMAIN[j] = data[data.length - LASTNBYTES + j]; 230 } 231 return md.digest(REMAIN); 232 } 233 }, 234 235 /* 236 * update the data one by one using method update(byte input) 237 * for the leading bytes (length is "data.length-LASTNBYTES"), 238 * then do digest (do a final update using the left LASTNBYTES 239 * bytes which is passed as a parameter for digest method, 240 * then complete the digest) 241 */ 242 UPDATE_LEADING_DIGEST_REMAIN { 243 @Override 244 public byte[] updateDigest(byte[] data, MessageDigest md) { 245 for (int i = 0; i < data.length - LASTNBYTES; i++) { 246 md.update(data[i]); 247 } 248 for (int j = 0; j < LASTNBYTES; j++) { 249 REMAIN[j] = data[data.length - LASTNBYTES + j]; 250 } 251 return md.digest(REMAIN); 252 } 253 }, 254 255 /* 256 * update all the data at once as a ByteBuffer, then do digest 257 * (giving the output buffer, offset, and the number of bytes 258 * to put in the output buffer) 259 */ 260 UPDATE_BYTE_BUFFER_DIGEST_BUFFER { 261 @Override 262 public byte[] updateDigest(byte[] data, MessageDigest md) 263 throws DigestException { 264 md.update(ByteBuffer.wrap(data)); 265 byte[] output = new byte[md.getDigestLength()]; 266 int len = md.digest(output, 0, output.length); 267 if (len != output.length) { 268 throw new RuntimeException( 269 "ERROR" + ": digest length differs!"); 270 } 271 return output; 272 } 273 }, 274 275 // update all the data at once as a ByteBuffer, then do digest 276 UPDATE_BYTE_BUFFER_DIGEST { 277 @Override 278 public byte[] updateDigest(byte[] data, MessageDigest md) { 279 md.update(ByteBuffer.wrap(data)); 280 return md.digest(); 281 } 282 }, 283 284 /* 285 * update the leading bytes (length is "data.length-LASTNBYTES") 286 * at once as a ByteBuffer, then do digest (do a final update 287 * using the left LASTNBYTES bytes which is passed as a parameter 288 * for the digest method, then complete the digest) 289 */ 290 UPDATE_BYTE_BUFFER_LEADING_DIGEST_REMAIN { 291 @Override 292 public byte[] updateDigest(byte[] data, MessageDigest md) { 293 byte[] mainPart = new byte[data.length - LASTNBYTES]; 294 for (int i = 0; i < mainPart.length; i++) { 295 mainPart[i] = data[i]; 296 } 297 for (int j = 0; j < LASTNBYTES; j++) { 298 REMAIN[j] = data[data.length - LASTNBYTES + j]; 299 } 300 md.update(ByteBuffer.wrap(mainPart)); 301 return md.digest(REMAIN); 302 } 303 }; 304 305 private static final int LASTNBYTES = 5; 306 private static final byte[] REMAIN = new byte[LASTNBYTES]; 307 308 public abstract byte[] updateDigest(byte[] data, MessageDigest md) 309 throws DigestException; 310 } 311 }