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.Constants; 30 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; 31 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 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="https://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Extension.html"> 39 * Interface X509Extension</A> 40 */ 41 public class XMLX509SKI extends SignatureElementProxy implements XMLX509DataContent { 42 43 private static final com.sun.org.slf4j.internal.Logger LOG = 44 com.sun.org.slf4j.internal.LoggerFactory.getLogger(XMLX509SKI.class); 45 46 /** 47 * {@code SubjectKeyIdentifier (id-ce-subjectKeyIdentifier) (2.5.29.14)}: 48 * This extension identifies the public key being certified. It enables 49 * distinct keys used by the same subject to be differentiated 50 * (e.g., as key updating occurs). 51 * <p></p> 52 * A key identifier shall be unique with respect to all key identifiers 53 * for the subject with which it is used. This extension is always non-critical. 54 */ 55 public static final String SKI_OID = "2.5.29.14"; //NOPMD 56 57 /** 58 * Constructor X509SKI 59 * 60 * @param doc 61 * @param skiBytes 62 */ XMLX509SKI(Document doc, byte[] skiBytes)63 public XMLX509SKI(Document doc, byte[] skiBytes) { 64 super(doc); 65 this.addBase64Text(skiBytes); 66 } 67 68 /** 69 * Constructor XMLX509SKI 70 * 71 * @param doc 72 * @param x509certificate 73 * @throws XMLSecurityException 74 */ XMLX509SKI(Document doc, X509Certificate x509certificate)75 public XMLX509SKI(Document doc, X509Certificate x509certificate) 76 throws XMLSecurityException { 77 super(doc); 78 this.addBase64Text(XMLX509SKI.getSKIBytesFromCert(x509certificate)); 79 } 80 81 /** 82 * Constructor XMLX509SKI 83 * 84 * @param element 85 * @param baseURI 86 * @throws XMLSecurityException 87 */ XMLX509SKI(Element element, String baseURI)88 public XMLX509SKI(Element element, String baseURI) throws XMLSecurityException { 89 super(element, baseURI); 90 } 91 92 /** 93 * Method getSKIBytes 94 * 95 * @return the skibytes 96 * @throws XMLSecurityException 97 */ getSKIBytes()98 public byte[] getSKIBytes() throws XMLSecurityException { 99 return this.getBytesFromTextChild(); 100 } 101 102 /** 103 * Method getSKIBytesFromCert 104 * 105 * @param cert 106 * @return ski bytes from the given certificate 107 * 108 * @throws XMLSecurityException 109 * @see java.security.cert.X509Extension#getExtensionValue(java.lang.String) 110 */ getSKIBytesFromCert(X509Certificate cert)111 public static byte[] getSKIBytesFromCert(X509Certificate cert) 112 throws XMLSecurityException { 113 114 if (cert.getVersion() < 3) { 115 Object exArgs[] = { cert.getVersion() }; 116 throw new XMLSecurityException("certificate.noSki.lowVersion", exArgs); 117 } 118 119 /* 120 * Gets the DER-encoded OCTET string for the extension value 121 * (extnValue) identified by the passed-in oid String. The oid 122 * string is represented by a set of positive whole numbers 123 * separated by periods. 124 */ 125 byte[] extensionValue = cert.getExtensionValue(XMLX509SKI.SKI_OID); 126 if (extensionValue == null) { 127 throw new XMLSecurityException("certificate.noSki.null"); 128 } 129 130 /** 131 * Strip away first four bytes from the extensionValue 132 * The first two bytes are the tag and length of the extensionValue 133 * OCTET STRING, and the next two bytes are the tag and length of 134 * the ski OCTET STRING. 135 */ 136 byte skidValue[] = new byte[extensionValue.length - 4]; 137 138 System.arraycopy(extensionValue, 4, skidValue, 0, skidValue.length); 139 140 if (LOG.isDebugEnabled()) { 141 LOG.debug("Base64 of SKI is " + XMLUtils.encodeToString(skidValue)); 142 } 143 144 return skidValue; 145 } 146 147 /** {@inheritDoc} */ equals(Object obj)148 public boolean equals(Object obj) { 149 if (!(obj instanceof XMLX509SKI)) { 150 return false; 151 } 152 153 XMLX509SKI other = (XMLX509SKI) obj; 154 155 try { 156 return Arrays.equals(other.getSKIBytes(), this.getSKIBytes()); 157 } catch (XMLSecurityException ex) { 158 return false; 159 } 160 } 161 hashCode()162 public int hashCode() { 163 int result = 17; 164 try { 165 byte[] bytes = getSKIBytes(); 166 for (int i = 0; i < bytes.length; i++) { 167 result = 31 * result + bytes[i]; 168 } 169 } catch (XMLSecurityException e) { 170 LOG.debug(e.getMessage(), e); 171 } 172 return result; 173 174 } 175 176 /** {@inheritDoc} */ getBaseLocalName()177 public String getBaseLocalName() { 178 return Constants._TAG_X509SKI; 179 } 180 } 181