首页 > 解决方案 > XML 摘要值不正确

问题描述

描述

我正在尝试计算 XML 数字签名的摘要值。问题是我无法计算出正确的摘要值。

出于测试目的,我使用了一个填充了有效数据的示例请求,我的目标是为引用的对象计算相同的摘要值。

示例 SOAP 消息():

我建议从源中查看消息(通过缩进可视化)。

<s:Envelope xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wse: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" u:Id="BinaryToken1" xmlns:wse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">MIIEmTCCA4GgAwIBAgIFAKCnuv0wDQYJKoZIhvcNAQELBQAwdzESMBAGCgmSJomT8ixkARkWAkNaMUMwQQYDVQQKDDrEjGVza8OhIFJlcHVibGlrYSDigJMgR2VuZXLDoWxuw60gZmluYW7EjW7DrSDFmWVkaXRlbHN0dsOtMRwwGgYDVQQDExNFRVQgQ0EgMSBQbGF5Z3JvdW5kMB4XDTE5MDgwODE5MjM0MloXDTIyMDgwODE5MjM0MlowQzESMBAGCgmSJomT8ixkARkWAkNaMRMwEQYDVQQDEwpDWjAwMDAwMDE5MRgwFgYDVQQNEw9wcmF2bmlja2Egb3NvYmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrVmZ6FE2jYqli43/LbXZ1vEG8USMRcC/zbGgk5mAoQQKMtF5PIm5i84pd0cPOSRtduNODc7mwjbPKd5r8p592zNhpei0/XbQcYQ5rpdf0Y84ZNbg9ZmB4nF8YCBy3Gk28YxfW//vIjqvkuQK6InT4l784gtz/iNAV48ZBkgE/jp+MMii1I+y5EyYkQuRZlCJtOTKdPXECnr5OrxrGUtbjmF7bBWLD2LXlspZoUOmh4RFfd9WHH8PmcQfij5aJq6cgIB2YENCBHSA1/HZZEd8vNLv05owb/BOvXj4n86lYJ8tlJVMcorAsrEzVy+XU++78/j9PewL0ft0jETHd0U8DAgMBAAGjggFeMIIBWjAJBgNVHRMEAjAAMB0GA1UdDgQWBBT8zaUMxlfEGXSD/2PZ089ZLGgerTAfBgNVHSMEGDAWgBR8MHaszNaH0ezJH+JwCCzjX94MBzAOBgNVHQ8BAf8EBAMCBsAwYwYDVR0gBFwwWjBYBgpghkgBZQMCATABMEowSAYIKwYBBQUHAgIwPAw6VGVudG8gY2VydGlmaWvDoXQgYnlsIHZ5ZMOhbiBwb3V6ZSBwcm8gdGVzdG92YWPDrSDDusSNZWx5LjCBlwYDVR0fBIGPMIGMMIGJoIGGoIGDhilodHRwOi8vY3JsLmNhMS1wZy5lZXQuY3ovZWV0Y2ExcGcvYWxsLmNybIYqaHR0cDovL2NybDIuY2ExLXBnLmVldC5jei9lZXRjYTFwZy9hbGwuY3JshipodHRwOi8vY3JsMy5jYTEtcGcuZWV0LmN6L2VldGNhMXBnL2FsbC5jcmwwDQYJKoZIhvcNAQELBQADggEBAKVFyv168b/q0X568G+JDvNnz4XVElbJ1r9ro/xv58QP+FD8PJSR5qxN2F7zKGNYTCee0jSo+XY1KEoSkmeoYHXnQpm7+NG7iUYc2OWu0B3hC/wMMhNEDtmsTwqSLjgSk6pZTTRXfvtaHf7zvU8iw1PGFhb9m9bJlOfLwoMeFclOpdfo80pbwRz5t8io/c0lvGodlYj7INHxjlwdwWf3m2mUx4iuKvoAev0ASCdSMDuUWWjYiMT3PEUqeabeM2dn3xccQ2EhgIcCwhQs2MCA/FDLBbiOt63mUJPJHATIFi/31VKtz11/Gc434HHsVYB8U/aammSyIfMp6bNE6LhaFe8=</wse:BinarySecurityToken><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#_1"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>OX7JTeL80dE6yDHOs6ILGQzitQI7DB5lEhBH7TNcmbo=</DigestValue></Reference></SignedInfo><SignatureValue>hn3LK3tdJrYBpFZto6Lahtei7A2nVR1wbs45IzvXElZIae7m6zTHDiLetPliq+ZuzvlvfA7llZPeAgk5JNBQX/BP/6B2gomDUPBwsB55cwdfZGk58At2D6++DVqYzYC3esPlPxafZ6x7UOSpg5ShxUgBJsC9YOYlTyWD5Jmh0Z3bfeoZBcNkj1gb7DHE6vNoNWysZgf4xwCn80WaYVVTxyge0FW0dIJ8MeRTNeac4oOWF0Z3104Iu48/NEYqB+ZkyGiBBLVBSIdW8rb2NuRQ+Dg/N8zFNYaH03uF6fpmx/1El1mhooS5yYJurioMZUSJAcasoGDnLqFuEyGNaDCR6Q==</SignatureValue><KeyInfo><wse:SecurityTokenReference xmlns:wse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wse:Reference URI="#BinaryToken1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509" /></wse:SecurityTokenReference></KeyInfo></Signature></wsse:Security></s:Header><s:Body u:Id="_1"><Trzba xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://fs.mfcr.cz/eet/schema/v3"><Hlavicka uuid_zpravy="878b2e10-c4a5-4f05-8c90-abc181cd6837" dat_odesl="2019-08-11T15:36:25+02:00" prvni_zaslani="true" overeni="false" /><Data dic_popl="CZ00000019" id_provoz="141" id_pokl="1patro-vpravo" porad_cis="141-18543-05" dat_trzby="2019-08-11T15:36:14+02:00" celk_trzba="236.00" zakl_dan1="100.00" dan1="21.00" zakl_dan2="100.00" dan2="15.00" rezim="0" /><KontrolniKody><pkp digest="SHA256" cipher="RSA2048" encoding="base64" xmlns="http://fs.mfcr.cz/eet/schema/v3">LnIZVjGlkdvO55gRP9Wa4k48X0QZrLU5aWsFDpYlwcCC/S8KHuUI0hxxS9pPP/vhuvKhe+a2YoZJ6wZDMSlPs0QDtt5i6D6XhQx/Oj84Azoo8fgSf5R6QOpnpsmw+X75jsUlwzGm4+YLGrhbScjdUdHIBLw2XCJus5cPXAb3aWcab59X2L/zaZ87oJRIQsmERMgPBtT8GIZNEfnX89OL/EMyyxibUC0C97aEokK1Lvvm55xidC9wWoMJJtKjNjScsGg5HpmOe0Zqekovtyvwt5mYVCx/fXa3OTsas2vVMskZKLyaxd7GYkJ5Y9nWCyuD8/pzKWR/8BxApIL601VHaQ==</pkp><bkp digest="SHA1" encoding="base16" xmlns="http://fs.mfcr.cz/eet/schema/v3">ABA7EB19-7AD8D753-60ED57B3-9AC9957E-C192030B</bkp></KontrolniKody></Trzba></s:Body></s:Envelope>

