如何从使用javax.xml.crypto API签名的XML中删除换行符和空格

时间:2016-05-11 16:10:34

标签: java xml signature xml-signature

我正在使用墨西哥“factura Electronica”,我需要使用cert.cer和key.key文件签署XML文档,

但要求是标签之间绝对没有空格和换行符,包括签名标签()。

如果我在签名后删除换行符和空格,签名就会被破坏, 我也无法更改规范化器/变换器组,因为它们是预定义的。

*我正在使用javax.xml.crypto API签署XML文档

以下是代码:

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

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

    SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
            (C14NMethodParameterSpec) null),
            fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
            Collections.singletonList(ref));


    X509Certificate cert = KeyLoaderFactory.createInstance(KeyLoaderEnumeration.PUBLIC_KEY_LOADER, new FileInputStream("C:\\Users\\Arturo\\Desktop\\PEMS\\Certificado\\0000166600201052508s.cer")).getKey();

    KeyInfoFactory kif = fac.getKeyInfoFactory();
    List x509Content = new ArrayList();

    X509IssuerSerial issuer = kif.newX509IssuerSerial(cert.getIssuerDN().getName(), cert.getSerialNumber());
    x509Content.add(issuer);
    x509Content.add(cert);
    X509Data xd = kif.newX509Data(x509Content);
    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("C:\\Users\\Arturo\\Documents\\NetBeansProjects\\AdminFraccionamientoWeb1\\web\\assets\\Pdfs\\Cancel_" + UUID + ".xml"));

    PrivateKey privateKey = KeyLoaderFactory.createInstance(KeyLoaderEnumeration.PRIVATE_KEY_LOADER, new FileInputStream("C:\\Users\\Arturo\\Desktop\\PEMS\\Certificado\\DST1010185B7_1205106666S.key"), "Suport").getKey();

    DOMSignContext dsc = new DOMSignContext(privateKey, doc.getDocumentElement());

    XMLSignature signature = fac.newXMLSignature(si, ki);

    signature.sign(dsc);
    String Ruta = "C:\\Users\\Arturo\\Documents\\NetBeansProjects\\AdminFraccionamientoWeb1\\web\\assets\\Pdfs\\Cancel_signed" + UUID + ".xml";

    OutputStream os = new FileOutputStream(Ruta);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer trans = tf.newTransformer();
    trans.transform(new DOMSource(doc), new StreamResult(os));

以下是生成的签名

