验证进程外的COM服务器客户端是否受信任

本文关键字:客户端 是否 信任 服务器 COM 进程 验证 | 更新日期: 2023-09-27 18:27:38

我有一个进程外COM服务器,它公开了一个我不想被我不信任的代码调用的方法。

基本上,我想做的是防止聪明的客户调用我也需要访问的这些方法。我尊重应该一起考虑一个不同的解决方案。但由于我不愿参与的原因,我真的没有这个选择。我可以选择不太健壮的解决方案,但更希望尽可能健壮。

我有能力更改客户端和服务器代码。服务器是用C++编写的,客户端是用C#编写的。

保护这些电话的最佳方法是什么?

我认为这样的问题对于进程间通信或远程过程调用来说并不罕见。所以我希望有一个可以接受的行业最佳实践,甚至可能是一个直接的COM解决方案。在没有这样的情况下,我倾向于从参数中获取下划线数据,并将这些数据片段作为字符串,使用另一段数据中的密钥进行加密,然后将其传递给服务器进行验证。

验证进程外的COM服务器客户端是否受信任

如果有现成的COM解决方案或最佳实践,我没有找到。我发现一种常见的技术是使用散列密钥。客户端生成一个密钥并将其传递给服务器。服务器生成相同的密钥,如果与客户端的密钥不匹配,则拒绝调用。

我的散列密钥是基于从API正在操作的底层数据中提取的一些秘密。由于每次使用我的数据都不一样,所以密钥每次都不一样。双方都可以在调用之前访问底层数据,因此可以生成相同的密钥。我选择base64编码我的,只是因为我更喜欢将NULL终止字符数组而不是字节数组传递给服务器。

LPCSTR      lpszSomeSecret  = "Some Secret To Be Hashed" ;
std::string strEncodedHash  ; // the resulting hash. 
HCRYPTPROV  hProv           = NULL ;
HCRYPTHASH  hHash           = NULL ;
DWORD       cbSomeSecret    = (DWORD)::strlen(lpszSomeSecret) ;
BYTE*       pbHash          = NULL ;
DWORD       cbHash          = 0 ;
DWORD       cbHashSize      = (DWORD)sizeof(cbHash) ;
LPSTR       pchEncodedHash  = NULL ;
int         cbEncodedHash   = 0 ;
HRESULT hResult = S_OK ;
if (!::CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
    hResult = ::AtlHresultFromLastError() ;
} else if (!::CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
    hResult = ::AtlHresultFromLastError() ;
} else if (!::CryptHashData(hHash, (BYTE*)lpszSomeSecret, cbSomeSecret, 0)) {
    hResult = ::AtlHresultFromLastError() ;
} else if (!::CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&cbHash, &cbHashSize, 0)) {
    hResult = ::AtlHresultFromLastError() ;
} else if ((pbHash = (BYTE*)::malloc(cbHash)) == NULL) {
    hResult = E_OUTOFMEMORY ;
} else if (!::CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &cbHash, 0)) {
    hResult = ::AtlHresultFromLastError() ;
} else if ((pchEncodedHash = (LPSTR)::malloc(
            (cbEncodedHash = ::Base64EncodeGetRequiredLength(cbHash, ATL_BASE64_FLAG_NOPAD | ATL_BASE64_FLAG_NOCRLF))
            )) == NULL) {
    hResult = E_OUTOFMEMORY ;
} else if (!::Base64Encode(pbHash, cbHash, pchEncodedHash, &cbEncodedHash, ATL_BASE64_FLAG_NOPAD | ATL_BASE64_FLAG_NOCRLF)) {
    hResult = E_FAIL ;
} else {
    strEncodedHash.assign(pchEncodedHash, cbEncodedHash) ;
}
if (pchEncodedHash) ::free(pchEncodedHash) ;
if (pbHash)         ::free(pbHash) ;
if (hProv)          ::CryptReleaseContext(hProv, 0) ;
if (hHash)          ::CryptDestroyHash(hHash) ;