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 */ 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 */ 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 */ 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 /** 102 * Test for <code>getType()</code> method<br> 103 * Assertion: returns this certificate type 104 */ 105 public final void testGetType() { 106 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 107 assertEquals("TEST_TYPE", c1.getType()); 108 } 109 110 /** 111 * Test #1 for <code>equals(Object)</code> method<br> 112 * Assertion: object equals to itself 113 */ 114 public final void testEqualsObject01() { 115 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 116 assertTrue(c1.equals(c1)); 117 } 118 119 /** 120 * Test for <code>equals(Object)</code> method<br> 121 * Assertion: object equals to other <code>Certificate</code> 122 * instance with the same state 123 */ 124 public final void testEqualsObject02() { 125 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 126 Certificate c2 = new MyCertificate("TEST_TYPE", testEncoding); 127 assertTrue(c1.equals(c2) && c2.equals(c1)); 128 } 129 130 /** 131 * Test for <code>equals(Object)</code> method<br> 132 * Assertion: object not equals to <code>null</code> 133 */ 134 public final void testEqualsObject03() { 135 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 136 assertFalse(c1.equals(null)); 137 } 138 139 /** 140 * Test for <code>equals(Object)</code> method<br> 141 * Assertion: object not equals to other which is not 142 * instance of <code>Certificate</code> 143 */ 144 public final void testEqualsObject04() { 145 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 146 assertFalse(c1.equals("TEST_TYPE")); 147 } 148 149 // the following tests just call methods 150 // that are abstract in <code>Certificate</code> 151 // (So they just like signature tests) 152 153 /** 154 * This test just calls <code>getEncoded()</code> method<br> 155 * @throws CertificateException 156 */ 157 public final void testGetEncoded() throws CertificateException { 158 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 159 assertNotNull(c1.getEncoded()); 160 assertTrue(Arrays.equals(testEncoding,c1.getEncoded())); 161 162 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 163 byte[] expectedEncoding = cert.getEncoded(); 164 Certificate actual = cf.generateCertificate(new ByteArrayInputStream(expectedEncoding)); 165 byte[] actualEncoding = actual.getEncoded(); 166 assertTrue(Arrays.equals(expectedEncoding, actualEncoding)); 167 168 assertFalse(expectedEncoding[4] == 200); 169 expectedEncoding[4] = (byte) 200; 170 try { 171 cf.generateCertificate(new ByteArrayInputStream(expectedEncoding)); 172 fail(); 173 } catch (CertificateException expected) { 174 } 175 } 176 177 /** 178 * This test just calls <code>verify(PublicKey)</code> method<br> 179 * 180 * @throws InvalidKeyException 181 * @throws CertificateException 182 * @throws NoSuchAlgorithmException 183 * @throws NoSuchProviderException 184 * @throws SignatureException 185 */ 186 public final void testVerifyPublicKey() 187 throws InvalidKeyException, 188 CertificateException, 189 NoSuchAlgorithmException, 190 NoSuchProviderException, 191 SignatureException { 192 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 193 c1.verify(null); 194 } 195 196 /** 197 * This test just calls <code>verify(PublicKey,String)</code> method<br> 198 * 199 * @throws InvalidKeyException 200 * @throws CertificateException 201 * @throws NoSuchAlgorithmException 202 * @throws NoSuchProviderException 203 * @throws SignatureException 204 */ 205 public final void testVerifyPublicKeyString() 206 throws InvalidKeyException, 207 CertificateException, 208 NoSuchAlgorithmException, 209 NoSuchProviderException, 210 SignatureException { 211 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 212 c1.verify(null, null); 213 } 214 215 /** 216 * This test just calls <code>toString()</code> method<br> 217 */ 218 public final void testToString() { 219 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 220 c1.toString(); 221 } 222 223 /** 224 * This test just calls <code>testGetPublicKey()</code> method<br> 225 */ 226 public final void testGetPublicKey() { 227 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 228 c1.getPublicKey(); 229 } 230 231 /** 232 * This test just calls <code>writeReplace()</code> method<br> 233 */ 234 public final void testWriteReplace() throws Exception { 235 MyCertificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 236 Object obj = c1.writeReplace(); 237 assertTrue(obj.toString().contains("java.security.cert.Certificate$CertificateRep")); 238 } 239 240 public class MyModifiablePublicKey implements PublicKey { 241 242 private PublicKey key; 243 private boolean modifiedAlgo; 244 private String algo; 245 private String format; 246 private boolean modifiedFormat; 247 private boolean modifiedEncoding; 248 private byte[] encoding; 249 250 public MyModifiablePublicKey(PublicKey k) { 251 super(); 252 this.key = k; 253 } 254 255 public String getAlgorithm() { 256 if (modifiedAlgo) { 257 return algo; 258 } else { 259 return key.getAlgorithm(); 260 } 261 } 262 263 public String getFormat() { 264 if (modifiedFormat) { 265 return this.format; 266 } else { 267 return key.getFormat(); 268 } 269 270 } 271 272 public byte[] getEncoded() { 273 if (modifiedEncoding) { 274 return this.encoding; 275 } else { 276 return key.getEncoded(); 277 } 278 279 } 280 281 public long getSerVerUID() { 282 return key.serialVersionUID; 283 } 284 285 public void setAlgorithm(String myAlgo) { 286 modifiedAlgo = true; 287 this.algo = myAlgo; 288 } 289 290 public void setFormat(String myFormat) { 291 modifiedFormat = true; 292 format = myFormat; 293 } 294 295 public void setEncoding(byte[] myEncoded) { 296 modifiedEncoding = true; 297 encoding = myEncoded; 298 } 299 } 300 301 private Certificate cert; 302 303 private Provider wrongProvider; 304 305 private Provider usefulProvider; 306 307 public void setUp() throws Exception { 308 super.setUp(); 309 TestUtils.initCertPathSSCertChain(); 310 cert = TestUtils.rootCertificateSS; 311 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 312 wrongProvider = cf.getProvider(); 313 usefulProvider = Signature.getInstance("SHA1WithRSA").getProvider(); 314 } 315 316 /** 317 * This test just calls <code>verify(PublicKey,String)</code> method<br> 318 * 319 * @throws InvalidKeyException 320 * @throws CertificateException 321 * @throws NoSuchAlgorithmException 322 * @throws NoSuchProviderException 323 * @throws SignatureException 324 */ 325 public final void testVerifyPublicKeyString2() throws InvalidKeyException, 326 CertificateException, NoSuchAlgorithmException, 327 NoSuchProviderException, SignatureException { 328 329 // real test 330 cert.verify(cert.getPublicKey(), usefulProvider.getName()); 331 332 // Exception tests 333 334 try { 335 cert.verify(cert.getPublicKey(), "UnknownProvider"); 336 fail(); 337 } catch (NoSuchProviderException expected) { 338 } 339 340 // This test has side effects affecting all other tests running later 341 // on in the same vm instance. Maybe a better way would be to first add 342 // a new provider, test if it works, then remove it and test if the 343 // exception is thrown. 344 // 345 // Security.removeProvider(wrongProvider.getName()); 346 // 347 // try { 348 // cert.verify(cert.getPublicKey(), wrongProvider.getName()); 349 // fail(); 350 // } catch (NoSuchAlgorithmException expected) { 351 // } 352 // 353 // Security.insertProviderAt(wrongProvider, oldPosition); 354 355 /* 356 PublicKey k = cert.getPublicKey(); 357 MyModifiablePublicKey tamperedKey = new MyModifiablePublicKey(k); 358 tamperedKey.setAlgorithm("wrongAlgo"); 359 360 try { 361 cert.verify(tamperedKey, provs[0].getName()); 362 fail(); 363 } catch (SignatureException expected) { 364 } 365 366 try { 367 cert.verify(c1.getPublicKey(), provs[0].getName()); 368 fail(); 369 } catch (InvalidKeyException expected) { 370 } 371 */ 372 } 373 374 /** 375 * This test just calls <code>verify(PublicKey)</code> method<br> 376 * 377 * @throws InvalidKeyException 378 * @throws CertificateException 379 * @throws NoSuchAlgorithmException 380 * @throws NoSuchProviderException 381 * @throws SignatureException 382 * @throws IOException 383 * @throws InvalidAlgorithmParameterException 384 */ 385 public final void testVerifyPublicKey2() 386 throws InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, InvalidAlgorithmParameterException, IOException { 387 388 Certificate c1 = new MyCertificate("TEST_TYPE", testEncoding); 389 c1.verify(null); 390 391 cert.verify(cert.getPublicKey()); 392 393 PublicKey k = cert.getPublicKey(); 394 395 MyModifiablePublicKey changedEncoding = new MyModifiablePublicKey(k); 396 changedEncoding.setEncoding(new byte[cert.getEncoded().length - 1]); 397 398 try { 399 cert.verify(c1.getPublicKey()); 400 fail(); 401 } catch (InvalidKeyException expected) { 402 } 403 404 try { 405 cert.verify(changedEncoding); 406 fail(); 407 } catch (Exception expected) { 408 } 409 } 410 411 /** 412 * This test just calls <code>writeReplace()</code> method<br> 413 */ 414 public final void testWriteReplace2() { 415 MyCertificate c1 = new MyFailingCertificate("TEST_TYPE", testEncoding); 416 417 try { 418 c1.writeReplace(); 419 fail(); 420 } catch (ObjectStreamException expected) { 421 } 422 } 423 424 /** 425 * serialization/deserialization compatibility. 426 */ 427 public void testSerializationSelf() throws Exception { 428 TestUtils.initCertPathSSCertChain(); 429 430 SerializationTest.verifySelf(TestUtils.rootCertificateSS); 431 } 432 433 /** 434 * serialization/deserialization compatibility with RI. 435 */ 436 public void testSerializationCompatibility() throws Exception { 437 // create test file (once) 438 // SerializationTest.createGoldenFile("/sdcard", this, TestUtils.rootCertificateSS); 439 TestUtils.initCertPathSSCertChain(); 440 441 SerializationTest.verifyGolden(this, TestUtils.rootCertificateSS); 442 } 443 } 444