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