7

我正在尝试使用封装签名和 javax.xml.crypto.dsig.* 类对 xml 文件进行签名。结果,我得到了具有正确签名内容但没有定义命名空间的文件。如何添加 xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 命名空间和相应的 ds 前缀?我没有看到任何可以定义它的地方。

示例代码:

    XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");

    (...)

    XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);

    // Marshal, generate, and sign the enveloped signature.
    signature.sign(domSignContext);

给出示例 XML:

<?xml version="1.0" encoding="UTF-8"?>
<test xmlns="http://different.namespace.com">
    <someBody/>
    <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/2000/09/xmldsig#rsa-sha1"/>     
            <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>base64_digest</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>some_base64</SignatureValue>
        <KeyInfo>
            <X509Data> 
                <X509SubjectName>subject_data</X509SubjectName>
                <X509Certificate>some_more_base64</X509Certificate>
            </X509Data>
            <KeyValue>
                <RSAKeyValue>
                    <Modulus>another_base64</Modulus>
                    <Exponent>base64_as_well</Exponent>
                </RSAKeyValue>
            </KeyValue>
        </KeyInfo>
   </Signature>
</test>

但我想要:

<?xml version="1.0" encoding="UTF-8"?>
<test xmlns="http://different.namespace.com" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <someBody/>
    <ds:Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>     
            <ds:Reference URI="">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <ds:DigestValue>base64_digest</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>some_base64</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data> 
                <ds:X509SubjectName>subject_data</ds:X509SubjectName>
                <ds:X509Certificate>some_more_base64</ds:X509Certificate>
            </ds:X509Data>
            <ds:KeyValue>
                <ds:RSAKeyValue>
                    <ds:Modulus>another_base64</ds:Modulus>
                    <ds:Exponent>base64_as_well</ds:Exponent>
                </ds:RSAKeyValue>
            </ds:KeyValue>
        </ds:KeyInfo>
   </ds:Signature>
</test>
4

3 回答 3

6

下面是来自 Oracle 的用于生成封装签名的示例代码。我猜你要找的是 dsc.setDefaultNamespacePrefix("dsig") ; 如下例所示。

    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

    Reference ref = fac.newReference
    ("", fac.newDigestMethod(DigestMethod.SHA1, null),
            Collections.singletonList
            (fac.newTransform
                    (Transform.ENVELOPED, (TransformParameterSpec) null)),
                    null, null);

    // Create the SignedInfo
    SignedInfo si = fac.newSignedInfo
    (fac.newCanonicalizationMethod
            (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
                    (C14NMethodParameterSpec) null),
                    fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null),
                    Collections.singletonList(ref));

    // Create a DSA KeyPair
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
    kpg.initialize(512);
    KeyPair kp = kpg.generateKeyPair();

    // Create a KeyValue containing the DSA PublicKey that was generated
    KeyInfoFactory kif = fac.getKeyInfoFactory();
    KeyValue kv = kif.newKeyValue(kp.getPublic());

    // Create a KeyInfo and add the KeyValue to it
    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));

    // Instantiate the document to be signed
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    Document doc =  dbf.newDocumentBuilder().parse(new FileInputStream(sourceFile));

    // Create a DOMSignContext and specify the DSA PrivateKey and
    // location of the resulting XMLSignature's parent element
    DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), doc.getDocumentElement());
    dsc.setDefaultNamespacePrefix("dsig");

    // Create the XMLSignature (but don't sign it yet)
    XMLSignature signature = fac.newXMLSignature(si, ki);

    // Marshal, generate (and sign) the enveloped signature
    signature.sign(dsc);

    // output the resulting document
    OutputStream os;
    os = new FileOutputStream(DestinationFile);

    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer trans = tf.newTransformer();
    trans.transform(new DOMSource(doc), new StreamResult(os));
于 2013-09-19T11:09:05.040 回答
-1

字符串算法 = XMLSignature.ALGO_ID_SIGNATURE_RSA; XMLSignature sig = new XMLSignature(doc, algoritmo);

于 2015-02-13T22:44:47.133 回答
-2

如果您希望您的签名 XML 采用以下格式

<ds:Signature ...> ... </ds:Signature>

然后请使用 java 6 版本 31,您将获得所需的签名 XML。

于 2017-05-09T12:41:32.963 回答