在我正在尝试使用的SOAP Web服务中,需要发送一个类似于此结构的XML:
<?xml version="1.0"?>
<TheData>
<Father Id="zzz">
<SomeInfo>1</SomeInfo>
<List>
<ElementOfList>
<Child Id="foo">foo</Child>
<Signature>
...
</Signature>
</ElementOfList>
<ElementOfList>
<Child Id="bar">bar</Child>
<Signature>
...
</Signature>
</ElementOfList>
</List>
</Father>
<Signature>
...
</Signature>
</TheData>
其中<Signature>
包含以下内容:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#[the _Id_ attr of this Signature's sibling element]">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>uCMzpgMnLCP9iESFQVgpmtQ5TRE=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>...</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>...</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
我该怎么做?
我正在尝试xmlsec1 --id-attr:Id Father --id-attr:Id Child
,将Signature
字段空白的文件传递给它,但它只会填充第一个字段。
我也试过单独签名孩子,把它放在父模板中并试图签下父亲,但xmlsec1
忽略了第二个元素(并改变了第一个签名的值 - 不是吗应该封装在其元素中?)。
我宁愿在Python代码中执行此操作,但我尝试使用的三个库python-xmlsec,pyxmlsec和xmldsig都无法生成/重新构建{{1 } {at} URI
。可能是因为他们缺少<Reference>
的{{1}},但是我得到的这些问题表明我并不真正理解这种XML签名的东西,因此,我正在做的事情错了,搞砸了。请帮我理解。
我似乎有很多人在这些XML签名主题中遇到困难,但他们都没有试图在同一个XML文件中签署两个不同的元素。这个案例也没有列在w3C Scenarios FAQ,这使得一切看起来都很奇怪,因为我的网络服务要求我有多个签名。或者不是吗?以下是他们发布的架构:https://github.com/proge/PyNFSe/blob/master/pysped_nfse/nfse.xsd#L539(请参阅此元素--id-attr
和孩子们)。
答案 0 :(得分:1)
我认为没有方法可以使用第三方库,大多数应用程序只需要所有XML内容的签名,而不是特定元素。
也许,这会对你有所帮助:
根据XSD相对于“RecepcionarLoteRps”方法
<s:element name="RecepcionarLoteRps">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="EnviarLoteRpsEnvio" type="tns:EnviarLoteRpsEnvio"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="EnviarLoteRpsEnvio">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="LoteRps" type="tns:tcLoteRps"/>
<s:element minOccurs="0" maxOccurs="1" name="Signature" type="s1:SignatureType"/>
</s:sequence>
</s:complexType>
<s:complexType name="tcLoteRps">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="NumeroLote" type="s:unsignedLong"/>
<s:element minOccurs="0" maxOccurs="1" name="Cnpj" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="InscricaoMunicipal" type="s:string"/>
<s:element minOccurs="1" maxOccurs="1" name="QuantidadeRps" type="s:int"/>
<s:element minOccurs="0" maxOccurs="1" name="ListaRps" type="tns:ArrayOfRps"/>
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfRps">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="Rps" nillable="true" type="tns:Rps"/>
</s:sequence>
</s:complexType>
<s:complexType name="Rps">
<s:complexContent mixed="false">
<s:extension base="tns:tcRps"/>
</s:complexContent>
</s:complexType>
<s:complexType name="tcRps">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="InfRps" type="tns:tcInfRps"/>
<s:element minOccurs="0" maxOccurs="1" name="Signature" type="s1:SignatureType"/>
</s:sequence>
</s:complexType>
您需要在“LoteRps”内的“ListaRps”上签署每个“Rps”,最后签署“LoteRps”元素。
当您逐步生成XML时,可以生成带有所有“Rps”的“ListaRps”元素,并在获取所有“InfRps”元素并对其进行全部签名后,或者您可以立即签署“InfRps”后执行此操作创建并添加到“ListaRps”,最后你应该签署“LoteRps”。
也许你也可以这样做生成完整的XML并在解析之后获取元素并使用适当的顺序逐个签名。
无论如何,您必须编码以根据需要对XML进行签名。
看一下使用Java和JAX-WS开发的assembla nfseWsClient,但这是一个很好的初始点。
这两个课程对你来说很有意义