1 module hunt.security.x509.AlgorithmId; 2 3 import hunt.security.AlgorithmParameters; 4 5 import hunt.security.util.DerEncoder; 6 import hunt.security.util.DerInputStream; 7 import hunt.security.util.DerOutputStream; 8 import hunt.security.util.DerValue; 9 import hunt.security.util.ObjectIdentifier; 10 11 import hunt.collection; 12 import hunt.stream.Common; 13 14 import hunt.Exceptions; 15 import hunt.text.Common; 16 import hunt.util.StringBuilder; 17 18 import std.string; 19 20 21 /** 22 * This class identifies algorithms, such as cryptographic transforms, each 23 * of which may be associated with parameters. Instances of this base class 24 * are used when this runtime environment has no special knowledge of the 25 * algorithm type, and may also be used in other cases. Equivalence is 26 * defined according to OID and (where relevant) parameters. 27 * 28 * <P>Subclasses may be used, for example when when the algorithm ID has 29 * associated parameters which some code (e.g. code using keys) needs 30 * to have parsed. Two examples of such algorithms are Diffie-Hellman key 31 * exchange, and the Digital Signature Standard Algorithm (DSS/DSA). 32 * 33 * <P>The OID constants defined in this class correspond to some widely 34 * used algorithms, for which conventional string names have been defined. 35 * This class is not a general repository for OIDs, or for such string names. 36 * Note that the mappings between algorithm IDs and algorithm names is 37 * not one-to-one. 38 * 39 * 40 * @author David Brownell 41 * @author Amit Kapoor 42 * @author Hemma Prafullchandra 43 */ 44 class AlgorithmId : DerEncoder { 45 46 /** use serialVersionUID from JDK 1.1. for interoperability */ 47 // private static final long serialVersionUID = 7205873507486557157L; 48 49 /** 50 * The object identitifer being used for this algorithm. 51 */ 52 private ObjectIdentifier algid; 53 54 // The (parsed) parameters 55 private AlgorithmParameters algParams; 56 private bool constructedFromDer = true; 57 58 /** 59 * Parameters for this algorithm. These are stored in unparsed 60 * DER-encoded form; subclasses can be made to automaticaly parse 61 * them so there is fast access to these parameters. 62 */ 63 protected DerValue params; 64 65 66 /** 67 * Constructs an algorithm ID which will be initialized 68 * separately, for example by deserialization. 69 * @deprecated use one of the other constructors. 70 */ 71 // @Deprecated 72 // this() { } 73 74 /** 75 * Constructs a parameterless algorithm ID. 76 * 77 * @param oid the identifier for the algorithm 78 */ 79 this(ObjectIdentifier oid) { 80 algid = oid; 81 } 82 83 /** 84 * Constructs an algorithm ID with algorithm parameters. 85 * 86 * @param oid the identifier for the algorithm. 87 * @param algparams the associated algorithm parameters. 88 */ 89 this(ObjectIdentifier oid, AlgorithmParameters algparams) { 90 algid = oid; 91 algParams = algparams; 92 constructedFromDer = false; 93 } 94 95 private this(ObjectIdentifier oid, DerValue params){ 96 this.algid = oid; 97 this.params = params; 98 if (this.params !is null) { 99 decodeParams(); 100 } 101 } 102 103 protected void decodeParams() { 104 string algidString = algid.toString(); 105 try { 106 algParams = AlgorithmParameters.getInstance(algidString); 107 } catch (NoSuchAlgorithmException e) { 108 /* 109 * This algorithm parameter type is not supported, so we cannot 110 * parse the parameters. 111 */ 112 algParams = null; 113 return; 114 } 115 116 // Decode (parse) the parameters 117 try { 118 algParams.initilize(params.toByteArray()); 119 } catch (IOException e) { 120 if (null != e.msg && e.msg.startsWith("Unknown named curve: ")) { 121 // named curve not supported 122 algParams = null; 123 return; 124 } 125 throw e; 126 } 127 } 128 129 /** 130 * Marshal a DER-encoded "AlgorithmID" sequence on the DER stream. 131 */ 132 final void encode(DerOutputStream o) { 133 derEncode(o); 134 } 135 136 /** 137 * DER encode this object onto an output stream. 138 * Implements the <code>DerEncoder</code> interface. 139 * 140 * @param outputStream 141 * the output stream on which to write the DER encoding. 142 * 143 * @exception IOException on encoding error. 144 */ 145 void derEncode (OutputStream outputStream) { 146 DerOutputStream bytes = new DerOutputStream(); 147 DerOutputStream tmp = new DerOutputStream(); 148 149 algid.encode(bytes); 150 151 // Setup params from algParams since no DER encoding is given 152 if (constructedFromDer == false) { 153 if (algParams !is null) { 154 params = new DerValue(algParams.getEncoded()); 155 } else { 156 params = null; 157 } 158 } 159 if (params is null) { 160 // Changes backed out for compatibility with Solaris 161 162 // Several AlgorithmId should omit the whole parameter part when 163 // it's NULL. They are --- 164 // rfc3370 2.1: Implementations SHOULD generate SHA-1 165 // AlgorithmIdentifiers with absent parameters. 166 // rfc3447 C1: When id-sha1, id-sha224, id-sha256, id-sha384 and 167 // id-sha512 are used in an AlgorithmIdentifier the parameters 168 // (which are optional) SHOULD be omitted. 169 // rfc3279 2.3.2: The id-dsa algorithm syntax includes optional 170 // domain parameters... When omitted, the parameters component 171 // MUST be omitted entirely 172 // rfc3370 3.1: When the id-dsa-with-sha1 algorithm identifier 173 // is used, the AlgorithmIdentifier parameters field MUST be absent. 174 /*if ( 175 algid.equals((Object)SHA_oid) || 176 algid.equals((Object)SHA224_oid) || 177 algid.equals((Object)SHA256_oid) || 178 algid.equals((Object)SHA384_oid) || 179 algid.equals((Object)SHA512_oid) || 180 algid.equals((Object)DSA_oid) || 181 algid.equals((Object)sha1WithDSA_oid)) { 182 ; // no parameter part encoded 183 } else { 184 bytes.putNull(); 185 }*/ 186 bytes.putNull(); 187 } else { 188 bytes.putDerValue(params); 189 } 190 tmp.write(DerValue.tag_Sequence, bytes); 191 outputStream.write(tmp.toByteArray()); 192 } 193 194 195 /** 196 * Returns the DER-encoded X.509 AlgorithmId as a byte array. 197 */ 198 final byte[] encode() { 199 DerOutputStream outputStream = new DerOutputStream(); 200 derEncode(outputStream); 201 return outputStream.toByteArray(); 202 } 203 204 /** 205 * Returns the ISO OID for this algorithm. This is usually converted 206 * to a string and used as part of an algorithm name, for example 207 * "OID.1.3.14.3.2.13" style notation. Use the <code>getName</code> 208 * call when you do not need to ensure cross-system portability 209 * of algorithm names, or need a user friendly name. 210 */ 211 final ObjectIdentifier getOID () { 212 return algid; 213 } 214 215 /** 216 * Returns a name for the algorithm which may be more intelligible 217 * to humans than the algorithm's OID, but which won't necessarily 218 * be comprehensible on other systems. For example, this might 219 * return a name such as "MD5withRSA" for a signature algorithm on 220 * some systems. It also returns names like "OID.1.2.3.4", when 221 * no particular name for the algorithm is known. 222 */ 223 string getName() { 224 string algName = nameTable.get(algid); 225 if (algName !is null) { 226 return algName; 227 } 228 if ((params !is null) && algid.opEquals(cast(Object)specifiedWithECDSA_oid)) { 229 try { 230 AlgorithmId paramsId = 231 AlgorithmId.parse(new DerValue(getEncodedParams())); 232 string paramsName = paramsId.getName(); 233 algName = makeSigAlg(paramsName, "EC"); 234 } catch (IOException e) { 235 // ignore 236 } 237 } 238 return (algName is null) ? algid.toString() : algName; 239 } 240 241 AlgorithmParameters getParameters() { 242 return algParams; 243 } 244 245 /** 246 * Returns the DER encoded parameter, which can then be 247 * used to initialize java.security.AlgorithmParamters. 248 * 249 * @return DER encoded parameters, or null not present. 250 */ 251 byte[] getEncodedParams() { 252 return (params is null) ? null : params.toByteArray(); 253 } 254 255 /** 256 * Returns true iff the argument indicates the same algorithm 257 * with the same parameters. 258 */ 259 bool equals(AlgorithmId other) { 260 bool paramsEqual = 261 (params is null ? other.params is null : params.opEquals(other.params)); 262 return algid == other.algid && paramsEqual; 263 } 264 265 /** 266 * Compares this AlgorithmID to another. If algorithm parameters are 267 * available, they are compared. Otherwise, just the object IDs 268 * for the algorithm are compared. 269 * 270 * @param other preferably an AlgorithmId, else an ObjectIdentifier 271 */ 272 override bool opEquals(Object other) { 273 if (this is other) { 274 return true; 275 } 276 AlgorithmId aid = cast(AlgorithmId) other; 277 if (aid !is null) { 278 return equals(aid); 279 } 280 ObjectIdentifier oid = cast(ObjectIdentifier) other; 281 if (oid !is null) { 282 return equals(oid); 283 } else { 284 return false; 285 } 286 } 287 288 /** 289 * Compares two algorithm IDs for equality. Returns true iff 290 * they are the same algorithm, ignoring algorithm parameters. 291 */ 292 final bool equals(ObjectIdentifier id) { 293 return algid == id; 294 } 295 296 /** 297 * Returns a hashcode for this AlgorithmId. 298 * 299 * @return a hashcode for this AlgorithmId. 300 */ 301 override size_t toHash() @trusted nothrow { 302 try 303 { 304 StringBuilder sbuf = new StringBuilder(); 305 sbuf.append(algid.toString()); 306 sbuf.append(paramsToString()); 307 return sbuf.toString().hashOf(); 308 } 309 catch(Exception) 310 { 311 return 0; 312 } 313 } 314 315 /** 316 * Provides a human-readable description of the algorithm parameters. 317 * This may be redefined by subclasses which parse those parameters. 318 */ 319 protected string paramsToString() { 320 if (params is null) { 321 return ""; 322 } else if (algParams !is null) { 323 return algParams.toString(); 324 } else { 325 return ", params unparsed"; 326 } 327 } 328 329 /** 330 * Returns a string describing the algorithm and its parameters. 331 */ 332 override string toString() { 333 return getName() ~ paramsToString(); 334 } 335 336 /** 337 * Parse (unmarshal) an ID from a DER sequence input value. This form 338 * parsing might be used when expanding a value which has already been 339 * partially unmarshaled as a set or sequence member. 340 * 341 * @exception IOException on error. 342 * @param val the input value, which contains the algid and, if 343 * there are any parameters, those parameters. 344 * @return an ID for the algorithm. If the system is configured 345 * appropriately, this may be an instance of a class 346 * with some kind of special support for this algorithm. 347 * In that case, you may "narrow" the type of the ID. 348 */ 349 static AlgorithmId parse(DerValue val) { 350 if (val.tag != DerValue.tag_Sequence) { 351 throw new IOException("algid parse error, not a sequence"); 352 } 353 354 /* 355 * Get the algorithm ID and any parameters. 356 */ 357 ObjectIdentifier algid; 358 DerValue params; 359 DerInputStream inputStream; // = val.toDerInputStream(); 360 // inputStream = new DerInputStream(val.toByteArray); 361 362 implementationMissing(false); 363 364 // algid = new ObjectIdentifier(inputStream); // inputStream.getOID(); 365 // if (inputStream.available() == 0) { 366 // params = null; 367 // } else { 368 // params = inputStream.getDerValue(); 369 // if (params.tag == DerValue.tag_Null) { 370 // if (params.length() != 0) { 371 // throw new IOException("invalid NULL"); 372 // } 373 // params = null; 374 // } 375 // if (inputStream.available() != 0) { 376 // throw new IOException("Invalid AlgorithmIdentifier: extra data"); 377 // } 378 // } 379 380 // return new AlgorithmId(algid, params); 381 return null; 382 } 383 384 /** 385 * Returns one of the algorithm IDs most commonly associated 386 * with this algorithm name. 387 * 388 * @param algname the name being used 389 * @deprecated use the short get form of this method. 390 * @exception NoSuchAlgorithmException on error. 391 */ 392 // @Deprecated 393 // static AlgorithmId getAlgorithmId(string algname) { 394 // return get(algname); 395 // } 396 397 /** 398 * Returns one of the algorithm IDs most commonly associated 399 * with this algorithm name. 400 * 401 * @param algname the name being used 402 * @exception NoSuchAlgorithmException on error. 403 */ 404 static AlgorithmId get(string algname) { 405 ObjectIdentifier oid; 406 try { 407 oid = algOID(algname); 408 } catch (IOException ioe) { 409 throw new NoSuchAlgorithmException 410 ("Invalid ObjectIdentifier " ~ algname); 411 } 412 413 if (oid is null) { 414 throw new NoSuchAlgorithmException 415 ("unrecognized algorithm name: " ~ algname); 416 } 417 return new AlgorithmId(oid); 418 } 419 420 /** 421 * Returns one of the algorithm IDs most commonly associated 422 * with this algorithm parameters. 423 * 424 * @param algparams the associated algorithm parameters. 425 * @exception NoSuchAlgorithmException on error. 426 */ 427 static AlgorithmId get(AlgorithmParameters algparams) { 428 ObjectIdentifier oid; 429 string algname = algparams.getAlgorithm(); 430 try { 431 oid = algOID(algname); 432 } catch (IOException ioe) { 433 throw new NoSuchAlgorithmException 434 ("Invalid ObjectIdentifier " ~ algname); 435 } 436 if (oid is null) { 437 throw new NoSuchAlgorithmException 438 ("unrecognized algorithm name: " ~ algname); 439 } 440 return new AlgorithmId(oid, algparams); 441 } 442 443 /* 444 * Translates from some common algorithm names to the 445 * OID with which they're usually associated ... this mapping 446 * is the reverse of the one below, except in those cases 447 * where synonyms are supported or where a given algorithm 448 * is commonly associated with multiple OIDs. 449 * 450 * XXX This method needs to be enhanced so that we can also pass the 451 * scope of the algorithm name to it, e.g., the algorithm name "DSA" 452 * may have a different OID when used as a "Signature" algorithm than when 453 * used as a "KeyPairGenerator" algorithm. 454 */ 455 private static ObjectIdentifier algOID(string name) { 456 // See if algname is in printable OID ("dot-dot") notation 457 if (name.indexOf('.') != -1) { 458 if (name.startsWith("OID.")) { 459 return new ObjectIdentifier(name.substring("OID.".length)); 460 } else { 461 return new ObjectIdentifier(name); 462 } 463 } 464 465 // Digesting algorithms 466 if (name.equalsIgnoreCase("MD5")) { 467 return AlgorithmId.MD5_oid; 468 } 469 if (name.equalsIgnoreCase("MD2")) { 470 return AlgorithmId.MD2_oid; 471 } 472 if (name.equalsIgnoreCase("SHA") || name.equalsIgnoreCase("SHA1") 473 || name.equalsIgnoreCase("SHA-1")) { 474 return AlgorithmId.SHA_oid; 475 } 476 if (name.equalsIgnoreCase("SHA-256") || 477 name.equalsIgnoreCase("SHA256")) { 478 return AlgorithmId.SHA256_oid; 479 } 480 if (name.equalsIgnoreCase("SHA-384") || 481 name.equalsIgnoreCase("SHA384")) { 482 return AlgorithmId.SHA384_oid; 483 } 484 if (name.equalsIgnoreCase("SHA-512") || 485 name.equalsIgnoreCase("SHA512")) { 486 return AlgorithmId.SHA512_oid; 487 } 488 if (name.equalsIgnoreCase("SHA-224") || 489 name.equalsIgnoreCase("SHA224")) { 490 return AlgorithmId.SHA224_oid; 491 } 492 493 // Various key algorithms 494 if (name.equalsIgnoreCase("RSA")) { 495 return AlgorithmId.RSAEncryption_oid; 496 } 497 if (name.equalsIgnoreCase("Diffie-Hellman") 498 || name.equalsIgnoreCase("DH")) { 499 return AlgorithmId.DH_oid; 500 } 501 if (name.equalsIgnoreCase("DSA")) { 502 return AlgorithmId.DSA_oid; 503 } 504 if (name.equalsIgnoreCase("EC")) { 505 return EC_oid; 506 } 507 if (name.equalsIgnoreCase("ECDH")) { 508 return AlgorithmId.ECDH_oid; 509 } 510 511 // Secret key algorithms 512 if (name.equalsIgnoreCase("AES")) { 513 return AlgorithmId.AES_oid; 514 } 515 516 // Common signature types 517 if (name.equalsIgnoreCase("MD5withRSA") 518 || name.equalsIgnoreCase("MD5/RSA")) { 519 return AlgorithmId.md5WithRSAEncryption_oid; 520 } 521 if (name.equalsIgnoreCase("MD2withRSA") 522 || name.equalsIgnoreCase("MD2/RSA")) { 523 return AlgorithmId.md2WithRSAEncryption_oid; 524 } 525 if (name.equalsIgnoreCase("SHAwithDSA") 526 || name.equalsIgnoreCase("SHA1withDSA") 527 || name.equalsIgnoreCase("SHA/DSA") 528 || name.equalsIgnoreCase("SHA1/DSA") 529 || name.equalsIgnoreCase("DSAWithSHA1") 530 || name.equalsIgnoreCase("DSS") 531 || name.equalsIgnoreCase("SHA-1/DSA")) { 532 return AlgorithmId.sha1WithDSA_oid; 533 } 534 if (name.equalsIgnoreCase("SHA224WithDSA")) { 535 return AlgorithmId.sha224WithDSA_oid; 536 } 537 if (name.equalsIgnoreCase("SHA256WithDSA")) { 538 return AlgorithmId.sha256WithDSA_oid; 539 } 540 if (name.equalsIgnoreCase("SHA1WithRSA") 541 || name.equalsIgnoreCase("SHA1/RSA")) { 542 return AlgorithmId.sha1WithRSAEncryption_oid; 543 } 544 if (name.equalsIgnoreCase("SHA1withECDSA") 545 || name.equalsIgnoreCase("ECDSA")) { 546 return AlgorithmId.sha1WithECDSA_oid; 547 } 548 if (name.equalsIgnoreCase("SHA224withECDSA")) { 549 return AlgorithmId.sha224WithECDSA_oid; 550 } 551 if (name.equalsIgnoreCase("SHA256withECDSA")) { 552 return AlgorithmId.sha256WithECDSA_oid; 553 } 554 if (name.equalsIgnoreCase("SHA384withECDSA")) { 555 return AlgorithmId.sha384WithECDSA_oid; 556 } 557 if (name.equalsIgnoreCase("SHA512withECDSA")) { 558 return AlgorithmId.sha512WithECDSA_oid; 559 } 560 561 implementationMissing(); 562 563 // See if any of the installed providers supply a mapping from 564 // the given algorithm name to an OID string 565 // string oidString; 566 // if (!initOidTable) { 567 // Provider[] provs = Security.getProviders(); 568 // for (int i=0; i<provs.length; i++) { 569 // for (Enumeration!Object enum_ = provs[i].keys(); 570 // enum_.hasMoreElements(); ) { 571 // string alias = (string)enum_.nextElement(); 572 // string upperCaseAlias = alias.toUpperCase(Locale.ENGLISH); 573 // int index; 574 // if (upperCaseAlias.startsWith("ALG.ALIAS") && 575 // (index=upperCaseAlias.indexOf("OID.", 0)) != -1) { 576 // index += "OID.".length(); 577 // if (index == alias.length()) { 578 // // invalid alias entry 579 // break; 580 // } 581 // if (oidTable is null) { 582 // oidTable = new HashMap!(string,ObjectIdentifier)(); 583 // } 584 // oidString = alias.substring(index); 585 // string stdAlgName = provs[i].getProperty(alias); 586 // if (stdAlgName !is null) { 587 // stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH); 588 // } 589 // if (stdAlgName !is null && 590 // oidTable.get(stdAlgName) is null) { 591 // oidTable.put(stdAlgName, 592 // new ObjectIdentifier(oidString)); 593 // } 594 // } 595 // } 596 // } 597 598 // if (oidTable is null) { 599 // oidTable = Collections.!(string,ObjectIdentifier)emptyMap(); 600 // } 601 // initOidTable = true; 602 // } 603 604 return oidTable.get(name.toUpper()); 605 } 606 607 private static ObjectIdentifier oid(int[] values...) { 608 return ObjectIdentifier.newInternal(values); 609 } 610 611 private static bool initOidTable = false; 612 private static Map!(string,ObjectIdentifier) oidTable; 613 private __gshared static Map!(ObjectIdentifier,string) nameTable; 614 615 /*****************************************************************/ 616 617 /* 618 * HASHING ALGORITHMS 619 */ 620 621 /** 622 * Algorithm ID for the MD2 Message Digest Algorthm, from RFC 1319. 623 * OID = 1.2.840.113549.2.2 624 */ 625 __gshared static ObjectIdentifier MD2_oid; 626 627 /** 628 * Algorithm ID for the MD5 Message Digest Algorthm, from RFC 1321. 629 * OID = 1.2.840.113549.2.5 630 */ 631 __gshared static ObjectIdentifier MD5_oid; 632 633 /** 634 * Algorithm ID for the SHA1 Message Digest Algorithm, from FIPS 180-1. 635 * This is sometimes called "SHA", though that is often confusing since 636 * many people refer to FIPS 180 (which has an error) as defining SHA. 637 * OID = 1.3.14.3.2.26. Old SHA-0 OID: 1.3.14.3.2.18. 638 */ 639 __gshared static ObjectIdentifier SHA_oid; 640 641 __gshared static ObjectIdentifier SHA224_oid; 642 643 __gshared static ObjectIdentifier SHA256_oid; 644 645 __gshared static ObjectIdentifier SHA384_oid; 646 647 __gshared static ObjectIdentifier SHA512_oid; 648 649 /* 650 * COMMON PUBLIC KEY TYPES 651 */ 652 private enum int[] DH_data = [ 1, 2, 840, 113549, 1, 3, 1 ]; 653 private enum int[] DH_PKIX_data = [ 1, 2, 840, 10046, 2, 1 ]; 654 private enum int[] DSA_OIW_data = [ 1, 3, 14, 3, 2, 12 ]; 655 private enum int[] DSA_PKIX_data = [ 1, 2, 840, 10040, 4, 1 ]; 656 private enum int[] RSA_data = [ 2, 5, 8, 1, 1 ]; 657 private enum int[] RSAEncryption_data = 658 [ 1, 2, 840, 113549, 1, 1, 1 ]; 659 660 __gshared static ObjectIdentifier DH_oid; 661 __gshared static ObjectIdentifier DH_PKIX_oid; 662 __gshared static ObjectIdentifier DSA_oid; 663 __gshared static ObjectIdentifier DSA_OIW_oid; 664 __gshared static ObjectIdentifier EC_oid; 665 __gshared static ObjectIdentifier ECDH_oid; 666 __gshared static ObjectIdentifier RSA_oid; 667 __gshared static ObjectIdentifier RSAEncryption_oid; 668 669 /* 670 * COMMON SECRET KEY TYPES 671 */ 672 __gshared static ObjectIdentifier AES_oid; 673 674 /* 675 * COMMON SIGNATURE ALGORITHMS 676 */ 677 private enum int[] md2WithRSAEncryption_data = 678 [ 1, 2, 840, 113549, 1, 1, 2 ]; 679 private enum int[] md5WithRSAEncryption_data = 680 [ 1, 2, 840, 113549, 1, 1, 4 ]; 681 private enum int[] sha1WithRSAEncryption_data = 682 [ 1, 2, 840, 113549, 1, 1, 5 ]; 683 private enum int[] sha1WithRSAEncryption_OIW_data = 684 [ 1, 3, 14, 3, 2, 29 ]; 685 private enum int[] sha224WithRSAEncryption_data = 686 [ 1, 2, 840, 113549, 1, 1, 14 ]; 687 private enum int[] sha256WithRSAEncryption_data = 688 [ 1, 2, 840, 113549, 1, 1, 11 ]; 689 private enum int[] sha384WithRSAEncryption_data = 690 [ 1, 2, 840, 113549, 1, 1, 12 ]; 691 private enum int[] sha512WithRSAEncryption_data = 692 [ 1, 2, 840, 113549, 1, 1, 13 ]; 693 private enum int[] shaWithDSA_OIW_data = 694 [ 1, 3, 14, 3, 2, 13 ]; 695 private enum int[] sha1WithDSA_OIW_data = 696 [ 1, 3, 14, 3, 2, 27 ]; 697 private enum int[] dsaWithSHA1_PKIX_data = 698 [ 1, 2, 840, 10040, 4, 3 ]; 699 700 __gshared static ObjectIdentifier md2WithRSAEncryption_oid; 701 __gshared static ObjectIdentifier md5WithRSAEncryption_oid; 702 __gshared static ObjectIdentifier sha1WithRSAEncryption_oid; 703 __gshared static ObjectIdentifier sha1WithRSAEncryption_OIW_oid; 704 __gshared static ObjectIdentifier sha224WithRSAEncryption_oid; 705 __gshared static ObjectIdentifier sha256WithRSAEncryption_oid; 706 __gshared static ObjectIdentifier sha384WithRSAEncryption_oid; 707 __gshared static ObjectIdentifier sha512WithRSAEncryption_oid; 708 __gshared static ObjectIdentifier shaWithDSA_OIW_oid; 709 __gshared static ObjectIdentifier sha1WithDSA_OIW_oid; 710 __gshared static ObjectIdentifier sha1WithDSA_oid; 711 __gshared static ObjectIdentifier sha224WithDSA_oid; 712 __gshared static ObjectIdentifier sha256WithDSA_oid; 713 714 __gshared static ObjectIdentifier sha1WithECDSA_oid; 715 __gshared static ObjectIdentifier sha224WithECDSA_oid; 716 __gshared static ObjectIdentifier sha256WithECDSA_oid; 717 __gshared static ObjectIdentifier sha384WithECDSA_oid; 718 __gshared static ObjectIdentifier sha512WithECDSA_oid; 719 __gshared static ObjectIdentifier specifiedWithECDSA_oid; 720 721 /** 722 * Algorithm ID for the PBE encryption algorithms from PKCS#5 and 723 * PKCS#12. 724 */ 725 __gshared static ObjectIdentifier pbeWithMD5AndDES_oid; 726 __gshared static ObjectIdentifier pbeWithMD5AndRC2_oid; 727 __gshared static ObjectIdentifier pbeWithSHA1AndDES_oid; 728 __gshared static ObjectIdentifier pbeWithSHA1AndRC2_oid; 729 __gshared static ObjectIdentifier pbeWithSHA1AndDESede_oid; 730 __gshared static ObjectIdentifier pbeWithSHA1AndRC2_40_oid; 731 732 shared static this() { 733 MD2_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 2, 2]); 734 MD5_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 2, 5]); 735 SHA_oid = ObjectIdentifier.newInternal([1, 3, 14, 3, 2, 26]); 736 SHA224_oid = ObjectIdentifier.newInternal([2, 16, 840, 1, 101, 3, 4, 2, 4]); 737 SHA256_oid = ObjectIdentifier.newInternal([2, 16, 840, 1, 101, 3, 4, 2, 1]); 738 SHA384_oid = ObjectIdentifier.newInternal([2, 16, 840, 1, 101, 3, 4, 2, 2]); 739 SHA512_oid = ObjectIdentifier.newInternal([2, 16, 840, 1, 101, 3, 4, 2, 3]); 740 741 EC_oid = oid(1, 2, 840, 10045, 2, 1); 742 ECDH_oid = oid(1, 3, 132, 1, 12); 743 AES_oid = oid(2, 16, 840, 1, 101, 3, 4, 1); 744 sha224WithDSA_oid = oid(2, 16, 840, 1, 101, 3, 4, 3, 1); 745 sha256WithDSA_oid = oid(2, 16, 840, 1, 101, 3, 4, 3, 2); 746 747 sha1WithECDSA_oid = oid(1, 2, 840, 10045, 4, 1); 748 sha224WithECDSA_oid = oid(1, 2, 840, 10045, 4, 3, 1); 749 sha256WithECDSA_oid = oid(1, 2, 840, 10045, 4, 3, 2); 750 sha384WithECDSA_oid = oid(1, 2, 840, 10045, 4, 3, 3); 751 sha512WithECDSA_oid = oid(1, 2, 840, 10045, 4, 3, 4); 752 specifiedWithECDSA_oid = oid(1, 2, 840, 10045, 4, 3); 753 754 pbeWithMD5AndDES_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 1, 5, 3]); 755 pbeWithMD5AndRC2_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 1, 5, 6]); 756 pbeWithSHA1AndDES_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 1, 5, 10]); 757 pbeWithSHA1AndRC2_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 1, 5, 11]); 758 pbeWithSHA1AndDESede_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 1, 12, 1, 3]); 759 pbeWithSHA1AndRC2_40_oid = ObjectIdentifier.newInternal([1, 2, 840, 113549, 1, 12, 1, 6]); 760 /* 761 * Note the preferred OIDs are named simply with no "OIW" or 762 * "PKIX" in them, even though they may point to data from these 763 * specs; e.g. SHA_oid, DH_oid, DSA_oid, SHA1WithDSA_oid... 764 */ 765 /** 766 * Algorithm ID for Diffie Hellman Key agreement, from PKCS #3. 767 * Parameters include values P and G, and may optionally specify 768 * the length of the private key X. Alternatively, algorithm parameters 769 * may be derived from another source such as a Certificate Authority's 770 * certificate. 771 * OID = 1.2.840.113549.1.3.1 772 */ 773 DH_oid = ObjectIdentifier.newInternal(DH_data); 774 775 /** 776 * Algorithm ID for the Diffie Hellman Key Agreement (DH), from RFC 3279. 777 * Parameters may include values P and G. 778 * OID = 1.2.840.10046.2.1 779 */ 780 DH_PKIX_oid = ObjectIdentifier.newInternal(DH_PKIX_data); 781 782 /** 783 * Algorithm ID for the Digital Signing Algorithm (DSA), from the 784 * NIST OIW Stable Agreements part 12. 785 * Parameters may include values P, Q, and G; or these may be 786 * derived from 787 * another source such as a Certificate Authority's certificate. 788 * OID = 1.3.14.3.2.12 789 */ 790 DSA_OIW_oid = ObjectIdentifier.newInternal(DSA_OIW_data); 791 792 /** 793 * Algorithm ID for the Digital Signing Algorithm (DSA), from RFC 3279. 794 * Parameters may include values P, Q, and G; or these may be 795 * derived from another source such as a Certificate Authority's 796 * certificate. 797 * OID = 1.2.840.10040.4.1 798 */ 799 DSA_oid = ObjectIdentifier.newInternal(DSA_PKIX_data); 800 801 /** 802 * Algorithm ID for RSA keys used for any purpose, as defined in X.509. 803 * The algorithm parameter is a single value, the number of bits in the 804 * modulus. 805 * OID = 2.5.8.1.1 806 */ 807 RSA_oid = ObjectIdentifier.newInternal(RSA_data); 808 809 /** 810 * Algorithm ID for RSA keys used with RSA encryption, as defined 811 * in PKCS #1. There are no parameters associated with this algorithm. 812 * OID = 1.2.840.113549.1.1.1 813 */ 814 RSAEncryption_oid = ObjectIdentifier.newInternal(RSAEncryption_data); 815 816 /** 817 * Identifies a signing algorithm where an MD2 digest is encrypted 818 * using an RSA private key; defined in PKCS #1. Use of this 819 * signing algorithm is discouraged due to MD2 vulnerabilities. 820 * OID = 1.2.840.113549.1.1.2 821 */ 822 md2WithRSAEncryption_oid = 823 ObjectIdentifier.newInternal(md2WithRSAEncryption_data); 824 825 /** 826 * Identifies a signing algorithm where an MD5 digest is 827 * encrypted using an RSA private key; defined in PKCS #1. 828 * OID = 1.2.840.113549.1.1.4 829 */ 830 md5WithRSAEncryption_oid = 831 ObjectIdentifier.newInternal(md5WithRSAEncryption_data); 832 833 /** 834 * Identifies a signing algorithm where a SHA1 digest is 835 * encrypted using an RSA private key; defined by RSA DSI. 836 * OID = 1.2.840.113549.1.1.5 837 */ 838 sha1WithRSAEncryption_oid = 839 ObjectIdentifier.newInternal(sha1WithRSAEncryption_data); 840 841 /** 842 * Identifies a signing algorithm where a SHA1 digest is 843 * encrypted using an RSA private key; defined in NIST OIW. 844 * OID = 1.3.14.3.2.29 845 */ 846 sha1WithRSAEncryption_OIW_oid = 847 ObjectIdentifier.newInternal(sha1WithRSAEncryption_OIW_data); 848 849 /** 850 * Identifies a signing algorithm where a SHA224 digest is 851 * encrypted using an RSA private key; defined by PKCS #1. 852 * OID = 1.2.840.113549.1.1.14 853 */ 854 sha224WithRSAEncryption_oid = 855 ObjectIdentifier.newInternal(sha224WithRSAEncryption_data); 856 857 /** 858 * Identifies a signing algorithm where a SHA256 digest is 859 * encrypted using an RSA private key; defined by PKCS #1. 860 * OID = 1.2.840.113549.1.1.11 861 */ 862 sha256WithRSAEncryption_oid = 863 ObjectIdentifier.newInternal(sha256WithRSAEncryption_data); 864 865 /** 866 * Identifies a signing algorithm where a SHA384 digest is 867 * encrypted using an RSA private key; defined by PKCS #1. 868 * OID = 1.2.840.113549.1.1.12 869 */ 870 sha384WithRSAEncryption_oid = 871 ObjectIdentifier.newInternal(sha384WithRSAEncryption_data); 872 873 /** 874 * Identifies a signing algorithm where a SHA512 digest is 875 * encrypted using an RSA private key; defined by PKCS #1. 876 * OID = 1.2.840.113549.1.1.13 877 */ 878 sha512WithRSAEncryption_oid = 879 ObjectIdentifier.newInternal(sha512WithRSAEncryption_data); 880 881 /** 882 * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a 883 * SHA digest is signed using the Digital Signing Algorithm (DSA). 884 * This should not be used. 885 * OID = 1.3.14.3.2.13 886 */ 887 shaWithDSA_OIW_oid = ObjectIdentifier.newInternal(shaWithDSA_OIW_data); 888 889 /** 890 * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a 891 * SHA1 digest is signed using the Digital Signing Algorithm (DSA). 892 * OID = 1.3.14.3.2.27 893 */ 894 sha1WithDSA_OIW_oid = ObjectIdentifier.newInternal(sha1WithDSA_OIW_data); 895 896 /** 897 * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a 898 * SHA1 digest is signed using the Digital Signing Algorithm (DSA). 899 * OID = 1.2.840.10040.4.3 900 */ 901 sha1WithDSA_oid = ObjectIdentifier.newInternal(dsaWithSHA1_PKIX_data); 902 903 nameTable = new HashMap!(ObjectIdentifier,string)(); 904 nameTable.put(MD5_oid, "MD5"); 905 nameTable.put(MD2_oid, "MD2"); 906 nameTable.put(SHA_oid, "SHA-1"); 907 nameTable.put(SHA224_oid, "SHA-224"); 908 nameTable.put(SHA256_oid, "SHA-256"); 909 nameTable.put(SHA384_oid, "SHA-384"); 910 nameTable.put(SHA512_oid, "SHA-512"); 911 nameTable.put(RSAEncryption_oid, "RSA"); 912 nameTable.put(RSA_oid, "RSA"); 913 nameTable.put(DH_oid, "Diffie-Hellman"); 914 nameTable.put(DH_PKIX_oid, "Diffie-Hellman"); 915 nameTable.put(DSA_oid, "DSA"); 916 nameTable.put(DSA_OIW_oid, "DSA"); 917 nameTable.put(EC_oid, "EC"); 918 nameTable.put(ECDH_oid, "ECDH"); 919 920 nameTable.put(AES_oid, "AES"); 921 922 nameTable.put(sha1WithECDSA_oid, "SHA1withECDSA"); 923 nameTable.put(sha224WithECDSA_oid, "SHA224withECDSA"); 924 nameTable.put(sha256WithECDSA_oid, "SHA256withECDSA"); 925 nameTable.put(sha384WithECDSA_oid, "SHA384withECDSA"); 926 nameTable.put(sha512WithECDSA_oid, "SHA512withECDSA"); 927 nameTable.put(md5WithRSAEncryption_oid, "MD5withRSA"); 928 nameTable.put(md2WithRSAEncryption_oid, "MD2withRSA"); 929 nameTable.put(sha1WithDSA_oid, "SHA1withDSA"); 930 nameTable.put(sha1WithDSA_OIW_oid, "SHA1withDSA"); 931 nameTable.put(shaWithDSA_OIW_oid, "SHA1withDSA"); 932 nameTable.put(sha224WithDSA_oid, "SHA224withDSA"); 933 nameTable.put(sha256WithDSA_oid, "SHA256withDSA"); 934 nameTable.put(sha1WithRSAEncryption_oid, "SHA1withRSA"); 935 nameTable.put(sha1WithRSAEncryption_OIW_oid, "SHA1withRSA"); 936 nameTable.put(sha224WithRSAEncryption_oid, "SHA224withRSA"); 937 nameTable.put(sha256WithRSAEncryption_oid, "SHA256withRSA"); 938 nameTable.put(sha384WithRSAEncryption_oid, "SHA384withRSA"); 939 nameTable.put(sha512WithRSAEncryption_oid, "SHA512withRSA"); 940 nameTable.put(pbeWithMD5AndDES_oid, "PBEWithMD5AndDES"); 941 nameTable.put(pbeWithMD5AndRC2_oid, "PBEWithMD5AndRC2"); 942 nameTable.put(pbeWithSHA1AndDES_oid, "PBEWithSHA1AndDES"); 943 nameTable.put(pbeWithSHA1AndRC2_oid, "PBEWithSHA1AndRC2"); 944 nameTable.put(pbeWithSHA1AndDESede_oid, "PBEWithSHA1AndDESede"); 945 nameTable.put(pbeWithSHA1AndRC2_40_oid, "PBEWithSHA1AndRC2_40"); 946 } 947 948 /** 949 * Creates a signature algorithm name from a digest algorithm 950 * name and a encryption algorithm name. 951 */ 952 static string makeSigAlg(string digAlg, string encAlg) { 953 digAlg = digAlg.replace("-", ""); 954 if (encAlg.equalsIgnoreCase("EC")) encAlg = "ECDSA"; 955 956 return digAlg ~ "with" ~ encAlg; 957 } 958 959 /** 960 * Extracts the encryption algorithm name from a signature 961 * algorithm name. 962 */ 963 static string getEncAlgFromSigAlg(string signatureAlgorithm) { 964 signatureAlgorithm = signatureAlgorithm.toUpper(); 965 ptrdiff_t w = signatureAlgorithm.indexOf("WITH"); 966 string keyAlgorithm = null; 967 if (w > 0) { 968 ptrdiff_t and = signatureAlgorithm.indexOf("AND", w + 4); 969 if (and > 0) { 970 keyAlgorithm = signatureAlgorithm[w + 4 .. and]; 971 } else { 972 keyAlgorithm = signatureAlgorithm[w + 4 .. $]; 973 } 974 if (keyAlgorithm.equalsIgnoreCase("ECDSA")) { 975 keyAlgorithm = "EC"; 976 } 977 } 978 return keyAlgorithm; 979 } 980 981 /** 982 * Extracts the digest algorithm name from a signature 983 * algorithm name. 984 */ 985 static string getDigAlgFromSigAlg(string signatureAlgorithm) { 986 signatureAlgorithm = signatureAlgorithm.toUpper(); 987 ptrdiff_t w = signatureAlgorithm.indexOf("WITH"); 988 if (w > 0) { 989 return signatureAlgorithm[0 .. w]; 990 } 991 return null; 992 } 993 }