如果在这种情况下我理解正确,我会按以下步骤计算摘要:

  1. 规范化引用的对象(XML Exclusive C14N)
  2. 散列引用的对象 ( <s:Body u:Id="_1">...</s:Body>) - 使用 SHA256 算法
  3. 将其编码为base64

我的解决方案

所以我尝试了(在 Go Playground 中):

package main

import (
    "bytes"
    "crypto/sha256"
    "encoding/base64"
    "encoding/xml"
    "fmt"

    "github.com/beevik/etree"
    "github.com/ucarion/c14n"
)

func errCheck(err error) {
    if err != nil {
        panic(err)
    }
}

func canonicalize(b []byte) []byte {
    decoder := xml.NewDecoder(bytes.NewReader(b))
    out, err := c14n.Canonicalize(decoder)
    errCheck(err)
    return out
}

func main() {
    sampleEnv := []byte(`<s:Envelope xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wse: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" u:Id="BinaryToken1" xmlns:wse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">MIIEmTCCA4GgAwIBAgIFAKCnuv0wDQYJKoZIhvcNAQELBQAwdzESMBAGCgmSJomT8ixkARkWAkNaMUMwQQYDVQQKDDrEjGVza8OhIFJlcHVibGlrYSDigJMgR2VuZXLDoWxuw60gZmluYW7EjW7DrSDFmWVkaXRlbHN0dsOtMRwwGgYDVQQDExNFRVQgQ0EgMSBQbGF5Z3JvdW5kMB4XDTE5MDgwODE5MjM0MloXDTIyMDgwODE5MjM0MlowQzESMBAGCgmSJomT8ixkARkWAkNaMRMwEQYDVQQDEwpDWjAwMDAwMDE5MRgwFgYDVQQNEw9wcmF2bmlja2Egb3NvYmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrVmZ6FE2jYqli43/LbXZ1vEG8USMRcC/zbGgk5mAoQQKMtF5PIm5i84pd0cPOSRtduNODc7mwjbPKd5r8p592zNhpei0/XbQcYQ5rpdf0Y84ZNbg9ZmB4nF8YCBy3Gk28YxfW//vIjqvkuQK6InT4l784gtz/iNAV48ZBkgE/jp+MMii1I+y5EyYkQuRZlCJtOTKdPXECnr5OrxrGUtbjmF7bBWLD2LXlspZoUOmh4RFfd9WHH8PmcQfij5aJq6cgIB2YENCBHSA1/HZZEd8vNLv05owb/BOvXj4n86lYJ8tlJVMcorAsrEzVy+XU++78/j9PewL0ft0jETHd0U8DAgMBAAGjggFeMIIBWjAJBgNVHRMEAjAAMB0GA1UdDgQWBBT8zaUMxlfEGXSD/2PZ089ZLGgerTAfBgNVHSMEGDAWgBR8MHaszNaH0ezJH+JwCCzjX94MBzAOBgNVHQ8BAf8EBAMCBsAwYwYDVR0gBFwwWjBYBgpghkgBZQMCATABMEowSAYIKwYBBQUHAgIwPAw6VGVudG8gY2VydGlmaWvDoXQgYnlsIHZ5ZMOhbiBwb3V6ZSBwcm8gdGVzdG92YWPDrSDDusSNZWx5LjCBlwYDVR0fBIGPMIGMMIGJoIGGoIGDhilodHRwOi8vY3JsLmNhMS1wZy5lZXQuY3ovZWV0Y2ExcGcvYWxsLmNybIYqaHR0cDovL2NybDIuY2ExLXBnLmVldC5jei9lZXRjYTFwZy9hbGwuY3JshipodHRwOi8vY3JsMy5jYTEtcGcuZWV0LmN6L2VldGNhMXBnL2FsbC5jcmwwDQYJKoZIhvcNAQELBQADggEBAKVFyv168b/q0X568G+JDvNnz4XVElbJ1r9ro/xv58QP+FD8PJSR5qxN2F7zKGNYTCee0jSo+XY1KEoSkmeoYHXnQpm7+NG7iUYc2OWu0B3hC/wMMhNEDtmsTwqSLjgSk6pZTTRXfvtaHf7zvU8iw1PGFhb9m9bJlOfLwoMeFclOpdfo80pbwRz5t8io/c0lvGodlYj7INHxjlwdwWf3m2mUx4iuKvoAev0ASCdSMDuUWWjYiMT3PEUqeabeM2dn3xccQ2EhgIcCwhQs2MCA/FDLBbiOt63mUJPJHATIFi/31VKtz11/Gc434HHsVYB8U/aammSyIfMp6bNE6LhaFe8=</wse:BinarySecurityToken><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#_1"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>OX7JTeL80dE6yDHOs6ILGQzitQI7DB5lEhBH7TNcmbo=</DigestValue></Reference></SignedInfo><SignatureValue>hn3LK3tdJrYBpFZto6Lahtei7A2nVR1wbs45IzvXElZIae7m6zTHDiLetPliq+ZuzvlvfA7llZPeAgk5JNBQX/BP/6B2gomDUPBwsB55cwdfZGk58At2D6++DVqYzYC3esPlPxafZ6x7UOSpg5ShxUgBJsC9YOYlTyWD5Jmh0Z3bfeoZBcNkj1gb7DHE6vNoNWysZgf4xwCn80WaYVVTxyge0FW0dIJ8MeRTNeac4oOWF0Z3104Iu48/NEYqB+ZkyGiBBLVBSIdW8rb2NuRQ+Dg/N8zFNYaH03uF6fpmx/1El1mhooS5yYJurioMZUSJAcasoGDnLqFuEyGNaDCR6Q==</SignatureValue><KeyInfo><wse:SecurityTokenReference xmlns:wse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wse:Reference URI="#BinaryToken1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509" /></wse:SecurityTokenReference></KeyInfo></Signature></wsse:Security></s:Header><s:Body u:Id="_1"><Trzba xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://fs.mfcr.cz/eet/schema/v3"><Hlavicka uuid_zpravy="878b2e10-c4a5-4f05-8c90-abc181cd6837" dat_odesl="2019-08-11T15:36:25+02:00" prvni_zaslani="true" overeni="false" /><Data dic_popl="CZ00000019" id_provoz="141" id_pokl="1patro-vpravo" porad_cis="141-18543-05" dat_trzby="2019-08-11T15:36:14+02:00" celk_trzba="236.00" zakl_dan1="100.00" dan1="21.00" zakl_dan2="100.00" dan2="15.00" rezim="0" /><KontrolniKody><pkp digest="SHA256" cipher="RSA2048" encoding="base64" xmlns="http://fs.mfcr.cz/eet/schema/v3">LnIZVjGlkdvO55gRP9Wa4k48X0QZrLU5aWsFDpYlwcCC/S8KHuUI0hxxS9pPP/vhuvKhe+a2YoZJ6wZDMSlPs0QDtt5i6D6XhQx/Oj84Azoo8fgSf5R6QOpnpsmw+X75jsUlwzGm4+YLGrhbScjdUdHIBLw2XCJus5cPXAb3aWcab59X2L/zaZ87oJRIQsmERMgPBtT8GIZNEfnX89OL/EMyyxibUC0C97aEokK1Lvvm55xidC9wWoMJJtKjNjScsGg5HpmOe0Zqekovtyvwt5mYVCx/fXa3OTsas2vVMskZKLyaxd7GYkJ5Y9nWCyuD8/pzKWR/8BxApIL601VHaQ==</pkp><bkp digest="SHA1" encoding="base16" xmlns="http://fs.mfcr.cz/eet/schema/v3">ABA7EB19-7AD8D753-60ED57B3-9AC9957E-C192030B</bkp></KontrolniKody></Trzba></s:Body></s:Envelope>`)

    doc := etree.NewDocument()
    err := doc.ReadFromBytes(sampleEnv)
    errCheck(err)

    // isolate the Body element
    bDoc := etree.NewDocument()
    bDoc.SetRoot(doc.FindElement("./Envelope/Body"))
    body, err := bDoc.WriteToBytes()
    errCheck(err)

    // canonicalize
    cBody := canonicalize(body)

    // hash
    hash := sha256.Sum256(cBody)

    // encode to base64
    digest := base64.StdEncoding.EncodeToString(hash[:])

    fmt.Println("Calculated digest:", digest)
    fmt.Println("Correct digest:", doc.FindElement("./Envelope/Header/Security/Signature/SignedInfo/Reference/DigestValue").Text())
}

在上面的代码中,我使用库github.com/ucarion/c14n来规范化 XML。它实现了所需的 ExcC14N 规范化(在 Github 上):

这个包是 XML 规范化(“c14n”)的 Golang 实现。特别是,它实现了 Exclusive Canonical XML 规范,这是在 SAML 中使用的推荐规范化方案。

输出:

Calculated digest: 8wZNjinOeoV5iP9Q2j/F1K1m4dG3NbpKeCX9z1OlwZU=
Correct digest: OX7JTeL80dE6yDHOs6ILGQzitQI7DB5lEhBH7TNcmbo=

我将不胜感激任何建议(无论大小)。

标签: xmlgosoapwssemessage-digest

解决方案


推荐阅读