<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"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> </Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>DiLnrOczxtHVnhG4EA9zj0JM8O0=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>PrHxWCpnZlFi92ETs0JMnVML/FoUxQkktRT5UpU9W90DhKZFX31nFjwEtt3GBluz+xEdt+j4lmnd
JHdZbEynVwqsm5ZF2Y/Z34fn/f050pUXyjitlog8QWoKB+oCbaNW1L3+9VHyuKQ4t/1XbNt6RCgM
RkDEm4hDc6V55G/szIQ=
</SignatureValue>
<KeyInfo>
<X509Data>
<X509IssuerSerial>   
<X509IssuerName>OID.1.2.840.113549.1.9.2=Responsable: Cecilia Guillermina García   Guerra, OID.2.5.4.45=SAT970701NN3, L=Cuauhtémoc, ST=Distrito Federal, C=MX,   OID.2.5.4.17=06300, STREET="Av. Hidalgo 77, Col. Guerrero",   EMAILADDRESS=asisnet@sat.gob.mx, OU=Administración de Seguridad de la   Información, O=Servicio de Administración Tributaria, CN=A.C. del Servicio de   Administración Tributaria
</X509IssuerName>   
<X509SerialNumber>275106190557734483187066766774039086286478061624
</X509SerialNumber>
</X509IssuerSerial>  
<X509Certificate>
MIIErTCCA5WgAwIBAgIUMDAwMDEwMDAwMDAyMDEwNTI1MDgwDQYJKoZIhvcNAQEFBQAwggGVMTgw
NgYDVQQDDC9BLkMuIGRlbCBTZXJ2aWNpbyBkZSBBZG1pbmlzdHJhY2nDs24gVHJpYnV0YXJpYTEv
MC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsM
L0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMSEwHwYJKoZI
hvcNAQkBFhJhc2lzbmV0QHNhdC5nb2IubXgxJjAkBgNVBAkMHUF2LiBIaWRhbGdvIDc3LCBDb2wu
IEd1ZXJyZXJvMQ4wDAYREVMRDAUwNjMwMDELMAkGA1UEBhMCTVgxGTAXBgNVBAgMEERpc3RyaXRv
IEZlZGVyYWwxFDASBgNVBAcMC0N1YXVodMOpbW9jMRUwEwYDVQQtEwxTYYQ5NzA3MDFOTjMxPjA8
BgkqhkiG9w0BCQIML1Jlc3BvbnNhYmxlOiBDZWNpbGlhIEd1aWxsZXJtaW5hIEdhcmPDrWEgR3Vl
cnJhMB4XDTEyMDUxMTAzMzYyNloXDTE2MDUxMTAzMzYyNlowge4xMDAuBgNVBAMTJ0RFU0FSUk9M
TE9TIFkgU09MVUNJT05FUyBFTiBUSSBTQSBEIUJGVjEwMC4GA1UEKRMnREVTQVJST0xMT1MgWSBT
T0xVQ0lPTkVTIEVGFERLIFNBIERFIENWMTAwLgYDVQQKEydERVNBUlJPTExPUyBZIFNPTFVDSU9O
RVMgRU4gVEkgU0EgREUgQ1YxJTAjBgNVBC0THERTVDEwMTAxODVCNyAvIFJJSk82OTA1MDhUQzEx
HjAcBgNVBAUTFSAvIFJJWEo2OTA1MDhIWlNTWFIwNjEPMA0GA1UECxMGVW5pZGFkMIGfMA0GCSqG
SIb3DQEBAQUAA4GNADCBiQKBgQDQZhQqxDy8Z05TPsl+jWl02mufOmhO2gyfQ2fNyCdbdjDDX3Ro
yp/23TYv6GiITJrsnUrEgDN6WrFIyS906GvyUvzQ8yTDwJPcS3PPLeybKr45PQIs06pyX70bNCEa
hJE3Afx+0YxfgQcw4QuSJ3Gr0mQT1A7/N0Ol33iQgtTLeQIDAQABox0wGzAMBgNVHRMBAf8EAjAA
MAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAbkjSi+DlMH69RK7fFXDLvZYUX+4gvutp
X2ex4LU/qFZVw7lvIYWITeUqF2DmuRzNXKNQqgSSRwuOnU0/ipxjR9JL0JIlLgy71nMtwMyQUO8q
Ei/EihXg1XHtOvPSsnFigRunD8ziyDpz+2ozUZS969zjRbsve9J5J2ke3CirrIjOLQaYbWBngrdl
8pXJPaaElkB5ZwzRKAP94P14WPOioTSmkBbhChEJ6xZKFcDRySRfWAsXmss9CvBM3nMqPhFdw2kj
6Rr/NsST5PZtp5Olk1xBhrPj5MVTZmzLpDvTz6+wFwrn5ucrIkUL+Uk4ZGD0HnTZYEeCh+VPeyXe
Er5fAw==
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>

注意不需要的换行符。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

几个小时后,我找到了解决问题的方法。 我希望这适用于其他人。

我们只需要将“true”值设置为“ignoreLineBreaks”参数, 导致'默认值为false,这允许签名API添加LineBreaks

这是避免或删除LineBreaks的代码

Field f = XMLUtils.class.getDeclaredField("ignoreLineBreaks");
f.setAccessible(true);
f.set(null, Boolean.TRUE);

然后,我们可以使用下一个代码行确保新值为true

System.err.println(XMLUtils.ignoreLineBreaks());

答案 1 :(得分:0)

您可以使用文本编辑器(如Notepad ++)轻松删除任何空格,包括换行符,制表符和换行符等。下面是一个快照,显示可用于删除这些空格的扩展字符。 Replace tab in notepad++ text editor