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 final class SubjectPublicKeyInfo { 53 /** the value of algorithmID field of the structure */ 54 private AlgorithmIdentifier algorithmID; 55 /** the value of subjectPublicKey field of the structure */ 56 private byte[] subjectPublicKey; 57 /** the public key corresponding to this SubjectPublicKeyInfo */ 58 private PublicKey publicKey; 59 /** the value of unusedBits field of the structure */ 60 private int unusedBits; 61 /** the ASN.1 encoded form of SubjectPublicKeyInfo */ 62 private byte[] encoding; 63 64 public SubjectPublicKeyInfo(AlgorithmIdentifier algID, byte[] subjectPublicKey) { 65 this(algID, subjectPublicKey, 0); 66 } 67 68 public SubjectPublicKeyInfo(AlgorithmIdentifier algID, byte[] subjectPublicKey, int unused) { 69 this(algID, subjectPublicKey, 0, null); 70 } 71 72 private SubjectPublicKeyInfo(AlgorithmIdentifier algID, 73 byte[] subjectPublicKey, int unused, 74 byte[] encoding) { 75 this.algorithmID = algID; 76 this.subjectPublicKey = subjectPublicKey; 77 this.unusedBits = unused; 78 this.encoding = encoding; 79 } 80 81 /** 82 * Returns the value of algorithmIdentifier field of the structure. 83 */ 84 public AlgorithmIdentifier getAlgorithmIdentifier() { 85 return algorithmID; 86 } 87 88 /** 89 * Returns the value of subjectPublicKey field of the structure. 90 */ 91 public byte[] getSubjectPublicKey() { 92 return subjectPublicKey; 93 } 94 95 /** 96 * Returns ASN.1 encoded form of this X.509 SubjectPublicKeyInfo value. 97 */ 98 public byte[] getEncoded() { 99 if (encoding == null) { 100 encoding = ASN1.encode(this); 101 } 102 return encoding; 103 } 104 105 /** 106 * Returns The PublicKey corresponding to this SubjectPublicKeyInfo 107 * instance. 108 */ 109 public PublicKey getPublicKey() { 110 if (publicKey == null) { 111 String alg_oid = algorithmID.getAlgorithm(); 112 try { 113 String alg = 114 AlgNameMapper.map2AlgName(alg_oid); 115 116 if (alg == null) { 117 alg = alg_oid; 118 } 119 publicKey = KeyFactory.getInstance(alg) 120 .generatePublic(new X509EncodedKeySpec(getEncoded())); 121 } catch (InvalidKeySpecException ignored) { 122 } catch (NoSuchAlgorithmException ignored) { 123 } 124 if (publicKey == null) { 125 publicKey = new X509PublicKey(alg_oid, getEncoded(), 126 subjectPublicKey); 127 } 128 } 129 return publicKey; 130 } 131 132 public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] { 133 AlgorithmIdentifier.ASN1, ASN1BitString.getInstance() }) { 134 @Override protected Object getDecodedObject(BerInputStream in) { 135 Object[] values = (Object[]) in.content; 136 return new SubjectPublicKeyInfo( 137 (AlgorithmIdentifier) values[0], 138 ((BitString) values[1]).bytes, 139 ((BitString) values[1]).unusedBits, 140 in.getEncoded()); 141 } 142 143 @Override protected void getValues(Object object, Object[] values) { 144 SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) object; 145 values[0] = spki.algorithmID; 146 values[1] = new BitString(spki.subjectPublicKey, spki.unusedBits); 147 } 148 }; 149 } 150 151