-
Notifications
You must be signed in to change notification settings - Fork 141
Description
According to the XML Signature specification, the value of the SignatureValue field is supposed to be "the base64 encoding of the concatenation of two octet-streams that respectively result from the octet-encoding of the values r and s" of the ECDSA signature.
ValidationContext.Validate calls x509.Certificate.CheckSignature to verify the XML signature, which, for ECDSA signatures, calls ecdsa.VerifyASN1.
As the name suggests, this function requires the signature to be ASN.1 encoded, making the function fail for valid XML signatures.
Reproducer
I verified this using xmlsec1 to create a signed XML document.
The resulting signature can not be validated using goxmldsig, resulting in an x509: ECDSA verification failure error.
The steps are as follows:
- Start by creating an XML template file and save it as
template.xml:
<root>
<data>TestDocument</data>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"/><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/><ds:DigestValue></ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue></ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate></ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
</root>- Generate an EC key and certificate:
openssl req -new -x509 -key signing_key.pem -sha384 -days 365 -out signing_cert.pem -subj "/CN=ECDSA Test/O=Example/C=US"- Create the signed XML document:
xmlsec1 --sign --output signed.xml --privkey-pem signing_key.key,signing_cert.crt template.xml- Verify the XML signature:
xmlsec1 --verify --trusted-pem signing_cert.crt signed.xmlThis should return the following:
OK
SignedInfo References (ok/all): 1/1
Manifests References (ok/all): 0/0- Run the following Go program to check the result
package main
import (
"crypto/x509"
_ "embed"
"encoding/pem"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
//go:embed doc.xml
var xmlData []byte
//go:embed signing_cert.pem
var signingCert []byte
func main() {
doc := etree.NewDocument()
if err := doc.ReadFromBytes(xmlData); err != nil {
panic(err)
}
certPEM, _ := pem.Decode(signingCert)
cert, err := x509.ParseCertificate(certPEM.Bytes)
if err != nil {
panic(err)
}
ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{cert},
})
if _, err := ctx.Validate(doc.Root()); err != nil {
panic(err)
}
}This will return the following:
panic: x509: ECDSA verification failureConversely, manually updating SignatureValue to the ASN.1 encoding of the signature results in the Go code succeeding, but other XML signature verification tools in failing to do so