首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bouncycastle XmlSignatureFactory NoSuchAlgorithmException

Bouncycastle XmlSignatureFactory NoSuchAlgorithmException
EN

Stack Overflow用户
提问于 2012-07-30 14:50:22
回答 2查看 7K关注 0票数 2

我在使用BouncyCastle来验证使用ECDSA的签名时遇到了一个问题。

下面是相关的代码行:

代码语言:javascript
复制
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);   
//some unrelated code
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM", provider);

在最后一行,抛出以下异常:

代码语言:javascript
复制
javax.xml.crypto.NoSuchMechanismException: java.security.NoSuchAlgorithmException: no such algorithm: DOM for provider SC

如果我将行更改为

代码语言:javascript
复制
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");

我得到了

代码语言:javascript
复制
javax.xml.crypto.MarshalException: unsupported SignatureMethod algorithm: http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160

有没有人知道这是什么原因?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-30 15:22:30

在您的第一个错误中,您可以在错误描述中读到“没有这样的算法: DOM for provider SC”。这很奇怪,因为它显示的是"provider SC“(Sun /SC provider),而不是"provider BC”(BouncyCastle安全提供商)。看起来你的代码(内部)并没有像你想要的那样使用Bouncycastle。您应该找出为什么会发生这种情况。它可能是关于BC库和类路径(如果您使用的是应用服务器)或提供者顺序配置的内容。

第二个错误。您改变了获取XMLSignatureFactory的方法。这种方法更好,因为如果您不指定提供程序,因为:

JCA此方法使用标准

提供者查找机制来定位和实例化所需机制类型的XMLSignatureFactory实现。它遍历已注册的安全提供商列表,从最首选的提供商开始。返回来自支持指定机制的第一个提供程序的新XMLSignatureFactory对象。

但是现在,算法已经不存在了。那么为什么呢?在这里,我会说BC没有被使用。它在那里吗?检查您的类路径。

列出所有可用的提供商可能会有所帮助:

代码语言:javascript
复制
for (Provider p : Security.getProviders()) {

    log.debug(p.getName());
    log.debug(p.getInfo());
}
票数 3
EN

Stack Overflow用户

发布于 2018-09-01 00:55:17

从您的第二个异常可以看出,因为您想验证xml签名,所以您可能需要使用一些代码,如下面的代码,来自https://www.massapi.com/class/xm/XMLSignatureFactory-2.html的代码

代码语言:javascript
复制
// Step 1: Load an XMLSignatureFactory instance. This factory class will
// be responsible for constructing almost all the major objects we need
// in working with XML Signature in JSR-105 APIs, except those related
// to KeyInfo.
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

// Step 3 : Find all Xml Signature element into the provided XML
// document (here for sample use only the first)
NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) {
    throw new Exception("Cannot find Signature element!");
}

// Step 4: Create a DOMValidateContext instance (extract public key from
// the "KeyInfo" bloc using overrided KeySelector impl.)
DOMValidateContext valContext = new DOMValidateContext(new KeyValueKeySelector(), nl.item(0));

// Step 5: Unmarshal the Signature node into an XMLSiganture object.
XMLSignature signature = fac.unmarshalXMLSignature(valContext);

// Step 6 : Validate signature
boolean isValid = signature.validate(valContext);
if (isValid) {
    System.out.println("OK");
}

但是xml表示如下所示:

代码语言:javascript
复制
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>  
            <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>  
            <SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160"/>  
            <Reference URI="">  
                <Transforms>  
                        <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>  
                </Transforms>  
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>  
                <DigestValue>bHS+6uf8KbJV4AGzoHNHLfnXvKM=</DigestValue>  
            </Reference>  
    </SignedInfo>
    ...
</Signature>

因此,工厂无法将xml表示解组为XMLSignature对象。实际上fac是由org.jcp.xml.dsig.internal.dom.XMLDSigRI提供商提供的,请确认查看$JRE_HOME/lib/security/java.securityfacDOMXMLSignatureFactory类的一个实例。解组操作将尝试形成Signature对象,并且必须首先形成子对象,如CanonicalizationMethod,然后是SignatureMethod,因此最终到达DOMSignedInfo构造函数DOMSignedInfo(Element var1, XMLCryptoContext var2, Provider var3) throws MarshalException处引发异常的调用

代码语言:javascript
复制
Element var5 = DOMUtils.getNextSiblingElement(var4, "SignatureMethod");
this.signatureMethod = DOMSignatureMethod.unmarshal(var5);

这是DOMSignatureMethod.unmarshal静态方法的又一步,它使用http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160查找数字签名算法,但DOMSignatureMethod只支持以下算法,

代码语言:javascript
复制
rsa-sha1
rsa-sha256
rsa-sha384
rsa-sha512
dsa-sha1
dsa-sha256
hmac-sha1
hmac-sha256
hmac-sha384
hmac-sha512
ecdsa-sha1
ecdsa-sha256
ecdsa-sha384
ecdsa-sha512

解决方案:将BC provider添加到安全性中,并使用org.apache.santuario -xmlsec项目中的XMLSignature进行验证,

代码语言:javascript
复制
public boolean verify(String signedXML) throws Exception {
    Document doc = null;
    try (InputStream is = new ByteArrayInputStream(signedXML.getBytes(Charset.forName("utf-8")))) {
        doc = MyXMLUtils.read(is, false);
    }

    XPathFactory xpf = XPathFactory.newInstance();
    XPath xpath = xpf.newXPath();
    xpath.setNamespaceContext(new DSNamespaceContext());

    String expression = "//ds:Signature[1]";
    Element sigElement =
            (Element) xpath.evaluate(expression, doc, XPathConstants.NODE);

    XMLSignature signature = new XMLSignature(sigElement, "");
    KeyInfo ki = signature.getKeyInfo();

    if (ki == null) {
        throw new RuntimeException("No keyinfo");
    }
    PublicKey pk = signature.getKeyInfo().getPublicKey();

    if (pk == null) {
        throw new RuntimeException("No public key");
    }

    return signature.checkSignatureValue(pk);
}

来自repo的更多演示:https://github.com/Honwhy/xml-sec

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11716579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档