java - 如何防止在java xml签名和证书中添加空格?

标签 java xml certificate ssl-certificate digital-signature

我正在签署 xml 文档的一部分,但生成的签名和证书中包含不需要的空格。例如,这是签名:

    <SignatureValue>QcjPfiZcmqE8aMNH5AKVk+oFBYQ4LynV3a5YlJIxuf0y22QQ0NA2BTkRriI85dd/6Qcezf5xFguJ&#13;
V+Mlk44c0uZD7TE+NlsFz3q1vtHHPi/9ygc2kJgQeSzxiCR2AHCONN3UN89RjidIqnN1qtKrBhc+&#13;
GNeEGhjqgV7DHvzK7tHVkC6c1EevsOV5bH2Gu0X5JsGwOtSHWe6eyOXue0TW7XWrqOLmOusWYhRR&#13;
ONJFoa49LQ4WV/RP498rp2TJ0bNE36PMWD6sMh52ERTj6NhngIl2cGjbbwzYteDN/ujo5bHmosmC&#13;
dVKBmgaw2YAICJy4BROyK7AmZI5BxKoZ6CY1Tw==</SignatureValue>

这是证书的一部分:

    <X509Certificate>MIIFtTCCBJ2gAwIBAgIQBsK927DS8wePBQjvzVX9BjANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQG&#13;
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMR0w&#13;
GwYDVQQDExRSYXBpZFNTTCBSU0EgQ0EgMjAxODAeFw0xOTA2MDcwMDAwMDBaFw0yMDA2MDYxMjAw&#13;

注意两者都有“$#13;”附加?

这是执行签名的代码:

    private void buildSignatureBlock5(String privateKeyPath, String publicKeyPath) {
    // Create a DOM XMLSignatureFactory that will be used to
    // generate the enveloped signature.
    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

    // Create a Reference to the enveloped document (in this case,
    // you are signing just the element with Id="Body", so a URI of "#Body" signifies
    // that, and also specify the SHA1 digest algorithm and the ENVELOPED Transform.
    Reference ref = null;
    try {
        ref = fac.newReference
         ("#Body", fac.newDigestMethod(DigestMethod.SHA1, null),
          Collections.singletonList
           (fac.newTransform
            (Transform.ENVELOPED, (TransformParameterSpec) null)),
             null, null);
    } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // Create the SignedInfo.
    SignedInfo si = null;
    try {
        si = fac.newSignedInfo
         (fac.newCanonicalizationMethod
          (CanonicalizationMethod.INCLUSIVE,
           (C14NMethodParameterSpec) null),
            fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
             Collections.singletonList(ref));
    } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       

    // Load the KeyStore and get the signing key and certificate.
    KeyStore ks = null;
    try {
        ks = KeyStore.getInstance("JKS");
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        ks.load(new FileInputStream(storage_path +"/keys/myproject.jks"), "changeit".toCharArray());
    } catch (NoSuchAlgorithmException | CertificateException | IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    KeyStore.PrivateKeyEntry keyEntry = null;
    try {
        keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry
            ("1", new KeyStore.PasswordProtection("changeit".toCharArray()));
    } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    X509Certificate cert = (X509Certificate) keyEntry.getCertificate();

    // Create the KeyInfo containing the X509Data.
    KeyInfoFactory kif = fac.getKeyInfoFactory();
    List x509Content = new ArrayList();
    String issuerName = cert.getIssuerX500Principal().getName();
    BigInteger serialNumber = cert.getSerialNumber();
    X509IssuerSerial issuer = kif.newX509IssuerSerial(issuerName, serialNumber);
    x509Content.add(issuer);
    x509Content.add(cert);
    X509Data xd = kif.newX509Data(x509Content);
    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));    

    // Create a DOMSignContext and specify the RSA PrivateKey and location of the resulting XMLSignature's parent element.
    Element envHeaderSig = (Element) document.getElementsByTagName("SOAP-SEC:Signature").item(0);
    DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), envHeaderSig);

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

    try {
        signature.sign(dsc);    //ResourceResolverException: Cannot resolve element with ID Body
    } catch (MarshalException | XMLSignatureException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

我已经尝试过这里建议的解决方案:

How to produce XML signature with no whitespaces and line-breaks in Java?

但是没有任何效果。有任何想法吗?

我有一个由 PHP 创建的示例签名 block ,我知道它可以工作,但没有空格。我试图让我的 java 输出看起来就像它一样。

最佳答案

我找不到一种“正确的方式”来做到这一点,因此编写了一个 hack 来在生成后对其进行修改。这是:

//hack to remove unwanted CR at the end of each line in SignatureValue and X509Certificate
private void removeWhitespaceFromSignature() {
    Element sig = (Element) document.getElementsByTagName("SignatureValue").item(0);
    String sigValue = sig.getTextContent().replaceAll("\r\n", "");
    sig.setTextContent(sigValue);

    Element cert = (Element) document.getElementsByTagName("X509Certificate").item(0);
    String certValue = cert.getTextContent().replaceAll("\r\n", "");
    cert.setTextContent(certValue);
}

不得不诉诸于此似乎很荒谬,但几个小时的搜索没有产生其他替代方案。

关于java - 如何防止在java xml签名和证书中添加空格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59218272/

相关文章:

java - 是否有为 Delphi (Win32) DLL 创建 C 头文件的工具?

c# - 使用什么序列化程序(到 xml)进行循环引用和自定义字段?

iphone - 定期吊销证书的任何问题

ssl - 邮件服务器的 SSL 证书无效

certificate - 更新证书时公共(public)指纹会改变吗?

java - 使用 Selenium WebDriver 和 FF24 上传文件

java - Maven 配置

java - 在java中格式化2位小数

java - 在 SQLite 中存储数组列表的数组列表

xml - 分析大量 XML 的程序