Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CryptDecryptMessage在LSA下运行的服务内部执行时返回CRYPT_E_NO_DECRYPT_CERT_C_Windows_Service_Certificate_Cryptoapi - Fatal编程技术网

CryptDecryptMessage在LSA下运行的服务内部执行时返回CRYPT_E_NO_DECRYPT_CERT

CryptDecryptMessage在LSA下运行的服务内部执行时返回CRYPT_E_NO_DECRYPT_CERT,c,windows,service,certificate,cryptoapi,C,Windows,Service,Certificate,Cryptoapi,我在LocalMachine/My store中创建了一个带有私钥的RSA证书 然后,我用C创建了一个简单的Windows控制台应用程序: 通过指纹找到证书 使用CryptEncryptMessage 将缓冲区写入文件 然后我用C编写了一个小型服务应用程序: 读取缓冲区 使用CryptDecryptMessage进行解密 只要服务应用程序不是在本地系统帐户(LSA)下运行,一切正常。在这种情况下,CryptDecryptMessage生成CRYPT\u E\u NO\u DECRYPT\

我在LocalMachine/My store中创建了一个带有私钥的RSA证书

然后,我用C创建了一个简单的Windows控制台应用程序:

  • 通过指纹找到证书
  • 使用
    CryptEncryptMessage
  • 将缓冲区写入文件
然后我用C编写了一个小型服务应用程序:

  • 读取缓冲区
  • 使用
    CryptDecryptMessage进行解密
只要服务应用程序不是在本地系统帐户(LSA)下运行,一切正常。在这种情况下,
CryptDecryptMessage
生成
CRYPT\u E\u NO\u DECRYPT\u CERT(0x8009200C)
。尽管证书位于LocalMachine/My中,但仍然存在这种情况

我试着尽可能地去除代码,但它仍然相当长。我希望有一些旗帜设置我是错误的。或者这是预期的行为?谢谢你看

