1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.security.tests.java.security; 19 20import java.io.ByteArrayOutputStream; 21import java.io.DataOutputStream; 22import java.io.IOException; 23import java.io.UnsupportedEncodingException; 24import java.security.DigestException; 25import java.security.MessageDigest; 26import java.security.NoSuchAlgorithmException; 27import java.security.NoSuchProviderException; 28import java.security.Provider; 29import java.security.Security; 30import java.util.Arrays; 31import java.util.Enumeration; 32import java.util.Vector; 33 34public class MessageDigest2Test extends junit.framework.TestCase { 35 36 private static final String MESSAGEDIGEST_ID = "MessageDigest."; 37 38 private String[] digestAlgs = null; 39 40 private String providerName = null; 41 42 private static final byte[] AR1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 43 44 private static final byte[] AR2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 45 46 private static final String MESSAGE = "abc"; 47 48 private static final byte[] MESSAGE_DIGEST = { -87, -103, 62, 54, 71, 6, 49 -127, 106, -70, 62, 37, 113, 120, 80, -62, 108, -100, -48, -40, 50 -99, }; 51 52 private static final byte[] MESSAGE_DIGEST_63_As = { 3, -16, -97, 91, 21, 53 -118, 122, -116, -38, -39, 32, -67, -36, 41, -72, 28, 24, -91, 81, 54 -11, }; 55 56 private static final byte[] MESSAGE_DIGEST_64_As = { 0, -104, -70, -126, 57 75, 92, 22, 66, 123, -41, -95, 18, 42, 90, 68, 42, 37, -20, 100, 58 77, }; 59 60 private static final byte[] MESSAGE_DIGEST_65_As = { 17, 101, 83, 38, -57, 61 8, -41, 3, 25, -66, 38, 16, -24, -91, 125, -102, 91, -107, -99, 59, }; 62 63 /** 64 * @tests java.security.MessageDigest#clone() 65 */ 66 public void test_clone() { 67 for (int i = 0; i < digestAlgs.length; i++) { 68 try { 69 MessageDigest d1 = MessageDigest.getInstance(digestAlgs[i], 70 providerName); 71 for (byte b = 0; b < 84; b++) { 72 d1.update(b); 73 } 74 75 MessageDigest d2 = (MessageDigest) d1.clone(); 76 d1.update((byte) 1); 77 d2.update((byte) 1); 78 79 assertTrue("cloned hash differs from original for algorithm " 80 + digestAlgs[i], MessageDigest.isEqual(d1.digest(), d2 81 .digest())); 82 } catch (CloneNotSupportedException e) { 83 // Expected - a Signature may not be cloneable 84 } catch (NoSuchAlgorithmException e) { 85 fail("getInstance did not find algorithm " + digestAlgs[i]); 86 } catch (NoSuchProviderException e) { 87 fail("getInstance did not find provider " + providerName); 88 } 89 } 90 } 91 92 private static final byte[] SHA_DATA_2 = { 70, -54, 124, 120, -29, 57, 56, 93 119, -108, -54, -97, -76, -97, -50, -63, -73, 2, 85, -53, -79, }; 94 95 private void testSerializationSHA_DATA_2(MessageDigest sha) { 96 try { 97 sha.reset(); 98 ByteArrayOutputStream out = new ByteArrayOutputStream(); 99 DataOutputStream output = new DataOutputStream(out); 100 // ----------------------------------------------------------------------- 101 102 // Made up data 103 output 104 .writeUTF("tests.api.java.security.MessageDigestTest$InitializerFieldsTest3"); 105 output.writeInt(0); // class modifiers 106 output.writeUTF("java.io.Serializable"); // interfaces 107 108 // Fields 109 output.writeUTF("sub_toBeNotSerialized"); // name 110 output.writeInt(9); // modifiers 111 output.writeUTF("Ljava/lang/String;"); // signature 112 113 output.writeUTF("sub_toBeNotSerialized2"); // name 114 output.writeInt(9); // modifiers 115 output.writeUTF("Ljava/lang/String;"); // signature 116 117 output.writeUTF("sub_toBeSerialized"); // name 118 output.writeInt(1); // modifiers 119 output.writeUTF("Ljava/lang/String;"); // signature 120 121 output.writeUTF("sub_toBeSerialized3"); // name 122 output.writeInt(1); // modifiers 123 output.writeUTF("Ljava/lang/String;"); // signature 124 125 output.writeUTF("sub_toBeSerialized4"); // name 126 output.writeInt(1); // modifiers 127 output.writeUTF("Ljava/lang/String;"); // signature 128 129 output.writeUTF("sub_toBeSerialized5"); // name 130 output.writeInt(1); // modifiers 131 output.writeUTF("Ljava/lang/String;"); // signature 132 133 // clinit 134 output.writeUTF("<clinit>"); // name 135 output.writeInt(8); // modifiers 136 output.writeUTF("()V"); // signature 137 138 // constructors 139 output.writeUTF("<init>"); // name 140 output.writeInt(0); // modifiers 141 output.writeUTF("()V"); // signature 142 143 // methods 144 output.writeUTF("equals"); // name 145 output.writeInt(1); // modifiers 146 output.writeUTF("(Ljava.lang.Object;)Z"); // signature 147 148 // ----------------------------------------------------------------------- 149 150 output.flush(); 151 152 byte[] data = out.toByteArray(); 153 byte[] hash = sha.digest(data); 154 assertTrue("SHA_DATA_2 NOT ok", Arrays.equals(hash, SHA_DATA_2)); 155 } catch (IOException e) { 156 fail("SHA_DATA_2 NOT ok"); 157 } 158 } 159 160 private static final byte[] SHA_DATA_1 = { 90, 36, 111, 106, -32, 38, 4, 161 126, 21, -51, 107, 45, -64, -68, -109, 112, -31, -46, 34, 115, }; 162 163 private void testSerializationSHA_DATA_1(MessageDigest sha) { 164 try { 165 sha.reset(); 166 ByteArrayOutputStream out = new ByteArrayOutputStream(); 167 DataOutputStream output = new DataOutputStream(out); 168 // ----------------------------------------------------------------------- 169 170 // Made up data 171 output 172 .writeUTF("tests.api.java.security.MessageDigestTest$OptionalDataNotRead"); 173 // name 174 output.writeInt(0); // class modifiers 175 output.writeUTF("java.io.Serializable"); // interfaces 176 177 // Fields 178 output.writeUTF("class$0"); // name 179 output.writeInt(8); // modifiers 180 output.writeUTF("Ljava/lang/Class;"); // signature 181 182 output.writeUTF("field1"); // name 183 output.writeInt(2); // modifiers 184 output.writeUTF("I"); // signature 185 186 output.writeUTF("field2"); // name 187 output.writeInt(2); // modifiers 188 output.writeUTF("I"); // signature 189 190 // clinit 191 output.writeUTF("<clinit>"); // name 192 output.writeInt(8); // modifiers 193 output.writeUTF("()V"); // signature 194 195 // constructors 196 output.writeUTF("<init>"); // name 197 output.writeInt(1); // modifiers 198 output.writeUTF("()V"); // signature 199 // ----------------------------------------------------------------------- 200 201 output.flush(); 202 byte[] data = out.toByteArray(); 203 byte[] hash = sha.digest(data); 204 assertTrue("SHA_DATA_1 NOT ok", Arrays.equals(hash, SHA_DATA_1)); 205 } catch (IOException e) { 206 fail("SHA_DATA_1 NOT ok"); 207 } 208 } 209 210 /** 211 * @throws UnsupportedEncodingException 212 * @tests java.security.MessageDigest#digest() 213 */ 214 public void test_digest() throws UnsupportedEncodingException { 215 MessageDigest sha = null; 216 try { 217 sha = MessageDigest.getInstance("SHA"); 218 assertNotNull(sha); 219 } catch (NoSuchAlgorithmException e) { 220 fail("getInstance did not find algorithm"); 221 } 222 sha.update(MESSAGE.getBytes("UTF-8")); 223 byte[] digest = sha.digest(); 224 assertTrue("bug in SHA", MessageDigest.isEqual(digest, MESSAGE_DIGEST)); 225 226 sha.reset(); 227 for (int i = 0; i < 63; i++) { 228 // just under buffer capacity 229 sha.update((byte) 'a'); 230 } 231 digest = sha.digest(); 232 assertTrue("bug in SHA", MessageDigest.isEqual(digest, 233 MESSAGE_DIGEST_63_As)); 234 235 sha.reset(); 236 for (int i = 0; i < 64; i++) { 237 // exact SHA buffer capacity 238 sha.update((byte) 'a'); 239 } 240 digest = sha.digest(); 241 assertTrue("bug in SHA", MessageDigest.isEqual(digest, 242 MESSAGE_DIGEST_64_As)); 243 244 sha.reset(); 245 for (int i = 0; i < 65; i++) { 246 // just above SHA buffer capacity 247 sha.update((byte) 'a'); 248 } 249 digest = sha.digest(); 250 assertTrue("bug in SHA", MessageDigest.isEqual(digest, 251 MESSAGE_DIGEST_65_As)); 252 253 testSerializationSHA_DATA_1(sha); 254 testSerializationSHA_DATA_2(sha); 255 } 256 257 /** 258 * @tests java.security.MessageDigest#digest(byte[]) 259 */ 260 public void test_digest$B() { 261 for (int i = 0; i < digestAlgs.length; i++) { 262 try { 263 MessageDigest digest = MessageDigest.getInstance(digestAlgs[i], 264 providerName); 265 assertNotNull(digest); 266 digest.digest(AR1); 267 } catch (NoSuchAlgorithmException e) { 268 fail("getInstance did not find algorithm " + digestAlgs[i]); 269 } catch (NoSuchProviderException e) { 270 fail("getInstance did not find provider " + providerName); 271 } 272 } 273 } 274 275 /** 276 * @tests java.security.MessageDigest#digest(byte[], int, int) 277 */ 278 public void test_digest$BII() { 279 for (int i = 0; i < digestAlgs.length; i++) { 280 try { 281 MessageDigest digest = MessageDigest.getInstance(digestAlgs[i], 282 providerName); 283 assertNotNull(digest); 284 int len = digest.getDigestLength(); 285 byte[] digestBytes = new byte[len]; 286 digest.digest(digestBytes, 0, digestBytes.length); 287 } catch (NoSuchAlgorithmException e) { 288 fail("getInstance did not find algorithm " + digestAlgs[i]); 289 } catch (NoSuchProviderException e) { 290 fail("getInstance did not find provider " + providerName); 291 } catch (DigestException e) { 292 fail("digest caused exception for algorithm " + digestAlgs[i] 293 + " : " + e); 294 } 295 } 296 try { 297 MessageDigest.getInstance("SHA").digest(new byte[] {}, Integer.MAX_VALUE, 755); 298 } catch (NoSuchAlgorithmException e) { 299 //allowed 300 } catch (DigestException e) { 301 //allowed 302 } catch (IllegalArgumentException e) { 303 //expected 304 } 305 } 306 307 /** 308 * @tests java.security.MessageDigest#update(byte[], int, int) 309 */ 310 public void test_update$BII() { 311 try { 312 MessageDigest.getInstance("SHA").update(new byte[] {},Integer.MAX_VALUE,Integer.MAX_VALUE); 313 } catch (NoSuchAlgorithmException e) { 314 //allowed 315 } catch (IllegalArgumentException e) { 316 //expected 317 } 318 } 319 320 /** 321 * @tests java.security.MessageDigest#getAlgorithm() 322 */ 323 public void test_getAlgorithm() { 324 for (int i = 0; i < digestAlgs.length; i++) { 325 try { 326 String alg = MessageDigest.getInstance(digestAlgs[i], 327 providerName).getAlgorithm(); 328 assertTrue("getAlgorithm ok", alg.equals(digestAlgs[i])); 329 } catch (NoSuchAlgorithmException e) { 330 fail("getInstance did not find algorithm " + digestAlgs[i]); 331 } catch (NoSuchProviderException e) { 332 fail("getInstance did not find provider " + providerName); 333 } 334 } 335 } 336 337 /** 338 * @tests java.security.MessageDigest#getDigestLength() 339 */ 340 public void test_getDigestLength() { 341 for (int i = 0; i < digestAlgs.length; i++) { 342 try { 343 int len = MessageDigest 344 .getInstance(digestAlgs[i], providerName) 345 .getDigestLength(); 346 assertTrue("length not ok", len > 0); 347 } catch (NoSuchAlgorithmException e) { 348 fail("getInstance did not find algorithm " + digestAlgs[i]); 349 } catch (NoSuchProviderException e) { 350 fail("getInstance did not find provider " + providerName); 351 } 352 }// end for 353 } 354 355 /** 356 * @tests java.security.MessageDigest#getInstance(java.lang.String) 357 */ 358 public void test_getInstanceLjava_lang_String() { 359 for (int i = 0; i < digestAlgs.length; i++) { 360 try { 361 MessageDigest.getInstance(digestAlgs[i]); 362 } catch (NoSuchAlgorithmException e) { 363 fail("getInstance did not find algorithm " + digestAlgs[i]); 364 } 365 } 366 } 367 368 /** 369 * @tests java.security.MessageDigest#getInstance(java.lang.String, 370 * java.lang.String) 371 */ 372 public void test_getInstanceLjava_lang_StringLjava_lang_String() { 373 for (int i = 0; i < digestAlgs.length; i++) { 374 try { 375 MessageDigest.getInstance(digestAlgs[i], providerName); 376 } catch (NoSuchAlgorithmException e) { 377 fail("getInstance did not find algorithm " + digestAlgs[i]); 378 } catch (NoSuchProviderException e) { 379 fail("getInstance did not find provider " + providerName); 380 } 381 } 382 } 383 384 /** 385 * @tests java.security.MessageDigest#getProvider() 386 */ 387 public void test_getProvider() { 388 for (int i = 0; i < digestAlgs.length; i++) { 389 try { 390 Provider p = MessageDigest.getInstance(digestAlgs[i], 391 providerName).getProvider(); 392 assertNotNull("provider is null", p); 393 } catch (NoSuchAlgorithmException e) { 394 fail("getInstance did not find algorithm " + digestAlgs[i]); 395 } catch (NoSuchProviderException e) { 396 fail("getInstance did not find provider " + providerName); 397 } 398 } 399 } 400 401 /** 402 * @tests java.security.MessageDigest#isEqual(byte[], byte[]) 403 */ 404 public void test_isEqual$B$B() { 405 assertTrue("isEqual is not correct", MessageDigest.isEqual(AR1, AR2)); 406 } 407 408 /** 409 * @tests java.security.MessageDigest#toString() 410 */ 411 public void test_toString() { 412 try { 413 String str = MessageDigest.getInstance("SHA").toString(); 414 assertNotNull("toString is null", str); 415 } catch (NoSuchAlgorithmException e) { 416 fail("getInstance did not find algorithm"); 417 } 418 } 419 420 protected void setUp() { 421 if (digestAlgs == null) { 422 Provider[] providers = Security.getProviders("MessageDigest.SHA"); 423 if (providers == null) { 424 fail("No providers available for test"); 425 } 426 427 // Arbitrarily select the first available provider 428 providerName = providers[0].getName(); 429 digestAlgs = getDigestAlgorithms(providerName); 430 if (digestAlgs == null || digestAlgs.length == 0) { 431 fail("No digest algorithms were found"); 432 } 433 } 434 } 435 436 /* 437 * Returns the digest algorithms that the given provider supports. 438 */ 439 private String[] getDigestAlgorithms(String providerName) { 440 Vector algs = new Vector(); 441 442 Provider provider = Security.getProvider(providerName); 443 if (provider == null) 444 return new String[0]; 445 Enumeration e = provider.keys(); 446 while (e.hasMoreElements()) { 447 String algorithm = (String) e.nextElement(); 448 if (algorithm.startsWith(MESSAGEDIGEST_ID) && !algorithm.contains(" ")) { 449 algs.addElement(algorithm.substring(MESSAGEDIGEST_ID.length())); 450 } 451 }// end while 452 453 return (String[]) algs.toArray(new String[algs.size()]); 454 } 455}