如何在Java中获取哈希算法名称的对象标识符

如何在Java中获取哈希算法名称的对象标识符,java,cryptography,bouncycastle,Java,Cryptography,Bouncycastle,我必须在加密算法名称和它们的对象标识符(OID)之间执行转换。我使用Java加密体系结构(JCA)和BouncyCastle作为安全提供者。使用JCA本身,将OID转换为文本名称相当容易 String oid = "2.16.840.1.101.3.4.2.4"; MessageDigest md = MessageDigest.getInstance(oid); String digestAlgorithmName = md.getAlgorithm(); 但是如何执行从文本名称到OID的向

我必须在加密算法名称和它们的对象标识符(OID)之间执行转换。我使用Java加密体系结构(JCA)和BouncyCastle作为安全提供者。使用JCA本身,将OID转换为文本名称相当容易

String oid = "2.16.840.1.101.3.4.2.4";
MessageDigest md = MessageDigest.getInstance(oid);
String digestAlgorithmName = md.getAlgorithm();

但是如何执行从文本名称到OID的向后转换呢?在JCA中,似乎没有办法获得算法名的别名。Bouncy Castle 1.50有地图,可以将算法名称连接到OID,但所有这些地图的访问都受到限制。

使用Bouncy Castle的
CMSSignedHelper
。看


(我不打算重复这个答案,因为它位于Stack Overflow的站点上)。

这就是如何从提供所需算法的JCA服务的文本描述中提取OID的方法。然而,解决方案是相当不雅观的

DERObjectIdentifier oid = null;
String digestAlgorithmName = "SHA-224";
Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
Service service = provider.getService("MessageDigest", digestAlgorithmName);
if (service != null) {
    String string = service.toString();
    String array[] = string.split("\n");
    if (array.length > 1) {
        string = array[array.length - 1];
        array = string.split("[\\[\\]]");
        if (array.length > 2) {
            string = array[array.length - 2];
            array = string.split(", ");
            Arrays.sort(array);
            oid = new ASN1ObjectIdentifier(array[0]);
        }
    }
}

PKIX发行版中有几个助手类专门用于处理此问题


查看org.bouncycastle.operator-DefaultDigestAlgorithmIdentifierFinder和DefaultSignatureAlgorithmIdentifierFinder。在本发行版的其余部分,还有一些其他文件在不同的地方。

CMSSignedHelper类是包私有的,因此只能从org.bouncycastle.cms包访问。BouncyCastle JAR已签名,因此无法将新类添加到org.BouncyCastle.cms包中。感谢divanov。所以我很清楚:David Reis使用
getEncryptionAlgName
getDigestAlgName
的答案对您没有帮助?(即使是一个
BiMap
也帮不了你吗?)。提交类似
http://oid-info.com/get/2.999
,并解析
元素。但你必须在线才能做到这一点。(这似乎比从
CMSSignedHelper
创建
BiMap
更糟糕,但它可能对您有效,因为您似乎被困在岩石和坚硬的地方之间)。顺便说一下,您还可以从他的ASN.1解析器中获得Peter Gutmann的数据库。它不是一个安全提供商,而且它相当全面。请参见位于的
dumpasn1.cfg
。如果您将当前答案替换为这些想法会怎么样?OID应该将OID映射到一个特定的算法。这是一个ID,所以这可能是你所期望的。不幸的是,OID可以由任何公认的组织创建。其中一些算法由多方建立,导致多个OID指向同一个算法。就我个人而言,如果只是为了避免多个答案,我会对OID进行硬编码。@owlstead:至少对于散列、签名和密钥工厂,情况并非如此。否则,安全算法根本无法工作。但另一方面,这些信息已经在安全提供程序中编码并可供JCA使用。这只是为了找到一种访问它的方法。基本上,你认为如果有别名,安全算法就不起作用,这显然是胡扯。不过,大多数协议确实直接定义了需要哪些OID,而且大多数协议是由一个组织定义的。但要求1:1的关系似乎很奇怪。以Java编码为例<代码>“UTF-8”、
“UTF8”
“UTF8”
都指向相同的编码。编码不起作用吗?加密算法也是如此。@owlstead:我理解你最初的评论,因为OID不是唯一的。算法文本名称是别名,已在JCA的安全提供程序清单中定义。正如您正确指出的,每个OID都有多个OID,因此在我的代码中对它们进行硬编码将导致需要维护我的列表和安全提供者列表之间的匹配。这就是为什么我想把它委托给JCA或安全提供商。是的,它做我真正需要的事情。此方法在BouncyCastle 1.47中可用。在1.52中,您将使用
DefaultAlgorithmNameFinder
DefaultxxAlgorithmIdentifierFinder