View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /**
6    * Licensed to the Apache Software Foundation (ASF) under one
7    * or more contributor license agreements. See the NOTICE file
8    * distributed with this work for additional information
9    * regarding copyright ownership. The ASF licenses this file
10   * to you under the Apache License, Version 2.0 (the
11   * "License"); you may not use this file except in compliance
12   * with the License. You may obtain a copy of the License at
13   *
14   * http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing,
17   * software distributed under the License is distributed on an
18   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   * KIND, either express or implied. See the License for the
20   * specific language governing permissions and limitations
21   * under the License.
22   */
23  package com.sun.org.apache.xml.internal.security.keys.content.x509;
24  
25  import java.security.cert.X509Certificate;
26  import java.util.Arrays;
27  
28  import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
29  import com.sun.org.apache.xml.internal.security.utils.Base64;
30  import com.sun.org.apache.xml.internal.security.utils.Constants;
31  import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
32  import org.w3c.dom.Document;
33  import org.w3c.dom.Element;
34  
35  /**
36   * Handles SubjectKeyIdentifier (SKI) for X.509v3.
37   *
38   * @see <A HREF="http://docs.oracle.com/javase/1.5.0/docs/api/java/security/cert/X509Extension.html">
39   * Interface X509Extension</A>
40   */
41  public class XMLX509SKI extends SignatureElementProxy implements XMLX509DataContent {
42  
43      /** {@link org.apache.commons.logging} logging facility */
44      private static java.util.logging.Logger log =
45          java.util.logging.Logger.getLogger(XMLX509SKI.class.getName());
46  
47      /**
48       * <CODE>SubjectKeyIdentifier (id-ce-subjectKeyIdentifier) (2.5.29.14)</CODE>:
49       * This extension identifies the public key being certified. It enables
50       * distinct keys used by the same subject to be differentiated
51       * (e.g., as key updating occurs).
52       * <BR />
53       * A key identifier shall be unique with respect to all key identifiers
54       * for the subject with which it is used. This extension is always non-critical.
55       */
56      public static final String SKI_OID = "2.5.29.14";
57  
58      /**
59       * Constructor X509SKI
60       *
61       * @param doc
62       * @param skiBytes
63       */
64      public XMLX509SKI(Document doc, byte[] skiBytes) {
65          super(doc);
66          this.addBase64Text(skiBytes);
67      }
68  
69      /**
70       * Constructor XMLX509SKI
71       *
72       * @param doc
73       * @param x509certificate
74       * @throws XMLSecurityException
75       */
76      public XMLX509SKI(Document doc, X509Certificate x509certificate)
77          throws XMLSecurityException {
78          super(doc);
79          this.addBase64Text(XMLX509SKI.getSKIBytesFromCert(x509certificate));
80      }
81  
82      /**
83       * Constructor XMLX509SKI
84       *
85       * @param element
86       * @param BaseURI
87       * @throws XMLSecurityException
88       */
89      public XMLX509SKI(Element element, String BaseURI) throws XMLSecurityException {
90          super(element, BaseURI);
91      }
92  
93      /**
94       * Method getSKIBytes
95       *
96       * @return the skibytes
97       * @throws XMLSecurityException
98       */
99      public byte[] getSKIBytes() throws XMLSecurityException {
100         return this.getBytesFromTextChild();
101     }
102 
103     /**
104      * Method getSKIBytesFromCert
105      *
106      * @param cert
107      * @return ski bytes from the given certificate
108      *
109      * @throws XMLSecurityException
110      * @see java.security.cert.X509Extension#getExtensionValue(java.lang.String)
111      */
112     public static byte[] getSKIBytesFromCert(X509Certificate cert)
113         throws XMLSecurityException {
114 
115         if (cert.getVersion() < 3) {
116             Object exArgs[] = { Integer.valueOf(cert.getVersion()) };
117             throw new XMLSecurityException("certificate.noSki.lowVersion", exArgs);
118         }
119 
120         /*
121          * Gets the DER-encoded OCTET string for the extension value
122          * (extnValue) identified by the passed-in oid String. The oid
123          * string is represented by a set of positive whole numbers
124          * separated by periods.
125          */
126         byte[] extensionValue = cert.getExtensionValue(XMLX509SKI.SKI_OID);
127         if (extensionValue == null) {
128             throw new XMLSecurityException("certificate.noSki.null");
129         }
130 
131         /**
132          * Strip away first four bytes from the extensionValue
133          * The first two bytes are the tag and length of the extensionValue
134          * OCTET STRING, and the next two bytes are the tag and length of
135          * the ski OCTET STRING.
136          */
137         byte skidValue[] = new byte[extensionValue.length - 4];
138 
139         System.arraycopy(extensionValue, 4, skidValue, 0, skidValue.length);
140 
141         if (log.isLoggable(java.util.logging.Level.FINE)) {
142             log.log(java.util.logging.Level.FINE, "Base64 of SKI is " + Base64.encode(skidValue));
143         }
144 
145         return skidValue;
146     }
147 
148     /** @inheritDoc */
149     public boolean equals(Object obj) {
150         if (!(obj instanceof XMLX509SKI)) {
151             return false;
152         }
153 
154         XMLX509SKI other = (XMLX509SKI) obj;
155 
156         try {
157             return Arrays.equals(other.getSKIBytes(), this.getSKIBytes());
158         } catch (XMLSecurityException ex) {
159             return false;
160         }
161     }
162 
163     public int hashCode() {
164         int result = 17;
165         try {
166             byte[] bytes = getSKIBytes();
167             for (int i = 0; i < bytes.length; i++) {
168                 result = 31 * result + bytes[i];
169             }
170         } catch (XMLSecurityException e) {
171             if (log.isLoggable(java.util.logging.Level.FINE)) {
172                 log.log(java.util.logging.Level.FINE, e.getMessage(), e);
173             }
174         }
175         return result;
176 
177     }
178 
179     /** @inheritDoc */
180     public String getBaseLocalName() {
181         return Constants._TAG_X509SKI;
182     }
183 }