我正在努力使用私钥签署XML soap消息。我以前在Java中已经完成了它,但是通过Python完成它非常困难。我在主目录中保留了一个模板XML,其值填充了“BinarySecurityToken”和“KeyInfo”标记。其中的值是通过SOAP UI使用相同的私钥生成的(因为指向Body标记的URI始终相同)。之后我计算整个Body标签的摘要值,并在“SignedInfo”中的“DigestValue”标签中填充它。现在我正在对此签名信息标记进行封装,并在其上计算“SignatureValue”。但最终,当我将这个Soap XML传递给webservice时,我收到了一条策略faliure消息(因为Signature generaion错误),下面是我的代码:
body = etree.tostring(root.find('.//{http://schemas.xmlsoap.org/soap/envelope/}Body'))
c14n_exc = True
ref_xml = canonicalize(body, c14n_exc)
digest_value = sha1_hash_digest(ref_xml)
#Inserting the digest Value
for soapheader in root.xpath('soapenv:Header/wsse:Security/ds:Signature/ds:SignedInfo/ds:Reference', namespaces=ns):
soaptag = etree.XPathEvaluator(soapheader,namespaces=ns)
soaptag('ds:DigestValue')[0].text = digest_value
signed_info_xml = etree.tostring(root.find('.//{http://www.w3.org/2000/09/xmldsig#}SignedInfo'))
signed_info = canonicalize(signed_info_xml, c14n_exc)
pkey = RSA.load_key("privkeyifind.pem", lambda *args, **kwargs: "nopass")
signature = pkey.sign(hashlib.sha1(signed_info).digest())
signature_value = base64.b64encode(signature)
#Inserting the signature Value
for signedInfo in root.xpath('soapenv:Header/wsse:Security/ds:Signature', namespaces=ns):
signtag = etree.XPathEvaluator(signedInfo,namespaces=ns)
signtag('ds:SignatureValue')[0].text = signature_value
canonReq = canonicalize(etree.tostring(root), c14n_exc)
proc = Popen(["curl", "-k", "-s" ,"--connect-timeout", '3', '--data-binary' , canon2, "https://world-service-dev.intra.aexp.com:4414/worldservice/CLIC/CaseManagementService/V1"], stdout=PIPE, stderr=PIPE)
response, err = proc.communicate()
#######################################################
#Method to generate the digest value of the xml message
#######################################################
def sha1_hash_digest(payload):
"Create a SHA1 hash and return the base64 string"
return base64.b64encode(hashlib.sha1(payload).digest())
#####################################
#Method to canonicalize a request XML
#to remove tabs, line feeds/spaces,
#quoting, attribute ordering and form
#a proper XML
#####################################
def canonicalize(xml, c14n_exc=True):
"Return the canonical (c14n) form of the xml document for hashing"
# UTF8, normalization of line feeds/spaces, quoting, attribute ordering...
output = StringIO()
# use faster libxml2 / lxml canonicalization function if available
et = lxml.etree.parse(StringIO(xml))
et.write_c14n(output, exclusive=c14n_exc)
return output.getvalue()
我只能使用2.6.6的标准Python函数。我无法下载像signxml等消息签名库(由于对环境的限制)。