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 18 /** 19 * @author Vladimir N. Molotkov 20 * @version $Revision$ 21 */ 22 23 package tests.security.cert; 24 25 import java.io.ByteArrayInputStream; 26 import java.io.IOException; 27 import java.io.ObjectStreamException; 28 import java.security.InvalidAlgorithmParameterException; 29 import java.security.InvalidKeyException; 30 import java.security.NoSuchAlgorithmException; 31 import java.security.NoSuchProviderException; 32 import java.security.Provider; 33 import java.security.PublicKey; 34 import java.security.Security; 35 import java.security.Signature; 36 import java.security.SignatureException; 37 import java.security.cert.Certificate; 38 import java.security.cert.CertificateEncodingException; 39 import java.security.cert.CertificateException; 40 import java.security.cert.CertificateFactory; 41 import java.util.Arrays; 42 import junit.framework.TestCase; 43 import org.apache.harmony.security.tests.support.cert.MyCertificate; 44 import org.apache.harmony.security.tests.support.cert.MyFailingCertificate; 45 import org.apache.harmony.security.tests.support.cert.TestUtils; 46 import org.apache.harmony.testframework.serialization.SerializationTest; 47 48 /** 49 * Tests for <code>Certificate</code> fields and methods 50 * 51 */ 52 public class CertificateTest extends TestCase { 53 /** 54 * Meaningless cert encoding just for testing purposes 55 */ 56 private static final byte[] testEncoding = new byte[] { (byte) 1, (byte) 2, 57 (byte) 3, (byte) 4, (byte) 5 }; 58 59 /** 60 * Test for <code>Certificate(String type)</code> method<br> 61 */ testCertificate()62 public final void testCertificate() throws Exception { 63 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 64 assertTrue(Arrays.equals(testEncoding, c1.getEncoded())); 65 assertEquals("TEST", c1.getPublicKey().getAlgorithm()); 66 assertTrue(Arrays.equals(new byte[] { (byte) 1, (byte) 2, (byte) 3 }, 67 c1.getPublicKey().getEncoded())); 68 assertEquals("TEST_FORMAT", c1.getPublicKey().getFormat()); 69 assertEquals("TEST_TYPE", c1.getType()); 70 } 71 72 /** 73 * Test for <code>hashCode()</code> method<br> 74 * Assertion: returns hash of the <code>Certificate</code> instance 75 * @throws CertificateEncodingException 76 */ testHashCode()77 public final void testHashCode() throws CertificateEncodingException { 78 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 79 Certificate c2 = new MyCertificate("TEST_TYPE", testEncoding); 80 81 assertTrue(c1.hashCode() == c2.hashCode()); 82 83 assertFalse(c1.hashCode() == new MyCertificate("TEST_TYPE", cert 84 .getEncoded()).hashCode()); 85 assertFalse(c1.hashCode() == cert.hashCode()); 86 } 87 88 /** 89 * Test for <code>hashCode()</code> method<br> 90 * Assertion: hash code of equal objects should be the same 91 */ testHashCodeEqualsObject()92 public final void testHashCodeEqualsObject() { 93 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 94 Certificate c2 = new MyCertificate("TEST_TYPE", testEncoding); 95 96 assertTrue((c1.hashCode() == c2.hashCode()) && c1.equals(c2)); 97 assertFalse(cert.equals(c1)); 98 } 99 100 /** 101 * Test for <code>hashCode()</code> method<br> 102 * Assertion: returns the value computed with the algorithm in jdk8u60. 103 */ testHashCodeValue()104 public final void testHashCodeValue() { 105 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 106 // Result used to be 40 prior to jdk8u60. 107 assertEquals(29615266, c1.hashCode()); 108 } 109 110 /** 111 * Test for <code>getType()</code> method<br> 112 * Assertion: returns this certificate type 113 */ testGetType()114 public final void testGetType() { 115 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 116 assertEquals("TEST_TYPE", c1.getType()); 117 } 118 119 /** 120 * Test #1 for <code>equals(Object)</code> method<br> 121 * Assertion: object equals to itself 122 */ testEqualsObject01()123 public final void testEqualsObject01() { 124 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 125 assertTrue(c1.equals(c1)); 126 } 127 128 /** 129 * Test for <code>equals(Object)</code> method<br> 130 * Assertion: object equals to other <code>Certificate</code> 131 * instance with the same state 132 */ testEqualsObject02()133 public final void testEqualsObject02() { 134 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 135 Certificate c2 = new MyCertificate("TEST_TYPE", testEncoding); 136 assertTrue(c1.equals(c2) && c2.equals(c1)); 137 } 138 139 /** 140 * Test for <code>equals(Object)</code> method<br> 141 * Assertion: object not equals to <code>null</code> 142 */ testEqualsObject03()143 public final void testEqualsObject03() { 144 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 145 assertFalse(c1.equals(null)); 146 } 147 148 /** 149 * Test for <code>equals(Object)</code> method<br> 150 * Assertion: object not equals to other which is not 151 * instance of <code>Certificate</code> 152 */ testEqualsObject04()153 public final void testEqualsObject04() { 154 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 155 assertFalse(c1.equals("TEST_TYPE")); 156 } 157 158 // the following tests just call methods 159 // that are abstract in <code>Certificate</code> 160 // (So they just like signature tests) 161 162 /** 163 * This test just calls <code>getEncoded()</code> method<br> 164 * @throws CertificateException 165 */ testGetEncoded()166 public final void testGetEncoded() throws CertificateException { 167 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 168 assertNotNull(c1.getEncoded()); 169 assertTrue(Arrays.equals(testEncoding,c1.getEncoded())); 170 171 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 172 byte[] expectedEncoding = cert.getEncoded(); 173 Certificate actual = cf.generateCertificate(new ByteArrayInputStream(expectedEncoding)); 174 byte[] actualEncoding = actual.getEncoded(); 175 assertTrue(Arrays.equals(expectedEncoding, actualEncoding)); 176 177 assertFalse(expectedEncoding[4] == (byte) 200); 178 expectedEncoding[4] = (byte) 200; 179 try { 180 cf.generateCertificate(new ByteArrayInputStream(expectedEncoding)); 181 fail(); 182 } catch (CertificateException expected) { 183 } 184 } 185 186 /** 187 * <code>verify(PublicKey)</code> with null args 188 * 189 * @throws InvalidKeyException 190 * @throws CertificateException 191 * @throws NoSuchAlgorithmException 192 * @throws NoSuchProviderException 193 * @throws SignatureException 194 */ testVerifyPublicKey()195 public final void testVerifyPublicKey() 196 throws InvalidKeyException, 197 CertificateException, 198 NoSuchAlgorithmException, 199 NoSuchProviderException, 200 SignatureException { 201 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 202 c1.verify(null); 203 } 204 205 /** 206 * <code>verify(PublicKey,String)</code> with null args 207 * 208 * @throws InvalidKeyException 209 * @throws CertificateException 210 * @throws NoSuchAlgorithmException 211 * @throws NoSuchProviderException 212 * @throws SignatureException 213 */ testVerifyPublicKeyString()214 public final void testVerifyPublicKeyString() 215 throws InvalidKeyException, 216 CertificateException, 217 NoSuchAlgorithmException, 218 NoSuchProviderException, 219 SignatureException { 220 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 221 c1.verify((PublicKey) null, (String) null); 222 } 223 224 /** 225 * <code>verify(PublicKey,Provider)</code> with null args 226 * 227 * @throws InvalidKeyException 228 * @throws CertificateException 229 * @throws NoSuchAlgorithmException 230 * @throws NoSuchProviderException 231 * @throws SignatureException 232 */ testVerifyPublicKeyProvider()233 public final void testVerifyPublicKeyProvider() 234 throws Exception { 235 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 236 try { 237 // Android-changed: throw UOE instead of infinite recursion. 238 c1.verify((PublicKey) null, (Provider) null); 239 fail(); 240 } catch(UnsupportedOperationException expected) {} 241 } 242 243 /** 244 * This test just calls <code>toString()</code> method<br> 245 */ testToString()246 public final void testToString() { 247 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 248 c1.toString(); 249 } 250 251 /** 252 * This test just calls <code>testGetPublicKey()</code> method<br> 253 */ testGetPublicKey()254 public final void testGetPublicKey() { 255 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 256 c1.getPublicKey(); 257 } 258 259 /** 260 * This test just calls <code>writeReplace()</code> method<br> 261 */ testWriteReplace()262 public final void testWriteReplace() throws Exception { 263 MyCertificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 264 Object obj = c1.writeReplace(); 265 assertTrue(obj.toString().contains("java.security.cert.Certificate$CertificateRep")); 266 } 267 268 public class MyModifiablePublicKey implements PublicKey { 269 270 private PublicKey key; 271 private boolean modifiedAlgo; 272 private String algo; 273 private String format; 274 private boolean modifiedFormat; 275 private boolean modifiedEncoding; 276 private byte[] encoding; 277 MyModifiablePublicKey(PublicKey k)278 public MyModifiablePublicKey(PublicKey k) { 279 super(); 280 this.key = k; 281 } 282 getAlgorithm()283 public String getAlgorithm() { 284 if (modifiedAlgo) { 285 return algo; 286 } else { 287 return key.getAlgorithm(); 288 } 289 } 290 getFormat()291 public String getFormat() { 292 if (modifiedFormat) { 293 return this.format; 294 } else { 295 return key.getFormat(); 296 } 297 298 } 299 getEncoded()300 public byte[] getEncoded() { 301 if (modifiedEncoding) { 302 return this.encoding; 303 } else { 304 return key.getEncoded(); 305 } 306 307 } 308 getSerVerUID()309 public long getSerVerUID() { 310 return key.serialVersionUID; 311 } 312 setAlgorithm(String myAlgo)313 public void setAlgorithm(String myAlgo) { 314 modifiedAlgo = true; 315 this.algo = myAlgo; 316 } 317 setFormat(String myFormat)318 public void setFormat(String myFormat) { 319 modifiedFormat = true; 320 format = myFormat; 321 } 322 setEncoding(byte[] myEncoded)323 public void setEncoding(byte[] myEncoded) { 324 modifiedEncoding = true; 325 encoding = myEncoded; 326 } 327 } 328 329 private Certificate cert; 330 setUp()331 public void setUp() throws Exception { 332 super.setUp(); 333 TestUtils.initCertPathSSCertChain(); 334 cert = TestUtils.rootCertificateSS; 335 } 336 337 /** 338 * This test just calls <code>verify(PublicKey,String)</code> method<br> 339 * 340 * @throws InvalidKeyException 341 * @throws CertificateException 342 * @throws NoSuchAlgorithmException 343 * @throws NoSuchProviderException 344 * @throws SignatureException 345 */ testVerifyPublicKeyString2()346 public final void testVerifyPublicKeyString2() throws InvalidKeyException, 347 CertificateException, NoSuchAlgorithmException, 348 NoSuchProviderException, SignatureException { 349 350 final Signature sig = Signature.getInstance("SHA1WithRSA"); 351 sig.initVerify(cert.getPublicKey()); 352 final Provider provider = sig.getProvider(); 353 // real test 354 cert.verify(cert.getPublicKey(), provider.getName()); 355 356 // Exception tests 357 358 try { 359 cert.verify(cert.getPublicKey(), "UnknownProvider"); 360 fail(); 361 } catch (NoSuchProviderException expected) { 362 } 363 364 // This test has side effects affecting all other tests running later 365 // on in the same vm instance. Maybe a better way would be to first add 366 // a new provider, test if it works, then remove it and test if the 367 // exception is thrown. 368 // 369 // CertificateFactory cf = CertificateFactory.getInstance("X.509"); 370 // Provider wrongProvider = cf.getProvider(); 371 // 372 // Security.removeProvider(wrongProvider.getName()); 373 // 374 // try { 375 // cert.verify(cert.getPublicKey(), wrongProvider.getName()); 376 // fail(); 377 // } catch (NoSuchAlgorithmException expected) { 378 // } 379 // 380 // Security.insertProviderAt(wrongProvider, oldPosition); 381 382 /* 383 PublicKey k = cert.getPublicKey(); 384 MyModifiablePublicKey tamperedKey = new MyModifiablePublicKey(k); 385 tamperedKey.setAlgorithm("wrongAlgo"); 386 387 try { 388 cert.verify(tamperedKey, provs[0].getName()); 389 fail(); 390 } catch (SignatureException expected) { 391 } 392 393 try { 394 cert.verify(c1.getPublicKey(), provs[0].getName()); 395 fail(); 396 } catch (InvalidKeyException expected) { 397 } 398 */ 399 } 400 testVerifyPublicKeyProvider2()401 public final void testVerifyPublicKeyProvider2() throws Exception { 402 final Signature sig = Signature.getInstance("SHA1WithRSA"); 403 sig.initVerify(cert.getPublicKey()); 404 final Provider provider = sig.getProvider(); 405 cert.verify(cert.getPublicKey(), provider); 406 // equivalent to calling cert.verify(cert.getPublicKey()) 407 cert.verify(cert.getPublicKey(), (Provider)null); 408 } 409 410 /** 411 * This test just calls <code>verify(PublicKey)</code> method<br> 412 * 413 * @throws InvalidKeyException 414 * @throws CertificateException 415 * @throws NoSuchAlgorithmException 416 * @throws NoSuchProviderException 417 * @throws SignatureException 418 * @throws IOException 419 * @throws InvalidAlgorithmParameterException 420 */ testVerifyPublicKey2()421 public final void testVerifyPublicKey2() 422 throws InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, InvalidAlgorithmParameterException, IOException { 423 424 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 425 c1.verify(null); 426 427 cert.verify(cert.getPublicKey()); 428 429 PublicKey k = cert.getPublicKey(); 430 431 MyModifiablePublicKey changedEncoding = new MyModifiablePublicKey(k); 432 changedEncoding.setEncoding(new byte[cert.getEncoded().length - 1]); 433 434 try { 435 cert.verify(c1.getPublicKey()); 436 fail(); 437 } catch (InvalidKeyException expected) { 438 } 439 440 try { 441 cert.verify(changedEncoding); 442 fail(); 443 } catch (Exception expected) { 444 } 445 } 446 447 /** 448 * This test just calls <code>writeReplace()</code> method<br> 449 */ testWriteReplace2()450 public final void testWriteReplace2() { 451 MyCertificate c1 = new MyFailingCertificate("TEST_TYPE", testEncoding); 452 453 try { 454 c1.writeReplace(); 455 fail(); 456 } catch (ObjectStreamException expected) { 457 } 458 } 459 460 /** 461 * serialization/deserialization compatibility. 462 */ testSerializationSelf()463 public void testSerializationSelf() throws Exception { 464 TestUtils.initCertPathSSCertChain(); 465 466 SerializationTest.verifySelf(TestUtils.rootCertificateSS); 467 } 468 469 /** 470 * serialization/deserialization compatibility with RI. 471 */ testSerializationCompatibility()472 public void testSerializationCompatibility() throws Exception { 473 // create test file (once) 474 // SerializationTest.createGoldenFile("/sdcard", this, TestUtils.rootCertificateSS); 475 TestUtils.initCertPathSSCertChain(); 476 477 SerializationTest.verifyGolden(this, TestUtils.rootCertificateSS); 478 } 479 } 480