XMLDSig X509SerialNumber 太大而不能成为 int,XSD 验证失败

Posted

技术标签:

【中文标题】XMLDSig X509SerialNumber 太大而不能成为 int,XSD 验证失败【英文标题】:XMLDSig X509SerialNumber too large to be an int, fails XSD validation 【发布时间】:2013-02-20 03:23:24 【问题描述】:

我正在尝试使用 X509 证书创建 XMLDSig。我从 MS (http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.x509issuerserial.aspx) 运行逐字示例,它生成下面的 XML。 XML 的问题在于 X509SerialNumber 字段太长而不能成为 int,而这正是 XSD 指定它必须的。因此,当我尝试对签名进行 XSD 验证时,它会失败。

我得到的错误信息是: 'http://www.w3.org/2000/09/xmldsig#:X509SerialNumber' 元素无效 - 值 '72620403068401703770138453672807553309' 根据其数据类型 'http://www.w3.org/2001/XMLSchema:integer' 无效 - 字符串 '72620403068401703770138453672807553309' 无效。

如何获得 X509SerialNumber 的正确值?

提前致谢!

<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" />
      </Transforms>
      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <DigestValue>zSI5ZAMmQ+8u7R2rP7aAPT6nNQw=</DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue>Tx4rqqDae4vdi5sTjARf0AlBiIGWnx2D8ET+ogGD9FtjrX4ZuYlsOG03Zk5KPKDpC/T45XlWaZpZdCtvAWtv0zwL1/jXxlU2BomQFNXm7rb9YoqlTh8nISStiZKizhmMQynW6GRsXGIpkK37Hnip4c8H1U+eSC/taKW4oyUmg40W64+ZyntovpBt2GqIJQu4AFvMfiF2azV9pg/qZ7IYNOgwmrUG6F0t2RhT2hqR9YRePjrfyIebZvYrLwjTQPXGOzzc2utRILAEhzGNSqsvpf5YeVrmuX75E8Zs3JuaicXu4mgDPYxNNVE2membNQMl6ggllfFjxPnvIofbb/KJ4Q==</SignatureValue>
  <KeyInfo>
    <X509Data>
      <X509IssuerSerial>
        <X509IssuerName>CN=XMLDSIG_Test</X509IssuerName>
        <X509SerialNumber>72620403068401703770138453672807553309</X509SerialNumber>
      </X509IssuerSerial>
      <X509Certificate>MIIDIDCCAgygAwIBAgIQNqIuTm7QSrZClm5/JrLZHTAJBgUrDgMCHQUAMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdDAeFw0xMDAxMDEwNjAwMDBaFw0yMDAxMDEwNjAwMDBaMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMl9hSOn53/2W2//EC8HUgwO7Hwpqx0/yTwth0w3amefwZcfu/+7k9rB+mnviCy6G/9uGzb0Mld+L3RVXisAx9zr2l6LVFjzImY1alwZ01z6AiDdllFPqO7BoSJSozMh0k+vdVQYR3lvgLNyKxXmrTayIWhioQeteIo6HuChz8HI/DNdzoO8axGbLuhy34pogG1gAQr3pTn16Pkd4Mu02KoRz90dryt09wuAk1P/jsePYHBeLQeJSLGojWp1sqypxr25FQiqJantyVLXRRmv7IauTTThSSNrREMcTzbpCx7B4tvyocNwGZysYcdJVsyjbxJRLqutQDlID6QykqkL9O8CAwEAAaNYMFYwVAYDVR0BBE0wS4AQ0N2edJbnLN9AE7hLcICPNaElMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdIIQNqIuTm7QSrZClm5/JrLZHTAJBgUrDgMCHQUAA4IBAQC5Nf5SGjqIzQqVnwJbP22RqSHrITAPlymGYfP/qST8Q9V5h5aX8idcGMt3lShUbexXAlKcpQLO4ZzUrjjP3H5Jc659sRSDaeqHGXE0ZMTJpvwA871WH/sGZ8tB7/yuHVsP9hPTImwwDCWx9mYDz8LxpvK11beq/tEilZQxLTvMP0MuT5A6YdCcCc4GkeDV0KVFF+VLEO8OkaWDVXUNMe/AJBHrXuHbQPrUb7s67FKH+b/2GVjBBkM6YI9JtL/A96Y2uf6drhOz6C7wfky2XQOe/7v87/YGEshObBawBA1/OB1AVa+A2WVOosisEGi7iJqszQTdF6TLqGB5eDsiZCH2</X509Certificate>
    </X509Data>
  </KeyInfo>
</Signature>

我正在使用来自以下 URL 的 XSD:

http://www.w3.org/2000/09/xmldsig#

这是我验证 XSD 的代码:

    XmlElement xmlDigitalSignature = signedXml.GetXml();

    var xEl = XElement.Parse(xmlDigitalSignature.OuterXml);
    var xDoc = XDocument.Load(xEl.CreateReader());

    XSDValidator.ValidateSignature(xDoc);


