一、 创建 XML 签名和验证 步骤
1.确定需要对XML文档、其数据对象不服或者其他内容资源进行签名,通过URI将这些数据项目表示为 引用资源 例 使用HTTP URL 引用XML文档类似于这样 http://www.robmebank.com/statement/accont.xml 2.对确定的数据对象应用转换,包括制定的编码规则、规范化算法以及应用于已签名数据的XSLT转换,<transform>元素用于指定要应用的算法 3.转化后,对<Reference> 元素表示的每个已经引用的URI 资源应用消息摘要算法,<DigestMethod>元素指定元素应用的算法,技术得到的摘要值将存储在<DigestValue>元素中 4.构造办函所有的<Reference>元素的<SignedInfo>元素,包括<DigestMethod>和<DigestValue>元素 5.使用<CananonicalizationMethod>元素指定的规范化算法对<SignedInof>元素进行规范化,如果不进行规范化,验证XML签名将可能因为XML结构或者表示方便不同而失败 6计算<SignedInfo>元素的摘要,并使用<SignatureMethod>元素制定的签名算法对齐进行签名,得到的签名值放到<SignatureValue>元素中 7. 添加<KeyInfo>元素(可选),如 X.509 已经验证签名时是否需要公钥 8.构造<Signature>元素,包括表示XML文档或者数据对齐的XML签名的<SignedInfo><SignedValue><KeyInfo>
二、核实和验证XML的签名
1.核实和验证摘要值:
重新计算<Refernce>元素引用的数据对象的摘要值,包括 应用的<Transforms>元素制定的转换,
并使用<DigestMethod>元素指定的算法计算转化结果摘要,将计算得到的摘要值与<DigestValue>元素中的值进行比较 2.核实和验证签名:
使用<KeyInfo>元素包含的或者从外部资源获得的密钥信息重新计算<SignedInfo>元素中的签名,
使用<SignatrueMethod>元素中的规范化方法很重要,因为指定的URI可能会被<SigedInfo>元素中的规范化方法修改,
将计算得到的签名值与<SignatureVlue>元素的值进行比较
三、签名数据结构
封装(enveloped)签名
<Finance> <Message id="0000"> <CPRes id="CPRes"> <version>6.0.1</version><instId>ALIPAY</instId><certId>13389743053847134299</certId><serialNo>2016103016340068218004B99</serialNo><bankCardNo>4218710000005136</bankCardNo><amount>1</amount><overdraft>N</overdraft><channelSystemId>0000</channelSystemId><banktime>20161108 18:00:51</banktime></CPRes> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:CanonicalizationMethod> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod> <ds:Reference URI="#CPRes"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod> <ds:DigestValue>i2+WlR9JT1Cjsih6+BlNZTy4Dto=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> lUSig2nCqu/hxUtiFH5rww0IS+tq8im2qkbWdRmoucPOWAAckHexpYlvM9FHdWdbUgPKx7ao4zVy 2h7NiqPFEbcxN5LsbFUO1wOJ5yHKAEELQLKYS3e4LbLgO+QwwHDaDuOA5DSTAIXH2ZMGze3vNkQx NTqPOP/W+K0Ng2r1NS0= </ds:SignatureValue> </ds:Signature></Message>
被封装(enveloping)和分离(detached)签名
[ ] <Signature Id="MySecondSignature" ...> [p01] <SignedInfo> [ ] ... [p02] <Reference URI="http://www.w3.org/TR/xml-stylesheet/"> [ ] ... [p03] <Reference URI="#AMadeUpTimeStamp" [p04] Type="http://www.w3.org/2000/09/xmldsig#SignatureProperties"> [p05] <Transforms> [p06] <Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/> [p07] </Transforms> [p08] <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> [p09] <DigestValue>dGhpcyBpcyBub3QgYSBzaWduYXR1cmUK...</DigestValue> [p10] </Reference> [p11] </SignedInfo> [p12] ... [p13] <Object> [p14] <SignatureProperties> [p15] <SignatureProperty Id="AMadeUpTimeStamp" Target="#MySecondSignature"> [p16] <timestamp xmlns="http://www.ietf.org/rfcXXXX.txt"> [p17] <date>19990914</date> [p18] <time>14:34:34:34</time> [p19] </timestamp> [p20] </SignatureProperty> [p21] </SignatureProperties> [p22] </Object> [p23]</Signature>
四、签名详解
XML签名可以对任意形式的资源进行签名,并能实现封装(enveloped)、被封装(enveloping)和分离(detached)签名多种签名方式。
如果XML签名用于对包含该签名的XML文档之外的资源签名,则称为detached signature
如果XML签名用于对包含它的XML文档的某个部分进行签名,则称为enveloped signature;
如果XML签名包含被签名的数据,则称为enveloping signature
区分签名方式,主要看Reference URI的数据,值是外部路径则为分离式,
值是xml的一个标签id且明文放在签名后数据中则为被封装,
值是xml的一个标签id但明文不在签名后数据中则为封装;
SignedInfo元素包含或引用签名后的数据,并指出使用了那种算法
DigestMethod元素指定散列算法。
DigestValue元素包含转换后资源经过散列算法的结果
SignatureValue元素包含一个经过Base64编码的签名结果 - 签名是按照 SignedInfo元素中的SignatureMethod元素中指明的参数进行的,签名前要先根据CanonicalizationMethod元素中指定的算法进行规范化xml格式
KeyInfo元素(可选)允许签名者为接收者提供验签该签名的密钥,通常是以一个或多个X.509数字证书的形式。如果没有出现KeyInfo元素,接收方必须从上下文中识别出验签的密钥。