XML 签名验证的基础知识

Adobe AIR 1.5 和更高版本

有关验证 XML 签名的快速介绍和代码示例,请参阅 Adobe Developer Connection 中的以下快速入门文章:

Adobe® AIR® 提供了用于验证 XML 签名的 XMLSignatureValidator 类和 IURIDereferencer 接口。XMLSignatureValidator 类接受的 XML 语法是针对 XML 签名语法和处理的 W3C 建议的子集。(由于仅支持该建议的子集,因此并不是可以验证所有合法签名。)AIR 未提供用于创建 XML 签名的 API。

XML 签名验证类

XML 签名验证 API 包含以下类:

flash.security

XMLSignatureValidator 字符串常量在以下类中定义:

flash.events

使用 XML 签名验证类

若要使用 XMLSignatureValidator 类验证 XML 签名,您必须:

  • 创建 XMLSignatureValidator 对象

  • 提供 IURIDereferencer 接口的实现。XMLSignatureValidator 对象调用 IURIDereferencer dereference() 方法,将签名中的每个引用传入 URI。 dereference() 方法必须解析 URI 并返回引用的数据(该数据可能与签名位于同一文档中,也可能位于外部资源中)。

  • 设置与您的应用程序相适应的 XMLSignatureValidator 对象的证书信任、吊销检查和引用验证设置。

  • complete error 事件添加事件侦听器。

  • 调用 verify() 方法,传入要验证的签名。

  • 处理 complete error 事件并解释结果。

以下示例实现用于验证 XML 签名有效性的 validate() 函数。设置 XMLSignatureValidator 属性,以便签名证书必须位于系统信任存储区中,或者链接到信任存储区中的证书。该示例还假定存在一个合适的名为 XMLDereferencer 的 IURIDereferencer 类。

private function validate( xmlSignature:XML ):void 
{ 
    var verifier:XMLSignatureValidator = new XMLSignatureValidator(); 
    verifier.addEventListener(Event.COMPLETE, verificationComplete); 
    verifier.addEventListener(ErrorEvent.ERROR, verificationError); 
    try 
    { 
        verifier.uriDereferencer = new XMLDereferencer(); 
 
        verifier.referencesValidationSetting = 
            ReferencesValidationSetting.VALID_IDENTITY; 
        verifier.revocationCheckSetting = RevocationCheckSettings.BEST_EFFORT; 
        verifier.useSystemTrustStore = true; 
         
        //Verify the signature 
        verifier.verify( xmlSignature ); 
    } 
    catch (e:Error) 
        { 
            trace("Verification error.\n" + e); 
        } 
} 
 
//Trace verification results 
private function verificationComplete(event:Event):void 
 
    var signature:XMLSignatureValidator = event.target as XMLSignatureValidator; 
    trace("Signature status: " + signature.validityStatus + "\n"); 
    trace("  Digest status: " + signature.digestStatus + "\n"); 
    trace("  Identity status: " + signature.identityStatus + "\n"); 
    trace("  Reference status: " + signature.referencesStatus + "\n"); 
} 
 
private function verificationError(event:ErrorEvent):void 
{ 
    trace("Verification error.\n" + event.text);                 
}

XML 签名验证过程

