当前位置: 首页 > 知识库问答 >
问题:

由于更改了XML属性顺序,导致数字签名损坏

费辰阳
2023-03-14
Actual Digest: ljf4iIFTgpHUDKtLjYJEto9Ro5k=

Expected Digest: iIYWShXDG4o8f/9L08d+apVsGx0=

我测试了一个SOAPHandler来截取响应,但我没有找到任何方法来更改消息属性的顺序。

这是签名类生成的节点时间戳的XML代码:

            <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TS-1000">
                <wsu:Created>2019-09-19T10:00:00.000Z</wsu:Created>
                <wsu:Expires>2019-09-19T10:05:00.000Z</wsu:Expires>
            </wsu:Timestamp>

这是响应中发送的时间戳节点的XML代码:

            <wsu:Timestamp wsu:Id="TS-1000" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <wsu:Created>2019-09-19T10:00:00.000Z</wsu:Created>
                <wsu:Expires>2019-09-19T10:05:00.000Z</wsu:Expires>
            </wsu:Timestamp>
        <S:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Body-1000">
            <AsignacionNotarioResponse xmlns="http://ancert.notariado.org/XML">
                <CodigoRespuesta>0</CodigoRespuesta>
                <IdNotificacionCGN>371003</IdNotificacionCGN>
            </AsignacionNotarioResponse>
        </S:Body>
        <S:Body wsu:Id="Body-1000" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <AsignacionNotarioResponse xmlns="http://ancert.notariado.org/XML">
                <CodigoRespuesta>0</CodigoRespuesta>
                <IdNotificacionCGN>371003</IdNotificacionCGN>
            </AsignacionNotarioResponse>
        </S:Body>
   <SOAP-ENV:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509Token-1000" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">MIIHdDCCBVygAwIBAgIQDOHw8dChstzYGWhilSpZhjANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCRVMxQTA
    ...OMITED... ==</wsse:BinarySecurityToken>
         <wsu:Timestamp wsu:Id="TS-1000" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsu:Created>2019-09-19T10:00:00.000Z</wsu:Created>
            <wsu:Expires>2019-09-19T10:05:00.000Z</wsu:Expires>
         </wsu:Timestamp>
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
               <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
               <ds:Reference URI="#Body-1000">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                  <ds:DigestValue>5yQ7ZdxYjr3pxySKrVbA0/98a4s=</ds:DigestValue>
               </ds:Reference>
               <ds:Reference URI="#TS-1000">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                  <ds:DigestValue>sEY89etI7c+uGrFPh7W59nu/4ac=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>CFsbgg+AbV6iiMqWbiZmCacMeZcmcrsW2Eub5B1bUzLsCnygrFZDv/WEI5R3CyS6nvSPNvr7TKXg
                W235F2mPYSUXFLun/IPYU+0BsMYMLxFF4qMX2pXRFgtXWt9zmhBIf1rl+iuG8mTqUGR0eYMrxW0B
                KxpAIgAEAUZmWuP7vHcnfPrEhR2+N7S4BOVloSlVFoekh1tr0njH1RDR3WYyP8XszeZdzaQmDHKl
                QONJQ5zjpaHk/TCMLhiSib+aDAeF4MaT73eo68rM5HNyD4b5EKty+z+bE6GPsS/lR8TFbP0uwLDz
                9uKiM0l7fM1ctEd3RORkveXvSXGZlKQ+HKmISA==</ds:SignatureValue>
            <ds:KeyInfo Id="KI-1000">
               <wsse:SecurityTokenReference wsu:Id="STR-1000" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                  <wsse:Reference URI="#X509Token-1000"/>
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
      </wsse:Security>
   </SOAP-ENV:Header>
        /**
         * Genera la firma del mensaje SOAP.
         * 
         * @param privateKey                        Clave privada
         * @param soapBody                          Cuerpo de la petición SOAP
         * @param nodoSecurity                      Nodo Security
         * @param nodoSecurityTokenReference        Nodo SecurityTokenReference
         * @param nodoTimestamp                     Nodo timestamp
         * 
         * @throws CgnException                     Error al generar la firma del mensaje
         */
        private static void crearFirmaSeparada(PrivateKey privateKey, SOAPBody soapBody, SOAPElement nodoSecurity, SOAPElement nodoSecurityTokenReference, 
                SOAPElement nodoTimestamp) throws CgnException 
        {
            String uri_algoritmo_digest         = "http://www.w3.org/2000/09/xmldsig#sha1";                 
            String uri_algoritmo_firma          = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";             
            String uri_algoritmo_transformacion = "http://www.w3.org/2001/10/xml-exc-c14n#";
            String uri_algoritmo_canonizacion   = "http://www.w3.org/2001/10/xml-exc-c14n#";


            try {
                // Creamos un el DOM XMLSignatureFactory que utilizaremos para generar la firma        
                String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
                Provider provider = (Provider) Class.forName(providerName).newInstance();
                XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM", provider);

                // Digest method
                javax.xml.crypto.dsig.DigestMethod digestMethod = xmlSignatureFactory.newDigestMethod(uri_algoritmo_digest, null);
                List <Transform> l_transformaciones = new ArrayList();


                // Transformaciones
                Transform envTransform = xmlSignatureFactory.newTransform(uri_algoritmo_transformacion, (TransformParameterSpec) null);
                l_transformaciones.add(envTransform);

                // Referencias al timestamp y al body
                String id_key_info = "KI-1000";

                List <Reference> l_referencias = new ArrayList();
                Reference refTS = xmlSignatureFactory.newReference("#TS-1000", digestMethod, l_transformaciones, null, null);
                Reference refBody = xmlSignatureFactory.newReference("#Body-1000", digestMethod, l_transformaciones, null, null);

                l_referencias.add(refBody);
                l_referencias.add(refTS);


                CanonicalizationMethod cm = xmlSignatureFactory.newCanonicalizationMethod(uri_algoritmo_canonizacion, (C14NMethodParameterSpec) null);

                SignatureMethod sm = xmlSignatureFactory.newSignatureMethod(uri_algoritmo_firma, null);
                SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(cm, sm, l_referencias);


                DOMSignContext signContext = new DOMSignContext(privateKey, nodoSecurity);

                signContext.setDefaultNamespacePrefix("ds");
                signContext.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", "ds");

                // Registramos los Id de los elementos (Requerido en últimas versiones de Java)
                signContext.setIdAttributeNS(soapBody, NAMESPACE_WSU, "Id");
                signContext.setIdAttributeNS(nodoTimestamp, NAMESPACE_WSU, "Id");

                KeyInfoFactory keyFactory = KeyInfoFactory.getInstance();
                DOMStructure domKeyInfo = new DOMStructure(nodoSecurityTokenReference);
                KeyInfo keyInfo = keyFactory.newKeyInfo(java.util.Collections.singletonList(domKeyInfo), id_key_info);

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

                signature.sign(signContext);
            } catch (Exception ex) {
                CgnException cgnex = new CgnException(Errores.ERR_PROC_GENERAR_FIRMA_MENSAJE, ex);
                throw cgnex;
            }
        }