Windows控制台应用程序 Windows服务应用程序
在调用
CryptAcquireContext
时,您将pszContainer用作
NULL
——因此使用默认密钥容器名称。但这在用户和服务之间是不同的。你需要使用具体的名字。不,谢谢你的建议。您的意思是选择任何唯一的容器名称?我在[(上下文)上读了这些评论但是我不清楚它应该被设置为什么。但是你可以通过
CertGetCertificateContextProperty
CertKey\u PROV\u INFO\u PROP\u ID
从Certificate获取
CRYPT\u KEY\u PROV\u INFO\u INFO
并使用pwszContainerName、pwszProvName、dwProvType真的你根本不需要调用
CryptAcquireContext
在加密中
EncryptParams.hCryptProv
-此成员未使用,应设置为NULL。在decrypt中-调用
CertOpenSystemStore(hCryptProv,cStore)时出错;
但您需要打开与encrypt-
CertOpenStore(CERT\u store\u PROV\u SYSTEM,X509\u ASN\u编码,0,CERT\u SYSTEM\u store\u LOCAL\u MACHINE,L“MY”)中相同的存储
和代码将更加简单。您可以在调用中使用类似的内容
CryptAcquireContext
您使用pszContainer作为
NULL
-因此使用默认密钥容器名称。但这在用户和服务之间是不同的。您需要使用具体的名称。这里不是0谢谢您的建议。您的意思是选择任何唯一的容器我?我读了[(上下文)上的评论但是我不清楚它应该被设置为什么。但是你可以通过
CertGetCertificateContextProperty
CertKey\u PROV\u INFO\u PROP\u ID
从Certificate获取
CRYPT\u KEY\u PROV\u INFO\u INFO
并使用pwszContainerName、pwszProvName、dwProvType真的你根本不需要调用
CryptAcquireContext
在加密中
EncryptParams.hCryptProv
-此成员未使用,应设置为NULL。在decrypt中-调用
CertOpenSystemStore(hCryptProv,cStore)时出错;
但您需要打开与encrypt-
CertOpenStore(CERT\u store\u PROV\u SYSTEM,X509\u ASN\u编码,0,CERT\u SYSTEM\u store\u LOCAL\u MACHINE,L“MY”)中相同的存储
而且代码会简单得多你可以
int __cdecl main(int argc, CHAR* argv[])
{
    HCERTSTORE hSysStore = NULL;
    DWORD err;
    PCHAR    certThumbprint   = "14FE20556FC106DA4C561707ABDFEACEB8CAAC98";
    PCERT_CONTEXT pContext = NULL;
    BYTE*    pbEncryptedBlob = NULL;
    DWORD    cbEncryptedBlob;
    BYTE bPlain[255] = {0};
    DWORD cbContent;
    strcpy_s(bPlain, sizeof(bPlain)-1, argv[1]);
    cbContent = strlen(bPlain)+1;
    err = myGetCertFromThumb(CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY", certThumbprint, &hSysStore, &pContext);
    if (err != 0)
        goto cleanup;
    pbEncryptedBlob = malloc(BUF_SZ);
    cbEncryptedBlob = BUF_SZ;
    /**** code below ****/
    err = myEncryptMsg(pContext, bPlain, cbContent, pbEncryptedBlob, &cbEncryptedBlob);
    if (err != 0)
        goto cleanup;
    printf("Encrypted msg size=%d\n", cbEncryptedBlob);

    /****  write cbEncryptedBlob to file  ****/

cleanup:
    if (pbEncryptedBlob)
        free(pbEncryptedBlob);
    if (pContext)
        CertFreeCertificateContext(pContext);
    if (hSysStore != NULL)
        CertCloseStore(hSysStore, CERT_CLOSE_STORE_CHECK_FLAG);
    return(err);
}

DWORD myEncryptMsg(PCERT_CONTEXT pContext, BYTE* pbPlain, DWORD cbPlainszsz, BYTE* pbCipher, DWORD *pcbCiphersz)
{
    BOOL rc;
    DWORD err;
    PCCERT_CONTEXT RecipientCertArray[1];
    DWORD EncryptAlgSize;
    HCRYPTPROV hCryptProv;
    CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
    CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
    DWORD EncryptParamsSize;
    rc = CryptAcquireContext(
        &hCryptProv,        // Address for handle to be returned.
        NULL,               // Use the current user's logon name.
        NULL,               // Use the default provider.
        PROV_RSA_FULL,      // Need to both encrypt and sign.
        0);              // No flags needed.
    if (rc) 
        goto keyset_exists;
    err = GetLastError();
    if (err != NTE_BAD_KEYSET)
        goto cleanup;
    rc = CryptAcquireContext(
        &hCryptProv,        // Address for handle to be returned.
        NULL,               // Use the current user's logon name.
        NULL,               // Use the default provider.
        PROV_RSA_AES,      // Need to both encrypt and sign.
        CRYPT_NEWKEYSET);              // No flags needed.
    if (!rc) 
    {
        err = GetLastError();
        goto cleanup;
    }
keyset_exists:
    RecipientCertArray[0] = pContext;
    EncryptAlgSize = sizeof(EncryptAlgorithm);
    memset(&EncryptAlgorithm, 0, EncryptAlgSize);
    EncryptAlgorithm.pszObjId = szOID_NIST_AES256_CBC;
    EncryptParamsSize = sizeof(EncryptParams);
    memset(&EncryptParams, 0, EncryptParamsSize);
    EncryptParams.cbSize =  EncryptParamsSize;
    EncryptParams.dwMsgEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING);
    EncryptParams.hCryptProv = hCryptProv;
    EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;
    rc = CryptEncryptMessage(
        &EncryptParams,
        1,
        RecipientCertArray,
        pbPlain,
        cbPlainszsz,
        pbCipher,
        pcbCiphersz);
    if (!rc)
    {
        err = GetLastError();
        goto cleanup;
    }
    err = 0;
cleanup:
    if(hCryptProv)
        CryptReleaseContext(hCryptProv,0);
    return(err);
}
BYTE * someRoutineInsideService()
{
    DWORD err;
    BYTE*    pbEncryptedBlob = NULL;
    DWORD    cbEncryptedBlob;
    BYTE* pbDecryptedMessage = NULL;
    DWORD cbDecryptedMessage;
    pbEncryptedBlob = malloc(BUF_SZ);
    cbEncryptedBlob = BUF_SZ;

    /**** read pbEncryptedBlob from file ****/

    pbDecryptedMessage = malloc(BUF_SZ);
    cbDecryptedMessage = BUF_SZ;
    /**** code below ****/
    err = myDecryptMessage("MY", pbEncryptedBlob, cbEncryptedBlob, pbDecryptedMessage, &cbDecryptedMessage);
    if (err != 0)
        goto cleanup;
cleanup:
    if (pbEncryptedBlob)
        free(pbEncryptedBlob);
    return(pbDecryptedMessage);
}

DWORD myDecryptMessage(LPSTR cStore, BYTE *pbEncryptedBlob, DWORD cbEncryptedBlob, BYTE *pbDecryptedMessage, DWORD *cbDecryptedMessage)
{
    HCERTSTORE CertStoreArray[1];
    CRYPT_DECRYPT_MESSAGE_PARA  DecryptParams;
    DWORD  DecryptParamsSize = sizeof(DecryptParams);
    HCRYPTPROV hCryptProv = 0;                      // CSP handle
    HCERTSTORE hStoreHandle = 0;
    DWORD err = 0;
    BOOL rc;
    rc = CryptAcquireContext(
        &hCryptProv,        // Address for handle to be returned.
        NULL,               // Use the current user's logon name.
        NULL,               // Use the default provider.
        PROV_RSA_FULL,      // Need to both encrypt and sign.
        0);              // No flags needed.
    if (!rc)
    {
        err = GetLastError();
        goto cleanup;
    }
    hStoreHandle = CertOpenSystemStore(hCryptProv, cStore);
    if (hStoreHandle == NULL)
    {
        err = GetLastError();
        goto cleanup;
    }
    CertStoreArray[0] = hStoreHandle;
    memset(&DecryptParams, 0, DecryptParamsSize);
    DecryptParams.cbSize = DecryptParamsSize;
    DecryptParams.dwMsgAndCertEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING);
    DecryptParams.cCertStore = 1;
    DecryptParams.rghCertStore = CertStoreArray;
    rc = CryptDecryptMessage(
              &DecryptParams,
              pbEncryptedBlob,
              cbEncryptedBlob,
              pbDecryptedMessage,
              cbDecryptedMessage,
              NULL);
    if (!rc)
    {
        err = GetLastError();    
        /**** returns 0x8009200C (CRYPT_E_NO_DECRYPT_CERT) if service run under LSA ****/
        goto cleanup;
    }
cleanup:
    if(hCryptProv)
        rc = CryptReleaseContext(hCryptProv,0);
    return(err);
}