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