Home | History | Annotate | Download | only in cert
      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