TrustAnchor.java revision fd6bb3510c2f94d636f3572dcf5f7f4dcd1a2726
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 18package java.security.cert; 19 20import java.io.IOException; 21import java.security.PublicKey; 22 23import javax.security.auth.x500.X500Principal; 24 25import org.apache.harmony.security.internal.nls.Messages; 26import org.apache.harmony.security.utils.Array; 27import org.apache.harmony.security.x509.NameConstraints; 28 29 30 31/** 32 * This class represents a trust anchor for validation of X.509 certification 33 * path. 34 * <p> 35 * It is a <i>trusted</i> certificate authority (CA) and includes the public key 36 * of the CA, the CA's name and the constraints for the validation of 37 * certification paths. The constructor also allows to specify a binary 38 * representation of a so called "Name Constraints" extension as a byte array. 39 */ 40public class TrustAnchor { 41 // Most trusted CA as a X500Principal 42 private final X500Principal caPrincipal; 43 // Most trusted CA name 44 private final String caName; 45 // Most trusted CA public key 46 private final PublicKey caPublicKey; 47 // Most trusted CA certificate 48 private final X509Certificate trustedCert; 49 // Name constraints extension 50 private final byte[] nameConstraints; 51 52 /** 53 * Creates a new {@code TrustAnchor} with the specified certificate and name 54 * constraints. 55 * <p> 56 * The name constraints will be used as additional constraints during the 57 * validation of certification paths. 58 * 59 * @param trustedCert 60 * the trusted certificate 61 * @param nameConstraints 62 * the ASN.1 DER encoded form of the name constraints or {@code 63 * null} if none. 64 * @throws IllegalArgumentException 65 * if the decoding of the name constraints fail. 66 */ 67 public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) { 68 if (trustedCert == null) { 69 throw new NullPointerException(Messages.getString("security.5C")); 70 } 71 this.trustedCert = trustedCert; 72 // copy nameConstraints if not null 73 if (nameConstraints != null) { 74 this.nameConstraints = new byte[nameConstraints.length]; 75 System.arraycopy(nameConstraints, 0, 76 this.nameConstraints, 0, this.nameConstraints.length); 77 processNameConstraints(); 78 } else { 79 this.nameConstraints = null; 80 } 81 this.caName = null; 82 this.caPrincipal = null; 83 this.caPublicKey = null; 84 } 85 86 /** 87 * Creates a new {@code TrustAnchor} with the specified certificate 88 * authority name, its public key and the specified name constraints. 89 * <p> 90 * The name constraints will be used as additional constraints during the 91 * validation of certification paths. 92 * 93 * @param caName 94 * the X.500 name of the certificate authority in RFC 2253 95 * {@code String} format. 96 * @param caPublicKey 97 * the public key of the certificate authority 98 * @param nameConstraints 99 * the ASN.1 DER encoded form of the name constraints or {@code 100 * null} if none. 101 * @throws IllegalArgumentException 102 * if the {@code caName} is empty or if decoding of the name 103 * constraints fail. 104 */ 105 public TrustAnchor(String caName, PublicKey caPublicKey, 106 byte[] nameConstraints) { 107 if (caName == null) { 108 throw new NullPointerException(Messages.getString("security.5D")); 109 } 110 this.caName = caName; 111 if (caPublicKey == null) { 112 throw new NullPointerException(Messages.getString("security.5E")); 113 } 114 this.caPublicKey = caPublicKey; 115 // copy nameConstraints if not null 116 if (nameConstraints != null) { 117 this.nameConstraints = new byte[nameConstraints.length]; 118 System.arraycopy(nameConstraints, 0, 119 this.nameConstraints, 0, this.nameConstraints.length); 120 processNameConstraints(); 121 } else { 122 this.nameConstraints = null; 123 } 124 125 this.trustedCert = null; 126 127 // X500Principal checks caName validity 128 if (caName.length() == 0) { 129 throw new IllegalArgumentException( 130 Messages.getString("security.5F")); 131 } 132 this.caPrincipal = new X500Principal(this.caName); 133 } 134 135 /** 136 * Creates a new {@code TrustAnchor} with the specified certificate 137 * authority name as principal, its public key and the specified name 138 * constraints. 139 * <p> 140 * The name constraints will be used as additional constraints during the 141 * validation of certification paths. 142 * 143 * @param caPrincipal 144 * the name of the certificate authority as X500 principal. 145 * @param caPublicKey 146 * the public key of the certificate authority. 147 * @param nameConstraints 148 * the ASN.1 DER encoded form of the name constraints or {@code 149 * null} if none. 150 * @throws IllegalArgumentException 151 * if decoding of the name constraints fail. 152 */ 153 public TrustAnchor(X500Principal caPrincipal, 154 PublicKey caPublicKey, byte[] nameConstraints) { 155 if (caPrincipal == null) { 156 throw new NullPointerException(Messages.getString("security.60")); 157 } 158 this.caPrincipal = caPrincipal; 159 if (caPublicKey == null) { 160 throw new NullPointerException(Messages.getString("security.5E")); 161 } 162 this.caPublicKey = caPublicKey; 163 // copy nameConstraints if not null 164 if (nameConstraints != null) { 165 this.nameConstraints = new byte[nameConstraints.length]; 166 System.arraycopy(nameConstraints, 0, 167 this.nameConstraints, 0, this.nameConstraints.length); 168 processNameConstraints(); 169 } else { 170 this.nameConstraints = null; 171 } 172 173 this.trustedCert = null; 174 this.caName = caPrincipal.getName(); 175 } 176 177 /** 178 * Returns a copy of the name constraints in ASN.1 DER encoded form. 179 * 180 * @return a copy of the name constraints in ASN.1 DER encoded form. 181 */ 182 public final byte[] getNameConstraints() { 183 if (nameConstraints == null) { 184 return null; 185 } 186 byte[] ret = new byte[nameConstraints.length]; 187 System.arraycopy(nameConstraints, 0, 188 ret, 0, nameConstraints.length); 189 return ret; 190 } 191 192 /** 193 * Returns the certificate of this <i>trusted</i> certificate authority. 194 * 195 * @return the certificate of this CA or {@code null}, if the trust anchor 196 * of this instance was not created with a certificate. 197 */ 198 public final X509Certificate getTrustedCert() { 199 return trustedCert; 200 } 201 202 /** 203 * Returns the name of the certificate authority as {@code X500Principal}. 204 * 205 * @return the name of the certificate authority or {@code null} if the 206 * trust anchor of this instance was not created with a {@code 207 * X500Principal}. 208 */ 209 public final X500Principal getCA() { 210 return caPrincipal; 211 } 212 213 /** 214 * Returns the name of the certificate authority as {@code String} in RFC 215 * 2253 format. 216 * 217 * @return the name of the certificate authority as {@code String} in RFC 218 * 2253 format or {@code null} if the trust anchor of this instance 219 * was not created with a CA name. 220 */ 221 public final String getCAName() { 222 return caName; 223 } 224 225 /** 226 * Returns the public key of the certificate authority. 227 * 228 * @return the public key of the certificate authority or {@code null} if 229 * the trust anchor if this instance was not created with a public 230 * key. 231 */ 232 public final PublicKey getCAPublicKey() { 233 return caPublicKey; 234 } 235 236 /** 237 * Returns a string representation of this {@code TrustAnchor} instance. 238 * 239 * @return a string representation of this {@code TrustAnchor} instance. 240 */ 241 public String toString() { 242 StringBuilder sb = new StringBuilder("TrustAnchor: [\n"); 243 if (trustedCert != null) { 244 sb.append("Trusted CA certificate: "); 245 sb.append(trustedCert); 246 sb.append("\n"); 247 } 248 if (caPrincipal != null) { 249 sb.append("Trusted CA Name: "); 250 sb.append(caPrincipal); 251 sb.append("\n"); 252 } 253 if (caPublicKey != null) { 254 sb.append("Trusted CA Public Key: "); 255 sb.append(caPublicKey); 256 sb.append("\n"); 257 } 258 // FIXME if needed: 259 if (nameConstraints != null) { 260 sb.append("Name Constraints:\n"); 261 sb.append(Array.toString(nameConstraints, " ")); 262 } 263 sb.append("\n]"); 264 return sb.toString(); 265 } 266 267 // 268 // Private stuff 269 // 270 271 // Decodes and checks NameConstraints structure. 272 // Throws IllegalArgumentException if NameConstraints 273 // encoding is invalid. 274 private void processNameConstraints() { 275 try { 276 // decode and check nameConstraints 277 NameConstraints.ASN1.decode(nameConstraints); 278 } catch (IOException e) { 279 throw new IllegalArgumentException(e.getMessage()); 280 } 281 } 282} 283