Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.apache.harmony.security.tests.x509;
     18 
     19 import org.apache.harmony.security.asn1.ASN1Integer;
     20 import org.apache.harmony.security.asn1.ASN1Sequence;
     21 import org.apache.harmony.security.asn1.ASN1Type;
     22 import org.apache.harmony.security.x509.AlgorithmIdentifier;
     23 import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
     24 import org.apache.harmony.security.x509.X509PublicKey;
     25 
     26 import java.nio.charset.Charset;
     27 import java.security.InvalidKeyException;
     28 import java.security.Key;
     29 import java.security.KeyFactorySpi;
     30 import java.security.KeyPair;
     31 import java.security.KeyPairGenerator;
     32 import java.security.PrivateKey;
     33 import java.security.Provider;
     34 import java.security.PublicKey;
     35 import java.security.Security;
     36 import java.security.interfaces.RSAPublicKey;
     37 import java.security.spec.InvalidKeySpecException;
     38 import java.security.spec.KeySpec;
     39 import java.security.spec.X509EncodedKeySpec;
     40 import java.util.Arrays;
     41 
     42 import junit.framework.TestCase;
     43 
     44 public class SubjectPublicKeyInfoTest extends TestCase {
     45     private static final byte[] ENCODED_BROKEN = "BROKEN!".getBytes(Charset.forName("ASCII"));
     46 
     47     public void test_getPublicKey_WellKnownOid() throws Exception {
     48         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
     49         KeyPair pair = kpg.generateKeyPair();
     50 
     51         final RSAPublicKey rsaPubKey = (RSAPublicKey) pair.getPublic();
     52 
     53         /* Do some fancy footwork to get an ASN.1 SubjectPublicKey for RSA */
     54         final ASN1Sequence rsaPubKeyInfo = new ASN1Sequence(new ASN1Type[] {
     55                 ASN1Integer.getInstance(), ASN1Integer.getInstance(),
     56         }) {
     57             @Override
     58             protected void getValues(Object object, Object[] values) {
     59                 values[0] = rsaPubKey.getModulus().toByteArray();
     60                 values[1] = rsaPubKey.getPublicExponent().toByteArray();
     61             }
     62         };
     63 
     64         /* The algorithm ID for RSA encryption */
     65         AlgorithmIdentifier algid = new AlgorithmIdentifier("1.2.840.113549.1.1.1");
     66 
     67         SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo(algid, rsaPubKeyInfo.encode(null));
     68 
     69         PublicKey pubKey = spki.getPublicKey();
     70         assertNotNull(pubKey);
     71         assertTrue(pubKey instanceof RSAPublicKey);
     72     }
     73 
     74     public void test_getPublicKey_Unknown_OID() throws Exception {
     75         AlgorithmIdentifier algid = new AlgorithmIdentifier("1.30.9999999999.8734878");
     76         SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo(algid, ENCODED_BROKEN);
     77         PublicKey pubKey = spki.getPublicKey();
     78         assertNotNull(pubKey);
     79         assertEquals(X509PublicKey.class, pubKey.getClass());
     80     }
     81 
     82     private static final String MY_TEST_KEY_OID = "1.30.987654321.1.1.1.2.2.2";
     83 
     84     public void test_getPublicKey_NameKnownButOnlyOIDFactoryRegistered() throws Exception {
     85         Security.addProvider(new MyTestProvider());
     86         try {
     87             AlgorithmIdentifier algid = new AlgorithmIdentifier(MY_TEST_KEY_OID, "UnknownKey");
     88             SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo(algid, ENCODED_BROKEN);
     89             PublicKey pubKey = spki.getPublicKey();
     90             assertNotNull(pubKey);
     91             assertEquals(MyTestPublicKey.class, pubKey.getClass());
     92             byte[] encoded = pubKey.getEncoded();
     93             assertEquals(
     94                     Arrays.toString(ENCODED_BROKEN),
     95                     Arrays.toString(Arrays.copyOfRange(encoded, encoded.length
     96                             - ENCODED_BROKEN.length, encoded.length)));
     97         } finally {
     98             Security.removeProvider(MyTestProvider.NAME);
     99         }
    100     }
    101 
    102     public static class MyTestProvider extends Provider {
    103         public static final String NAME = "MyTestProvider";
    104 
    105         protected MyTestProvider() {
    106             super(NAME, 1.0, "MyTestProvider");
    107 
    108             put("KeyFactory." + MY_TEST_KEY_OID, MyTestKeyFactory.class.getName());
    109         }
    110     }
    111 
    112     public static class MyTestKeyFactory extends KeyFactorySpi {
    113         @Override
    114         protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException {
    115             if (!(keySpec instanceof X509EncodedKeySpec)) {
    116                 throw new InvalidKeySpecException("Only X509EncodedKeySpec supported");
    117             }
    118 
    119             X509EncodedKeySpec x509ks = (X509EncodedKeySpec) keySpec;
    120             return new MyTestPublicKey(x509ks.getEncoded());
    121         }
    122 
    123         @Override
    124         protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException {
    125             throw new UnsupportedOperationException();
    126         }
    127 
    128         @Override
    129         protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
    130                 throws InvalidKeySpecException {
    131             throw new UnsupportedOperationException();
    132         }
    133 
    134         @Override
    135         protected Key engineTranslateKey(Key key) throws InvalidKeyException {
    136             throw new UnsupportedOperationException();
    137         }
    138     }
    139 
    140     public static class MyTestPublicKey implements PublicKey {
    141         private final byte[] data;
    142 
    143         public MyTestPublicKey(byte[] data) {
    144             this.data = data;
    145         }
    146 
    147         @Override
    148         public String getAlgorithm() {
    149             return "MyTestPublicKey";
    150         }
    151 
    152         @Override
    153         public String getFormat() {
    154             return null;
    155         }
    156 
    157         @Override
    158         public byte[] getEncoded() {
    159             return data;
    160         }
    161     }
    162 }
    163