1 /* 2 * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security; 27 28 import java.io.Serializable; 29 import java.util.*; 30 31 /** 32 * <p>This class represents identities: real-world objects such as people, 33 * companies or organizations whose identities can be authenticated using 34 * their public keys. Identities may also be more abstract (or concrete) 35 * constructs, such as daemon threads or smart cards. 36 * 37 * <p>All Identity objects have a name and a public key. Names are 38 * immutable. Identities may also be scoped. That is, if an Identity is 39 * specified to have a particular scope, then the name and public 40 * key of the Identity are unique within that scope. 41 * 42 * <p>An Identity also has a set of certificates (all certifying its own 43 * public key). The Principal names specified in these certificates need 44 * not be the same, only the key. 45 * 46 * <p>An Identity can be subclassed, to include postal and email addresses, 47 * telephone numbers, images of faces and logos, and so on. 48 * 49 * @see IdentityScope 50 * @see Signer 51 * @see Principal 52 * 53 * @author Benjamin Renaud 54 * @since 1.1 55 * @deprecated This class is deprecated and subject to removal in a future 56 * version of Java SE. It has been replaced by 57 * {@code java.security.KeyStore}, the {@code java.security.cert} package, 58 * and {@code java.security.Principal}. 59 */ 60 @Deprecated(since="1.2", forRemoval=true) 61 @SuppressWarnings("removal") 62 public abstract class Identity implements Principal, Serializable { 63 64 /** use serialVersionUID from JDK 1.1.x for interoperability */ 65 @java.io.Serial 66 private static final long serialVersionUID = 3609922007826600659L; 67 68 /** 69 * The name for this identity. 70 * 71 * @serial 72 */ 73 private String name; 74 75 /** 76 * The public key for this identity. 77 * 78 * @serial 79 */ 80 private PublicKey publicKey; 81 82 /** 83 * Generic, descriptive information about the identity. 84 * 85 * @serial 86 */ 87 String info = "No further information available."; 88 89 /** 90 * The scope of the identity. 91 * 92 * @serial 93 */ 94 IdentityScope scope; 95 96 /** 97 * The certificates for this identity. 98 * 99 * @serial 100 */ 101 Vector<Certificate> certificates; 102 103 /** 104 * Constructor for serialization only. 105 */ 106 protected Identity() { 107 this("restoring..."); 108 } 109 110 /** 111 * Constructs an identity with the specified name and scope. 112 * 113 * @param name the identity name. 114 * @param scope the scope of the identity. 115 * 116 * @exception KeyManagementException if there is already an identity 117 * with the same name in the scope. 118 */ 119 public Identity(String name, IdentityScope scope) throws 120 KeyManagementException { 121 this(name); 122 if (scope != null) { 123 scope.addIdentity(this); 124 } 125 this.scope = scope; 126 } 127 128 /** 129 * Constructs an identity with the specified name and no scope. 130 * 131 * @param name the identity name. 132 */ 133 public Identity(String name) { 134 this.name = name; 135 } 136 137 /** 138 * Returns this identity's name. 139 * 140 * @return the name of this identity. 141 */ 142 public final String getName() { 143 return name; 144 } 145 146 /** 147 * Returns this identity's scope. 148 * 149 * @return the scope of this identity. 150 */ 151 public final IdentityScope getScope() { 152 return scope; 153 } 154 155 /** 156 * Returns this identity's public key. 157 * 158 * @return the public key for this identity. 159 * 160 * @see #setPublicKey 161 */ 162 public PublicKey getPublicKey() { 163 return publicKey; 164 } 165 166 /** 167 * Sets this identity's public key. The old key and all of this 168 * identity's certificates are removed by this operation. 169 * 170 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 171 * method is called with {@code "setIdentityPublicKey"} 172 * as its argument to see if it's ok to set the public key. 173 * 174 * @param key the public key for this identity. 175 * 176 * @exception KeyManagementException if another identity in the 177 * identity's scope has the same public key, or if another exception occurs. 178 * 179 * @exception SecurityException if a security manager exists and its 180 * {@code checkSecurityAccess} method doesn't allow 181 * setting the public key. 182 * 183 * @see #getPublicKey 184 * @see SecurityManager#checkSecurityAccess 185 */ 186 /* Should we throw an exception if this is already set? */ 187 public void setPublicKey(PublicKey key) throws KeyManagementException { 188 189 check("setIdentityPublicKey"); 190 this.publicKey = key; 191 certificates = new Vector<>(); 192 } 193 194 /** 195 * Specifies a general information string for this identity. 196 * 197 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 198 * method is called with {@code "setIdentityInfo"} 199 * as its argument to see if it's ok to specify the information string. 200 * 201 * @param info the information string. 202 * 203 * @exception SecurityException if a security manager exists and its 204 * {@code checkSecurityAccess} method doesn't allow 205 * setting the information string. 206 * 207 * @see #getInfo 208 * @see SecurityManager#checkSecurityAccess 209 */ 210 public void setInfo(String info) { 211 check("setIdentityInfo"); 212 this.info = info; 213 } 214 215 /** 216 * Returns general information previously specified for this identity. 217 * 218 * @return general information about this identity. 219 * 220 * @see #setInfo 221 */ 222 public String getInfo() { 223 return info; 224 } 225 226 /** 227 * Adds a certificate for this identity. If the identity has a public 228 * key, the public key in the certificate must be the same, and if 229 * the identity does not have a public key, the identity's 230 * public key is set to be that specified in the certificate. 231 * 232 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 233 * method is called with {@code "addIdentityCertificate"} 234 * as its argument to see if it's ok to add a certificate. 235 * 236 * @param certificate the certificate to be added. 237 * 238 * @exception KeyManagementException if the certificate is not valid, 239 * if the public key in the certificate being added conflicts with 240 * this identity's public key, or if another exception occurs. 241 * 242 * @exception SecurityException if a security manager exists and its 243 * {@code checkSecurityAccess} method doesn't allow 244 * adding a certificate. 245 * 246 * @see SecurityManager#checkSecurityAccess 247 */ 248 public void addCertificate(Certificate certificate) 249 throws KeyManagementException { 250 251 check("addIdentityCertificate"); 252 253 if (certificates == null) { 254 certificates = new Vector<>(); 255 } 256 if (publicKey != null) { 257 if (!keyEquals(publicKey, certificate.getPublicKey())) { 258 throw new KeyManagementException( 259 "public key different from cert public key"); 260 } 261 } else { 262 publicKey = certificate.getPublicKey(); 263 } 264 certificates.addElement(certificate); 265 } 266 267 private boolean keyEquals(PublicKey aKey, PublicKey anotherKey) { 268 String aKeyFormat = aKey.getFormat(); 269 String anotherKeyFormat = anotherKey.getFormat(); 270 if ((aKeyFormat == null) ^ (anotherKeyFormat == null)) 271 return false; 272 if (aKeyFormat != null && anotherKeyFormat != null) 273 if (!aKeyFormat.equalsIgnoreCase(anotherKeyFormat)) 274 return false; 275 return java.util.Arrays.equals(aKey.getEncoded(), 276 anotherKey.getEncoded()); 277 } 278 279 280 /** 281 * Removes a certificate from this identity. 282 * 283 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 284 * method is called with {@code "removeIdentityCertificate"} 285 * as its argument to see if it's ok to remove a certificate. 286 * 287 * @param certificate the certificate to be removed. 288 * 289 * @exception KeyManagementException if the certificate is 290 * missing, or if another exception occurs. 291 * 292 * @exception SecurityException if a security manager exists and its 293 * {@code checkSecurityAccess} method doesn't allow 294 * removing a certificate. 295 * 296 * @see SecurityManager#checkSecurityAccess 297 */ 298 public void removeCertificate(Certificate certificate) 299 throws KeyManagementException { 300 check("removeIdentityCertificate"); 301 if (certificates != null) { 302 certificates.removeElement(certificate); 303 } 304 } 305 306 /** 307 * Returns a copy of all the certificates for this identity. 308 * 309 * @return a copy of all the certificates for this identity. 310 */ 311 public Certificate[] certificates() { 312 if (certificates == null) { 313 return new Certificate[0]; 314 } 315 int len = certificates.size(); 316 Certificate[] certs = new Certificate[len]; 317 certificates.copyInto(certs); 318 return certs; 319 } 320 321 /** 322 * Tests for equality between the specified object and this identity. 323 * This first tests to see if the entities actually refer to the same 324 * object, in which case it returns true. Next, it checks to see if 325 * the entities have the same name and the same scope. If they do, 326 * the method returns true. Otherwise, it calls 327 * {@link #identityEquals(Identity) identityEquals}, which subclasses should 328 * override. 329 * 330 * @param identity the object to test for equality with this identity. 331 * 332 * @return true if the objects are considered equal, false otherwise. 333 * 334 * @see #identityEquals 335 */ 336 public final boolean equals(Object identity) { 337 338 if (identity == this) { 339 return true; 340 } 341 342 if (identity instanceof Identity) { 343 Identity i = (Identity)identity; 344 if (this.fullName().equals(i.fullName())) { 345 return true; 346 } else { 347 return identityEquals(i); 348 } 349 } 350 return false; 351 } 352 353 /** 354 * Tests for equality between the specified identity and this identity. 355 * This method should be overridden by subclasses to test for equality. 356 * The default behavior is to return true if the names and public keys 357 * are equal. 358 * 359 * @param identity the identity to test for equality with this identity. 360 * 361 * @return true if the identities are considered equal, false 362 * otherwise. 363 * 364 * @see #equals 365 */ 366 protected boolean identityEquals(Identity identity) { 367 if (!name.equalsIgnoreCase(identity.name)) 368 return false; 369 370 if ((publicKey == null) ^ (identity.publicKey == null)) 371 return false; 372 373 if (publicKey != null && identity.publicKey != null) 374 if (!publicKey.equals(identity.publicKey)) 375 return false; 376 377 return true; 378 379 } 380 381 /** 382 * Returns a parsable name for identity: identityName.scopeName 383 */ 384 String fullName() { 385 String parsable = name; 386 if (scope != null) { 387 parsable += "." + scope.getName(); 388 } 389 return parsable; 390 } 391 392 /** 393 * Returns a short string describing this identity, telling its 394 * name and its scope (if any). 395 * 396 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 397 * method is called with {@code "printIdentity"} 398 * as its argument to see if it's ok to return the string. 399 * 400 * @return information about this identity, such as its name and the 401 * name of its scope (if any). 402 * 403 * @exception SecurityException if a security manager exists and its 404 * {@code checkSecurityAccess} method doesn't allow 405 * returning a string describing this identity. 406 * 407 * @see SecurityManager#checkSecurityAccess 408 */ 409 public String toString() { 410 check("printIdentity"); 411 String printable = name; 412 if (scope != null) { 413 printable += "[" + scope.getName() + "]"; 414 } 415 return printable; 416 } 417 418 /** 419 * Returns a string representation of this identity, with 420 * optionally more details than that provided by the 421 * {@code toString} method without any arguments. 422 * 423 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 424 * method is called with {@code "printIdentity"} 425 * as its argument to see if it's ok to return the string. 426 * 427 * @param detailed whether or not to provide detailed information. 428 * 429 * @return information about this identity. If {@code detailed} 430 * is true, then this method returns more information than that 431 * provided by the {@code toString} method without any arguments. 432 * 433 * @exception SecurityException if a security manager exists and its 434 * {@code checkSecurityAccess} method doesn't allow 435 * returning a string describing this identity. 436 * 437 * @see #toString 438 * @see SecurityManager#checkSecurityAccess 439 */ 440 public String toString(boolean detailed) { 441 String out = toString(); 442 if (detailed) { 443 out += "\n"; 444 out += printKeys(); 445 out += "\n" + printCertificates(); 446 if (info != null) { 447 out += "\n\t" + info; 448 } else { 449 out += "\n\tno additional information available."; 450 } 451 } 452 return out; 453 } 454 455 String printKeys() { 456 String key = ""; 457 if (publicKey != null) { 458 key = "\tpublic key initialized"; 459 } else { 460 key = "\tno public key"; 461 } 462 return key; 463 } 464 465 String printCertificates() { 466 String out = ""; 467 if (certificates == null) { 468 return "\tno certificates"; 469 } else { 470 out += "\tcertificates: \n"; 471 472 int i = 1; 473 for (Certificate cert : certificates) { 474 out += "\tcertificate " + i++ + 475 "\tfor : " + cert.getPrincipal() + "\n"; 476 out += "\t\t\tfrom : " + 477 cert.getGuarantor() + "\n"; 478 } 479 } 480 return out; 481 } 482 483 /** 484 * Returns a hashcode for this identity. 485 * 486 * @return a hashcode for this identity. 487 */ 488 public int hashCode() { 489 return name.hashCode(); 490 } 491 492 private static void check(String directive) { 493 SecurityManager security = System.getSecurityManager(); 494 if (security != null) { 495 security.checkSecurityAccess(directive); 496 } 497 } 498 }