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