共有1个答案

张智
2023-03-14

过了几天,我终于设法找到了问题。

为了签名主体,我必须为标记分配一个Id,以及在tar下对这个Id的引用。

所以我的XML如下所示:

我的功能是将Id属性添加到Body标记:

/**
 * Asigna un identificador único al nodo Body del mensaje.
 * 
 * @param soapMessage                       Mensaje SOAP
 * 
 * @throws SOAPException
 */
private static void asignarIdNodoBody(SOAPMessage soapMessage) throws SOAPException {
    String idBody = "Body-123456";
    SOAPBody soapBody = soapMessage.getSOAPBody();
    soapBody.setAttributeNS(NAMESPACE_WSU, "wsu:Id", id_body);
}

由于一些奇怪的原因我不明白,上面的代码导致添加的数字签名没有通过验证。

我用这个函数替换了上面的函数

/**
 * Asigna un identificador único al nodo Body del mensaje.
 * 
 * @param soapMessage                       Mensaje SOAP
 * 
 * @throws SOAPException
 */
private static void asignarIdNodoBody(SOAPMessage soapMessage) throws SOAPException {
    String idBody = "Body-123456";
    SOAPBody soapBody = soapMessage.getSOAPBody();
    SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
    Name name = soapEnvelope.createName("Id", "wsu", NAMESPACE_WSU);

    soapBody.addAttribute(name, id_body);
}
Referencia [0] 
    URI:              #Body-123456
    Validacion OK:    true 
    Digest:           JMdmg+d/yJJA1wg7yzDctIBE9z4= 
    Expected digest:  JMdmg+d/yJJA1wg7yzDctIBE9z4= 
Referencia [1] 
    URI:              #TS-1000 
    Validacion OK:    true 
    Digest:           sEY89etI7c+uGrFPh7W59nu/4ac= 
    Expected digest:  sEY89etI7c+uGrFPh7W59nu/4ac=
 类似资料:
  • 对于一个关于签名数据被哈希两次的C#问题,我看到了一个类似的答复,但是我不知道为什么我的签名数据会出现在这里。 C#PKCS7 Smartchard数字签名损坏

  • 我尝试使用智能卡(USB令牌)对pdf文件进行签名,但在Adobe中打开签名的pdf文件时,遇到错误。这个错误不是描述性的,我也不知道该去哪里看,因为代码对我来说似乎很好,但显然不是… 我使用的代码是: 我尝试签名的pdf文件是这个。 添加签名字段后创建的临时pdf文件如下。 签名的Base64格式为

  • 我已经研究了所有类似的问题,但找不到一个应用itextsharp延迟签名的案例。 基本上,我的应用程序使用签名对pdf文档进行签名,该签名是由远程web服务创建的。 我的应用程序向这个web服务发送原始文档的哈希(添加空签名字段后可签名字节的哈希),并接收一个Base64编码的签名文件。 我将此签名嵌入到先前生成的临时pdf文件中,该文件具有空签名字段。 最后,我的签名未被验证,因为Adobe R

  • 我已经安装了elasticsearch(6.6.0)和CentOS 7。我想为旋转日志添加更多属性,比如大小为50MB的旋转和压缩。但如果我在/etc/elasticsearch/log4j2中添加更多配置。属性文件并重新启动elasticsearch服务器,则失败。 我当前的log4j2.properties文件: 当我尝试添加,因为它是在elasticsearch文档这是如何添加配置, 它是错

  • 问题内容: 通过标准DOM处理XML时,不能保证属性顺序在重新序列化之后。最后,这是我在使用标准java XML Transform API序列化输出时刚刚意识到的。 但是我确实需要保持秩序。我想知道在Java上是否有可能保持通过DOM API处理的XML文件的属性的原始顺序,或以任何方式强制执行该顺序(可能通过使用替代的序列化API来让你进行设置)一种财产)。就我而言,处理减少了用一堆属性来更改