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