验证进程外COM服务器客户端是可信的

时间:2014-10-23 13:54:46

标签: c# c++ security com

我有一个进程外的COM服务器暴露了一个我不希望被我不信任的代码调用的方法。

基本上我要做的就是阻止聪明的客户调用这些我需要访问的方法。我认为应该考虑一个不同的解决方案。但由于我不愿意进入的原因,我没有真正的选择。我可以采用不太强大的解决方案,但更愿意尽可能强大。

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

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

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

1 个答案:

答案 0 :(得分:0)

如果有一个开箱即用的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) ;