当调用 XMLSignatureValidator verify() 方法时,AIR 将执行以下步骤:

  • 运行时使用签名证书的公钥来验证签名的加密完整性。

  • 运行时根据 XMLSignatureValidator 对象的当前设置建立证书的加密完整性、标识和信任度。

    放置在签名证书中的信任关系是验证过程完整性的关键。签名验证是使用良好定义的加密过程执行的,但签名证书的信任度是一种判断,无法通过算法计算。

    通常,可以使用三种方法确定证书是否可信:

    • 通过依靠证书颁发机构和操作系统信任存储区。

    • 直接从签名者获取证书副本(该证书副本是充当证书信任锚的另一证书)或者可靠地标识该证书的足够信息(如公钥)。

    • 如果最终用户信任该证书,则向他们询问您的应用程序。此类查询对自签名证书无效,因为证书中的标识信息本身并不可靠。

  • 运行时验证已签名数据的加密完整性。

    签名的数据是借助 IURIDereferencer 实现来验证的。对于签名文档中的每个引用,调用 IURIDereferencer 实现的 dereference() 方法。 dereference() 方法返回的数据用于计算引用摘要。此摘要值与签名文档中记录的摘要进行比较。 如果摘要匹配,则该数据自签名以来没有被更改。

    在依赖验证 XML 签名的结果时,需要重点考虑的一点是只有对什么签名才是安全的。例如,考虑使用列出包中文件的签名清单。当 XMLSignatureValidator 验证签名时,它仅检查清单本身是否未更改。而文件中的数据未被签名,因此当清单中引用的文件被更改或删除时,仍将验证签名。

    注: 若要验证此类清单中的文件,可以计算文件数据的摘要(使用与清单相同的哈希算法),并将结果与签名清单中存储的摘要进行比较。在某些情况下,还应检查其他文件的存在。

解释验证结果

验证结果由 XMLSignatureValidator 对象的状态属性报告。在验证程序对象调度 complete 事件后,可以读取这些属性。这四个状态属性是: validityStatus digestStatus identityStatus referencesStatus

validityStatus 属性

validityStatus 属性报告签名的总体有效性。 validityStatus 取决于其他三种状态属性的状态,并且可以是下列值之一:

  • valid — 如果 digestStatus identityStatus referencesStatus 都是 valid

  • invalid — 如果一个或多个状态属性为 invalid

  • unknown — 如果一个或多个单独的状态属性为 unknown ,且没有单独的状态为 invalid

digestStatus 属性

digestStatus 属性报告消息摘要的加密验证的结果。 digestStatus 属性可以是下列值之一:

  • valid — 如果签名文档本身自签名以来未被更改。

  • invalid — 如果签名文档已更改或格式不正确。

  • unknown — 如果 verify() 方法未完成,且未出现错误。

identityStatus 属性

identityStatus 属性报告签名证书的状态。此属性的值取决于多个因素,其中包括:

  • 证书的加密完整性

  • 证书是否过期或被吊销

  • 证书在当前计算机上是否受信任

  • XMLSignatureValidator 对象的状态(如,是否为构建信任链添加了其他证书,这些证书是否受信任以及 useSystemTrustStore revocationCheckSettings 属性的值)

identityStatus 属性可以是下列值:
  • valid — 若要使签名证书被认为是有效的,必须符合下列条件:

    • 签名证书必须未被更改。

    • 签名证书必须未到期或吊销(除非签名中存在有效的时间戳)。 如果签名没有时间戳,则只要对文档进行签名时证书有效,就将该证书视为有效。 (时间戳服务对时间戳进行签名所使用的证书必须与用户计算机上的受信任根证书有联系。)

    • 签名证书是受信任证书。如果证书位于系统信任存储区或者链接到系统信任存储区中的其他证书,并且将 useSystemTrustStore 属性设置为 true,该证书即是受信任证书。还可以使用 XMLSignatureValidator 对象的 addCertificate() 方法将证书指定为受信任证书。

    • 该证书实际上是签名证书。

  • invalid — 该证书已过期或被吊销,并且在签名时不存在任何证明签名有效性的时间戳,或者证书已更改。

  • unknown — 如果该证书没有失效,但也不被信任。例如,自签名证书将被报告为 unknown (除非明确被信任)。如果 verify() 方法未完成且未出现错误,或者由于签名摘要无效而未检查标识, identityStatus 也会被报告为 unknown

referencesStatus 属性

referencesStatus 属性报告签名的 SignedData 元素中的引用的加密完整性。

  • valid — 如果签名中每个引用的计算的摘要与 XML 签名中记录的相应摘要匹配。 valid 状态指示签名的数据未被更改。

  • invalid — 如果计算的任何摘要与签名中相应的摘要都不匹配。

  • unknown — 如果未检查引用摘要。如果整个签名摘要为 invalid 或者签名证书无效,则不检查引用。如果 identityStatus unknown ,则仅在 referencesValidationSetting validOrUnknown 时才检查引用。