[英]How to canonicalize and digest the Body of SOAP with xmlib2
我正在嘗試手動簽署 SOAP 請求。 在我的 cpp 應用程序中使用 libxml2,我可以使用 xmlC14NDocDumpMemory function 和 xmlNodeSetPtr 作為 null 參數規范化和消化整個 883812976388 soap 文檔。 然而,對於實際簽名,我只需要專門處理 SOAP 的正文。
xmlChar* canon;
int canonLength = xmlC14NDocDumpMemory(
doc,
nullptr,
xmlC14NMode::XML_C14N_EXCLUSIVE_1_0,
nullptr,
1,
&canon
);
std::string canonizedString(reinterpret_cast<const char*>(canon), canonLength);
std::cout << "canonized string:\n" << canonizedString << std::endl;
//freeing the original parsed file:
xmlFreeDoc(doc);
//digesting the value:
const EVP_MD* md = EVP_sha1(); // algorithm
unsigned char digest_value[EVP_MAX_MD_SIZE]; //the digest result value
unsigned int dv_length; //the digest result length
EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); //create msg digest context
EVP_DigestInit_ex(mdctx, md, NULL); // Initialise the context (engine null value?)
EVP_DigestUpdate(mdctx, canon, canonLength); //digesting
EVP_DigestFinal_ex(mdctx, digest_value, &dv_length); //finalizing
EVP_MD_CTX_free(mdctx); //free the context
char* base64convert;
size_t base64convertLength;
base64::Encode(
reinterpret_cast<const char*>(digest_value),
dv_length,
&base64convert,
&base64convertLength);
std::string digest64(base64convert, base64convertLength);
std::cout << "\ndigest value:\n" << digest64;
示例 SOAP:
<?xml version="1.0" encoding="UTF-8"?>
<e:Envelope xmlns:e="http://schemas.xmlsoap.org/soap/envelope/">
<e:Header/>
<e:Body>
<!-- doctor-E,EGN:XXXXXXXXXX -->
<ws:hbIn xmlns:ws="http://pis.technologica.com/ws/">
<ws:egn>XXXXXXXXXX</ws:egn>
<ws:date>2015-06-11</ws:date>
</ws:hbIn>
</e:Body>
</e:Envelope>
符號示例的結果:
<e:Envelope xmlns:e="http://schemas.xmlsoap.org/soap/envelope/">
<e:Header>
<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="#signedContent">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>93BoBU73Y0Efm1rarqzUGw5x4SU=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>jQGU7xsoSVGx/a......</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIICjzCCAfi......</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</e:Header>
<e:Body id="signedContent">
<!-- doctor-E,EGN:XXXXXXXXXX -->
<ws:hbIn xmlns:ws="http://pis.technologica.com/ws/">
<ws:egn>XXXXXXXXXX</ws:egn>
<ws:date>2015-06-11</ws:date>
</ws:hbIn>
</e:Body>
</e:Envelope>
所以問題是如何獲得 93BoBU73Y0Efm1rarqzUGw5x4SU= 值? 我注意到簽名的 soap 正文具有 URI id“signedContent”。 我不確定這個 URI 是在消化之前還是之后插入的(如果之前插入它可能會改變整個 hash)。
我對任何在這里絆倒的人的建議是——不要試圖自己規范化、消化和簽名。 使用 xmlsec。 盡管構建起來很麻煩(我在 Windows 上)並且文檔幾乎不存在,但它完成了工作。 可以在此處找到最終答案: 使用 xmlsec 對 XML 的一部分進行簽名
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.