/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Vladimir N. Molotkov * @version $Revision$ */ /* * Imported by CG 20090319 based on Apache Harmony ("enhanced") revision 587517. */ package org.apache.harmony.security.utils; import java.security.Provider; import java.security.Security; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.harmony.security.Util; import org.apache.harmony.security.asn1.ObjectIdentifier; /** * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known * mappings are hardcoded. Tries to obtain additional mappings from installed * providers during initialization. */ public class AlgNameMapper { // Will search OID mappings for these services private static final String[] serviceName = { "Cipher", //$NON-NLS-1$ "AlgorithmParameters", //$NON-NLS-1$ "Signature" //$NON-NLS-1$ }; // These mappings CAN NOT be overridden // by the ones from available providers // during maps initialization // (source: http://asn1.elibel.tm.fr): private static final String[][] knownAlgMappings = { {"1.2.840.10040.4.1", "DSA"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.10040.4.3", "SHA1withDSA"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.1.1", "RSA"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.1.2", "MD2withRSA"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.1.4", "MD5withRSA"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.1.5", "SHA1withRSA"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.3.1", "DiffieHellman"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.5.3", "pbeWithMD5AndDES-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.12.1.3", "pbeWithSHAAnd3-KeyTripleDES-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.1.12.1.6", "pbeWithSHAAnd40BitRC2-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.2", "RC2-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.3", "RC2-EBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.4", "RC4"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.5", "RC4WithMAC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.6", "DESx-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.7", "TripleDES-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.8", "rc5CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.9", "RC5-CBC"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.2.840.113549.3.10", "DESCDMF"}, //$NON-NLS-1$ //$NON-NLS-2$ {"1.3.14.3.2.26", "SHA1"}, //$NON-NLS-1$ //$NON-NLS-2$ {"2.23.42.9.11.4.1", "ECDSA"}, //$NON-NLS-1$ //$NON-NLS-2$ }; // Maps alg name to OID private static final Map alg2OidMap = new HashMap(); // Maps OID to alg name private static final Map oid2AlgMap = new HashMap(); // Maps aliases to alg names private static final Map algAliasesMap = new HashMap(); static { for (int i = 0; i < knownAlgMappings.length; ++i) { String[] element = knownAlgMappings[i]; String algUC = Util.toUpperCase(element[1]); alg2OidMap.put(algUC, element[0]); oid2AlgMap.put(element[0], algUC); // map upper case alg name to its original name algAliasesMap.put(algUC, element[1]); } // // Now search providers for mappings like // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name> // or // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name> // Provider[] pl = Security.getProviders(); for (int j = 0; j < pl.length; ++j) { selectEntries(pl[j]); } } // No instances private AlgNameMapper() { } /** * Returns OID for algName * * @param algName algorithm name to be mapped * @return OID as String */ public static String map2OID(String algName) { // alg2OidMap map contains upper case keys return (String) alg2OidMap.get(Util.toUpperCase(algName)); } /** * Returns algName for OID * * @param oid OID to be mapped * @return algorithm name */ public static String map2AlgName(String oid) { // oid2AlgMap map contains upper case values String algUC = (String) oid2AlgMap.get(oid); // if not null there is always map UC->Orig return algUC == null ? null : (String) algAliasesMap.get(algUC); } /** * Returns Algorithm name for given algorithm alias * * @param algName - alias * @return algorithm name */ public static String getStandardName(String algName) { return (String) algAliasesMap.get(Util.toUpperCase(algName)); } // Searches given provider for mappings like // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name> // or // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name> // Puts mappings found into appropriate internal maps private static void selectEntries(Provider p) { Set entrySet = p.entrySet(); for (int i = 0; i < serviceName.length; ++i) { String service = serviceName[i]; String keyPrfix2find = "Alg.Alias." + service + "."; //$NON-NLS-1$ //$NON-NLS-2$ Iterator iter = entrySet.iterator(); while (iter.hasNext()) { Entry me = (Entry) iter.next(); String key = (String)me.getKey(); if (key.startsWith(keyPrfix2find)) { String alias = key.substring(keyPrfix2find.length()); String alg = (String)me.getValue(); String algUC = Util.toUpperCase(alg); if (isOID(alias)) { if (alias.startsWith("OID.")) { //$NON-NLS-1$ alias = alias.substring(4); } // Do not overwrite already known mappings boolean oid2AlgContains = oid2AlgMap.containsKey(alias); boolean alg2OidContains = alg2OidMap.containsKey(algUC); if (!oid2AlgContains || !alg2OidContains) { if (!oid2AlgContains) { oid2AlgMap.put(alias, algUC); } if (!alg2OidContains) { alg2OidMap.put(algUC, alias); } // map upper case alg name to its original name algAliasesMap.put(algUC, alg); } // Do not override known standard names } else if (!algAliasesMap.containsKey(Util.toUpperCase(alias))) { algAliasesMap.put(Util.toUpperCase(alias), alg); } } } } } /** * Checks if parameter represents OID * * @param alias alias to be checked * @return 'true' if parameter represents OID */ public static boolean isOID(String alias) { try { // The method makes all needed checks in it. // If alias is not an OID, exception is thrown. ObjectIdentifier.toIntArray(normalize(alias)); // will not come here if exception is thrown return true; } catch (IllegalArgumentException e) { return false; } } /** * Removes leading "OID." from oid String passed * * @param oid string that may contain leading "OID." * @return string passed without leading "OID." */ public static String normalize(String oid) { return oid.startsWith("OID.") //$NON-NLS-1$ ? oid.substring(4) : oid; } /** * Present all internal maps as formatted string * @return Internal maps String representation */ public static String dump() { StringBuffer sb = new StringBuffer("alg2OidMap: "); //$NON-NLS-1$ sb.append(alg2OidMap); sb.append("\noid2AlgMap: "); //$NON-NLS-1$ sb.append(oid2AlgMap); sb.append("\nalgAliasesMap: "); //$NON-NLS-1$ sb.append(algAliasesMap); return sb.toString(); } }