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