c++ - gSOAP wsse 插件 - 签署请求的正确程序是什么?
问题描述
我正在使用 gSOAP(2.8.16 - 是的,它很旧)在 RHEL 上开发一个 C++ 客户端,该客户端与需要对消息进行数字签名的服务进行通信。签名基于 wsu:Timestamp 元素。我正在使用带有 RSA 私钥的 X509 (PEM) 证书。客户端是使用生成的
wsdl2h -g -e -o client-pre.h -t$SOAPHOME/WS/WS-typemap.dat -v $WSDL
sed -f add-imports client-pre.h > client.h # adds import statements for WS-Header.h, dom.h, and wsse.h
soapcpp2 -d ../ -A -L _c -w -j -I $SOAPHOME/import -x -n client.h
根据Genevia 文档,以下代码应该足够了(不是实际代码,而是代表它 - 省略错误处理以节省空间):
ServiceSOAPProxy client;
...
soap_register_plugin( client.soap, soap_wsse );
...
soap_ssl_client_context( client.soap, SOAP_SSL_DEFAULT, pemfile, pwd, cafile, NULL, NULL );
_ns__RequestType *req = soap_new__ns__RequestType( cpClient.soap );
// set request parameters
RSA *rsakey = PEM_read_RSAPrivateKey( fp, NULL, NULL, (void *) pwd );
...
X509 *cert = PEM_read_X509( fp, NULL, NULL, NULL );
...
soap_wsse_add_Timestamp( client.soap, timeid.c_str(), duration );
if ( soap_wsse_add_BinarySecurityTokenX509( client.soap, tokid.c_str(), cert ) != SOAP_OK ||
soap_wsse_add_KeyInfo_SecurityTokenReferenceX509( client.soap, ("#" + tokid).c_str()) != SOAP_OK ||
soap_wsse_sign( client.soap, SOAP_SMD_SIGN_RSA_SHA256, rsakey, 0 ) != SOAP_OK ||
soap_wsse_sign_only( client.soap, ("#" + timeid).c_str() ) != SOAP_OK )
{
soap_print_fault( client.soap, ::stderr );
// handle error
}
ns__ResponseType *rsp = soap_new_ns__ResponseType( client.soap );
cpClient.SendRequest( req, rsp );
不幸的是,签名不完整- 没有 SignatureValue,没有 SignedInfo 等,只有 SecurityTokenReference:
<ds:Signature>
<ds:KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="#BST-a9ec4d98-41c0-11e9-961e-0e5b675ed876" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
这些soap_wsse*
方法都没有返回错误,但要么我错过了一个步骤,要么没有正确设置某些东西。Genevia 文档中绝对没有任何内容可以暗示我做错了什么。
我错过了什么步骤?
编辑
事实证明,我为时间戳传递了错误的标签——我使用了带有前导#
( ("#" + time_id).c_str()
) 的引用 URI,这就是为什么没有将任何内容添加到签名中的原因。
当我使用正确的标签 ( time_id.c_str()
) 时,我得到一个段错误 - 不知何故,soap->attributes
被设置为一个错误的值。我在 gdb 会话中的 soap->attributes 成员上设置了一个手表,并得到以下信息:
Old value = (soap_attribute *) 0x0
New value = (soap_attribute *) 0x9bf1a0
0x00000000005f2d49 in soap_set_attr (soap=0x7ffff7fb7010, name=0x7ffff7fd35d0 "xmlns:SOAP-ENV", value=0x9bf131 "http://schemas.xmlsoap.org/soap/envelope/", flag=1) at stdsoap2.cpp:10456
Old value = (soap_attribute *) 0x9bf1a0
New value = (soap_attribute *) 0xa1aaa0
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0xa1aaa0
New value = (soap_attribute *) 0x9eca10
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9eca10
New value = (soap_attribute *) 0x9bf3b0
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9bf3b0
New value = (soap_attribute *) 0x9c4570
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9c4570
New value = (soap_attribute *) 0x9ec740
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9ec740
New value = (soap_attribute *) 0xa1a960
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0xa1a960
New value = (soap_attribute *) 0x9ec690
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9ec690
New value = (soap_attribute *) 0x9b9f30
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9b9f30
New value = (soap_attribute *) 0x9bf300
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x9bf300
New value = (soap_attribute *) 0x0
soap_clr_attr (soap=0x7ffff7fb7010) at stdsoap2.cpp:10510
Old value = (soap_attribute *) 0x0
New value = (soap_attribute *) 0x2000000000000
soap_smd_begin (soap=0x7ffff7fb7010, alg=10, key=0x95b150, keylen=0) at smdevp.c:373
为什么会发生这种情况?
解决方案
推荐阅读
- powershell - 在电子邮件正文中显示图像
- python - 如何使用 Pandas 删除出现在所有行中的行值
- python - 用于将 CSV 转换为 JSON 以与 Auth0 一起使用的 Python 脚本在系统升级后出现问题
- windows - netcat 在批处理文件中将其作为单独的进程运行
- nginx - 无法应用 Nginx 入口控制器
- navigation - 错误类型错误:未定义不是对象(评估'navigation.navigate'
- database - 如何在选择下拉列表时运行数据库内容检查
- javascript - AWS Lambda - 只有在第二次测试触发后才能得到答案
- html - 如何缩进段落,但排除某些行进行格式化?
- javascript - 将内部标签转移到父标签