需要使用 GOST 34.11 算法来计算哈希值。文档中有一个计算示例:
<ds:Reference URI="#id-9a89bcea-eb0d-41f2-a8e8-405ad5ea0d62">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
<ds:DigestValue>STvOHkqaWjQbVCkB7mnG++RLLdGmjryqTqS+BcZx4Cg=</ds:DigestValue>
</ds:Reference>
所引用文件的范围:
<a:To wsu:Id="id-9a89bcea-eb0d-41f2-a8e8-405ad5ea0d62" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">https://ips.test.egisz.rosminzdrav.ru/57234d87b0838</a:To>
我还没有弄清楚要使用什么算法来获取哈希值(2012 年 11 月 34 日或 1994 年 11 月 34 日)。以下是 2012 年 11 月 34 日的代码(pygost 库:https://github.com/ilyaTT/pygost_0_15/tree/master):
from lxml import etree
from pygost.gost3411_12 import GOST341112
import base64
data = '''<a:To wsu:Id="id-9a89bcea-eb0d-41f2-a8e8-405ad5ea0d62" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing">https://ips.test.egisz.rosminzdrav.ru/57234d87b0838</a:To>'''
parser = etree.XMLParser(remove_blank_text=True)
xml_tree = etree.fromstring(data.encode("utf-8"), parser)
canonical_xml = etree.tostring(xml_tree, method="c14n", exclusive=True).decode("utf-8")
canonical_base64 = base64.b64encode(canonical_xml.encode("utf-8")).decode("utf-8")
data_bytes = canonical_base64.encode("utf-8")[::-1]
# Хэшируем
gost_hash = GOST341112(digest_size=256)
gost_hash.update(data_bytes)
signature_hash = gost_hash.digest()[::-1]
# Хэш в шестнадцатеричной строке
hex_string = signature_hash.hex()
print("HEX:", hex_string)
new_value = base64.b64encode(signature_hash).decode()
print("BASE64:", new_value)
程序中获得的哈希值与样本中的哈希值不匹配。
GOST 34.11-1994 的实施:
from lxml import etree
from pygost.gost3411_94 import GOST341194
import base64
# Исходный XML-документ
xml_data = '''<a:To wsu:Id="id-9a89bcea-eb0d-41f2-a8e8-405ad5ea0d62" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">https://ips.test.egisz.rosminzdrav.ru/57234d87b0838</a:To>'''
root = etree.fromstring(xml_data)
# Канонизируем (c14n)
data_to_hash = etree.tostring(root, method="c14n", exclusive=True, with_comments=False)
print(type(data_to_hash))
print(data_to_hash)
# Вычисляем хэш (ГОСТ Р 34.11-94)
gost_hash = GOST341194(data_to_hash)
digest_value = gost_hash.digest()
digest_base64 = base64.b64encode(digest_value).decode()
print("DigestValue:", digest_base64)
得到了哈希:“ost9NriBuOVw2DKHUiKThCpIVkk2HITA0v6cMWv16mU=”但它应该是:“STvOHkqaWjQbVCkB7mnG++RLLdGmjryqTqS+BcZx4Cg=”