public class XSDValidator

    public static void ValidateSignature(XDocument document)
    
        var schemaSet = new XmlSchemaSet();
        var assm = Assembly.GetExecutingAssembly();
        using (var stream = assm.GetManifestResourceStream("JayTest1.XMLSignature.xsd"))
        
            schemaSet.Add(XmlSchema.Read(stream, null));
        
        var isValid = true;
        string errorMessage = null;

        document.Validate(schemaSet, (o, e) =>
        
            errorMessage = e.Message;
            isValid = false;
        );
        if (!isValid)
        
            Console.WriteLine("XSD is not valid: " + errorMessage);
        
        else
        
            Console.WriteLine("GOOD!");
        
    

【问题讨论】:

【参考方案1】:

根据RFC 5280序列号可以预期包含长整数:

证书用户必须能够处理最多 20 个八位字节的 serialNumber 值。符合标准的 CA 不得使用超过 20 个八位字节的 serialNumber 值。

(关于序列号的第 4.1.2.2 节)

您的序列号7262040306 8401703770 1384536728 07553309只有 38 位数字,即使它们是十六进制数字,也很容易形成一个适合 20 字节长整数的数字。

在XML Signature Syntax and Processing (Second Edition)(和schema file)中,元素X509SerialNumber被定义为

<element name="X509SerialNumber" type="integer"/>

根据integer 的定义确实允许任意整数值:

integer 是通过将 fractionDigits 的值固定为 0 从 decimal 派生。这导致整数的标准数学概念。整数的值空间是无限集...,-2,-1,0,1,2,...。整数的基本类型是十进制。

(XML Schema Part 2: Datatypes 第 3.3.13 节)

因此,您可能需要检查架构文件或 XSD 验证器。

编辑

虽然您的代码基于XML-Signature Syntax and Processing 而不是XML Signature Syntax and Processing (Second Edition) 我的回答是,但这并没有什么区别,因为在这两种情况下X509SerialNumber 都被定义为integer 而没有进一步的限制。

因此,这是您的验证器的问题。是错误还是只是一些配置或自定义问题,我不知道。

【讨论】:

mkl,谢谢您的回复。我已经用我正在使用的 XSD 文件和我用来验证 XSD 的代码更新了这个问题。我是否在 XSD 检查中做错了什么? @jhilden 您的 XMLdsig 版本还将 X509SerialNumber 定义为 integer. 因此,这是您的验证器的问题。我不知道这是一个错误还是仅仅是一些配置或自定义问题。 嗨,你解决过这个问题吗?我今天也遇到了同样的问题。我很难相信 .NET System.Xml 库有问题....此外,我在 Notepad++ 的 XML 插件中遇到了同样的验证错误 - 所以这是 2 个据称现在有问题的验证器...... 对不起,西蒙,但我认为我从来没有解决过这个问题。也许手动更新 XSD 是关键。 嗯,不喜欢这样做,但这似乎是我唯一可用的选择。不敢相信 .NET xsd 验证器行为不端已经 2 年了,但没有得到修复!我将在解析后将 xsd 更改为说字符串和数字检查【参考方案2】:

xs:integer 的 .NET XSD 验证器尝试通过将其解析为 C# decimal(https://referencesource.microsoft.com/#System.Xml/System/Xml/Schema/DataTypeImplementation.cs,2874、https://referencesource.microsoft.com/#System.Xml/System/Xml/XmlConvert.cs,3e8716fb1936c48d)来验证该值。

十进制的范围为正数 79,228,162,514,264,337,593,543,950,335 到负数 79,228,162,514,264,337,593,543,950,335 (https://docs.microsoft.com/en-us/dotnet/api/system.decimal?view=netframework-4.7),或 28.79 位。

此限制确实超过了最小值http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#decimal:

注意:所有 · 最低限度符合 · 处理器 · 必须 · 支持至少 18 位十进制数字的十进制数字(即 18 位的 ·totalDigits )。但是,··最低限度符合··处理器··可以·设置应用程序定义的最大十进制位数限制...

如果您觉得这阻碍了这些类型的有效使用(不仅仅是测试场景,尽管这些也很重要)https://github.com/dotnet/corefx/issues/ 将是搜索要投票的问题的地方(或找不到问题,创建一个新的一)。

【讨论】:

以上是关于XMLDSig X509SerialNumber 太大而不能成为 int,XSD 验证失败的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法漂亮地打印 X509Certificate?

SAML 请求中缺少 xmlns:ds="http://www.w3.org/2000/09/xmldsig#"

iot:Certificate.Subject.SerialNumber 用于限制影子访问

libusb 根据设备的serialnumber来打开

js计算数组中某个元素重复出现的个数

ASN1_INTEGER到ASN1_STRING