001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Vladimir N. Molotkov
020: * @version $Revision$
021: */package org.apache.harmony.security.utils;
022:
023: import java.security.Provider;
024: import java.security.Security;
025: import java.util.HashMap;
026: import java.util.Map;
027: import java.util.Set;
028: import java.util.Map.Entry;
029:
030: import org.apache.harmony.security.Util;
031: import org.apache.harmony.security.asn1.ObjectIdentifier;
032:
033: /**
034: * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
035: * mappings are hardcoded. Tries to obtain additional mappings from installed
036: * providers during initialization.
037: */
038: public class AlgNameMapper {
039:
040: // Will search OID mappings for these services
041: private static final String[] serviceName = { "Cipher", //$NON-NLS-1$
042: "AlgorithmParameters", //$NON-NLS-1$
043: "Signature" //$NON-NLS-1$
044: };
045:
046: // These mappings CAN NOT be overridden
047: // by the ones from available providers
048: // during maps initialization
049: // (source: http://asn1.elibel.tm.fr):
050: private static final String[][] knownAlgMappings = {
051: { "1.2.840.10040.4.1", "DSA" }, //$NON-NLS-1$ //$NON-NLS-2$
052: { "1.2.840.10040.4.3", "SHA1withDSA" }, //$NON-NLS-1$ //$NON-NLS-2$
053: { "1.2.840.113549.1.1.1", "RSA" }, //$NON-NLS-1$ //$NON-NLS-2$
054: { "1.2.840.113549.1.1.2", "MD2withRSA" }, //$NON-NLS-1$ //$NON-NLS-2$
055: { "1.2.840.113549.1.1.4", "MD5withRSA" }, //$NON-NLS-1$ //$NON-NLS-2$
056: { "1.2.840.113549.1.1.5", "SHA1withRSA" }, //$NON-NLS-1$ //$NON-NLS-2$
057: { "1.2.840.113549.1.3.1", "DiffieHellman" }, //$NON-NLS-1$ //$NON-NLS-2$
058: { "1.2.840.113549.1.5.3", "pbeWithMD5AndDES-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
059: {
060: "1.2.840.113549.1.12.1.3", "pbeWithSHAAnd3-KeyTripleDES-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
061: { "1.2.840.113549.1.12.1.6", "pbeWithSHAAnd40BitRC2-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
062: { "1.2.840.113549.3.2", "RC2-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
063: { "1.2.840.113549.3.3", "RC2-EBC" }, //$NON-NLS-1$ //$NON-NLS-2$
064: { "1.2.840.113549.3.4", "RC4" }, //$NON-NLS-1$ //$NON-NLS-2$
065: { "1.2.840.113549.3.5", "RC4WithMAC" }, //$NON-NLS-1$ //$NON-NLS-2$
066: { "1.2.840.113549.3.6", "DESx-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
067: { "1.2.840.113549.3.7", "TripleDES-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
068: { "1.2.840.113549.3.8", "rc5CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
069: { "1.2.840.113549.3.9", "RC5-CBC" }, //$NON-NLS-1$ //$NON-NLS-2$
070: { "1.2.840.113549.3.10", "DESCDMF" }, //$NON-NLS-1$ //$NON-NLS-2$
071: { "2.23.42.9.11.4.1", "ECDSA" }, //$NON-NLS-1$ //$NON-NLS-2$
072: };
073: // Maps alg name to OID
074: private static final Map<String, String> alg2OidMap = new HashMap<String, String>();
075: // Maps OID to alg name
076: private static final Map<String, String> oid2AlgMap = new HashMap<String, String>();
077: // Maps aliases to alg names
078: private static final Map<String, String> algAliasesMap = new HashMap<String, String>();
079:
080: static {
081: for (String[] element : knownAlgMappings) {
082: String algUC = Util.toUpperCase(element[1]);
083: alg2OidMap.put(algUC, element[0]);
084: oid2AlgMap.put(element[0], algUC);
085: // map upper case alg name to its original name
086: algAliasesMap.put(algUC, element[1]);
087: }
088: //
089: // Now search providers for mappings like
090: // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
091: // or
092: // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
093: //
094: Provider[] pl = Security.getProviders();
095: for (Provider element : pl) {
096: selectEntries(element);
097: }
098: }
099:
100: // No instances
101: private AlgNameMapper() {
102: }
103:
104: /**
105: * Returns OID for algName
106: *
107: * @param algName algorithm name to be mapped
108: * @return OID as String
109: */
110: public static String map2OID(String algName) {
111: // alg2OidMap map contains upper case keys
112: return alg2OidMap.get(Util.toUpperCase(algName));
113: }
114:
115: /**
116: * Returns algName for OID
117: *
118: * @param oid OID to be mapped
119: * @return algorithm name
120: */
121: public static String map2AlgName(String oid) {
122: // oid2AlgMap map contains upper case values
123: String algUC = oid2AlgMap.get(oid);
124: // if not null there is always map UC->Orig
125: return algUC == null ? null : algAliasesMap.get(algUC);
126: }
127:
128: /**
129: * Returns Algorithm name for given algorithm alias
130: *
131: * @param algName - alias
132: * @return algorithm name
133: */
134: public static String getStandardName(String algName) {
135: return algAliasesMap.get(Util.toUpperCase(algName));
136: }
137:
138: // Searches given provider for mappings like
139: // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
140: // or
141: // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
142: // Puts mappings found into appropriate internal maps
143: private static void selectEntries(Provider p) {
144: Set<Map.Entry<Object, Object>> entrySet = p.entrySet();
145: for (String service : serviceName) {
146: String keyPrfix2find = "Alg.Alias." + service + "."; //$NON-NLS-1$ //$NON-NLS-2$
147: for (Entry<Object, Object> me : entrySet) {
148: String key = (String) me.getKey();
149: if (key.startsWith(keyPrfix2find)) {
150: String alias = key
151: .substring(keyPrfix2find.length());
152: String alg = (String) me.getValue();
153: String algUC = Util.toUpperCase(alg);
154: if (isOID(alias)) {
155: if (alias.startsWith("OID.")) { //$NON-NLS-1$
156: alias = alias.substring(4);
157: }
158: // Do not overwrite already known mappings
159: boolean oid2AlgContains = oid2AlgMap
160: .containsKey(alias);
161: boolean alg2OidContains = alg2OidMap
162: .containsKey(algUC);
163: if (!oid2AlgContains || !alg2OidContains) {
164: if (!oid2AlgContains) {
165: oid2AlgMap.put(alias, algUC);
166: }
167: if (!alg2OidContains) {
168: alg2OidMap.put(algUC, alias);
169: }
170: // map upper case alg name to its original name
171: algAliasesMap.put(algUC, alg);
172: }
173: // Do not override known standard names
174: } else if (!algAliasesMap.containsKey(Util
175: .toUpperCase(alias))) {
176: algAliasesMap.put(Util.toUpperCase(alias), alg);
177: }
178: }
179: }
180: }
181: }
182:
183: /**
184: * Checks if parameter represents OID
185: *
186: * @param alias alias to be checked
187: * @return 'true' if parameter represents OID
188: */
189: public static boolean isOID(String alias) {
190: try {
191: // The method makes all needed checks in it.
192: // If alias is not an OID, exception is thrown.
193: ObjectIdentifier.toIntArray(normalize(alias));
194:
195: // will not come here if exception is thrown
196: return true;
197: } catch (IllegalArgumentException e) {
198: return false;
199: }
200: }
201:
202: /**
203: * Removes leading "OID." from oid String passed
204: *
205: * @param oid string that may contain leading "OID."
206: * @return string passed without leading "OID."
207: */
208: public static String normalize(String oid) {
209: return oid.startsWith("OID.") //$NON-NLS-1$
210: ? oid.substring(4)
211: : oid;
212: }
213:
214: /**
215: * Present all internal maps as formatted string
216: * @return Internal maps String representation
217: */
218: public static String dump() {
219: StringBuffer sb = new StringBuffer("alg2OidMap: "); //$NON-NLS-1$
220: sb.append(alg2OidMap);
221: sb.append("\noid2AlgMap: "); //$NON-NLS-1$
222: sb.append(oid2AlgMap);
223: sb.append("\nalgAliasesMap: "); //$NON-NLS-1$
224: sb.append(algAliasesMap);
225: return sb.toString();
226: }
227: }
|