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 Alexander Y. Kleymenov 20 * @version $Revision$ 21 */ 22 23 package org.apache.harmony.security.x509; 24 25 import java.security.KeyFactory; 26 import java.security.NoSuchAlgorithmException; 27 import java.security.PublicKey; 28 import java.security.spec.InvalidKeySpecException; 29 import java.security.spec.X509EncodedKeySpec; 30 import org.apache.harmony.security.asn1.ASN1BitString; 31 import org.apache.harmony.security.asn1.ASN1Sequence; 32 import org.apache.harmony.security.asn1.ASN1Type; 33 import org.apache.harmony.security.asn1.BerInputStream; 34 import org.apache.harmony.security.asn1.BitString; 35 import org.apache.harmony.security.utils.AlgNameMapper; 36 37 /** 38 * The class encapsulates the ASN.1 DER encoding/decoding work 39 * with the following structure which is a part of X.509 certificate 40 * (as specified in RFC 3280 - 41 * Internet X.509 Public Key Infrastructure. 42 * Certificate and Certificate Revocation List (CRL) Profile. 43 * http://www.ietf.org/rfc/rfc3280.txt): 44 * 45 * <pre> 46 * SubjectPublicKeyInfo ::= SEQUENCE { 47 * algorithm AlgorithmIdentifier, 48 * subjectPublicKey BIT STRING 49 * } 50 * </pre> 51 */ 52 public class SubjectPublicKeyInfo { 53 54 // the value of algorithmID field of the structure 55 private AlgorithmIdentifier algorithmID; 56 // the value of subjectPublicKey field of the structure 57 private byte[] subjectPublicKey; 58 // the public key corresponding to this SubjectPublicKeyInfo 59 private PublicKey publicKey; 60 // the value of unusedBits field of the structure 61 private int unusedBits; 62 // the ASN.1 encoded form of SubjectPublicKeyInfo 63 private byte[] encoding; 64 65 /** 66 * TODO 67 * @param algID: AlgorithmIdentifier 68 * @param subjectPublicKey: byte[] 69 */ 70 public SubjectPublicKeyInfo(AlgorithmIdentifier algID, 71 byte[] subjectPublicKey) { 72 this(algID, subjectPublicKey, 0); 73 } 74 75 /** 76 * TODO 77 * @param algID: AlgorithmIdentifier 78 * @param subjectPublicKey: byte[] 79 * @param unused: int 80 */ 81 public SubjectPublicKeyInfo(AlgorithmIdentifier algID, 82 byte[] subjectPublicKey, int unused) { 83 this(algID, subjectPublicKey, 0, null); 84 } 85 86 // 87 // TODO 88 // @param algID: AlgorithmIdentifier 89 // @param subjectPublicKey: byte[] 90 // @param unused: int 91 // @param encoding: byte[] 92 // 93 private SubjectPublicKeyInfo(AlgorithmIdentifier algID, 94 byte[] subjectPublicKey, int unused, 95 byte[] encoding) { 96 this.algorithmID = algID; 97 this.subjectPublicKey = subjectPublicKey; 98 this.unusedBits = unused; 99 this.encoding = encoding; 100 } 101 102 /** 103 * Returns the value of algorithmIdentifier field of the structure. 104 * @return algorithmIdentifier 105 */ 106 public AlgorithmIdentifier getAlgorithmIdentifier() { 107 return algorithmID; 108 } 109 110 /** 111 * Returns the value of subjectPublicKey field of the structure. 112 * @return subjectPublicKey 113 */ 114 public byte[] getSubjectPublicKey() { 115 return subjectPublicKey; 116 } 117 118 /** 119 * Returns the value of unusedBits field of the structure. 120 * @return unusedBits 121 */ 122 public int getUnusedBits() { 123 return unusedBits; 124 } 125 126 /** 127 * Returns ASN.1 encoded form of this X.509 SubjectPublicKeyInfo value. 128 * @return a byte array containing ASN.1 encode form. 129 */ 130 public byte[] getEncoded() { 131 if (encoding == null) { 132 encoding = ASN1.encode(this); 133 } 134 return encoding; 135 } 136 137 /** 138 * Returns The PublicKey corresponding to this SubjectPublicKeyInfo 139 * instance. 140 * @return public key corresponding to this SubjectPublicKeyInfo. 141 */ 142 public PublicKey getPublicKey() { 143 if (publicKey == null) { 144 String alg_oid = algorithmID.getAlgorithm(); 145 try { 146 String alg = 147 AlgNameMapper.map2AlgName(alg_oid); 148 149 if (alg == null) { 150 alg = alg_oid; 151 } 152 publicKey = KeyFactory.getInstance(alg) 153 .generatePublic(new X509EncodedKeySpec(getEncoded())); 154 } catch (InvalidKeySpecException e) { 155 } catch (NoSuchAlgorithmException e) { 156 } 157 if (publicKey == null) { 158 publicKey = new X509PublicKey(alg_oid, getEncoded(), 159 subjectPublicKey); 160 } 161 } 162 return publicKey; 163 } 164 165 public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] { 166 AlgorithmIdentifier.ASN1, ASN1BitString.getInstance() }) { 167 168 protected Object getDecodedObject(BerInputStream in) { 169 Object[] values = (Object[]) in.content; 170 return new SubjectPublicKeyInfo( 171 (AlgorithmIdentifier) values[0], 172 ((BitString) values[1]).bytes, 173 ((BitString) values[1]).unusedBits, 174 in.getEncoded()); 175 } 176 177 protected void getValues(Object object, Object[] values) { 178 179 SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) object; 180 181 values[0] = spki.algorithmID; 182 values[1] = new BitString(spki.subjectPublicKey, spki.unusedBits); 183 } 184 }; 185 } 186 187