-->

Error with CryptDecrypt winapi function?

2019-08-17 01:34发布

问题:

i have write simple program to load a public key generated by openssl to decrypt a string encrypted by private key of the public key. But I don't know why I fail at

b = CryptDecrypt(hKey,NULL,FALSE,0,pbEncrypt,&cbEncrypt);

And i get error "8009000D NTE_NO_KEY Key does not exist.". Can someone explain this to me ?

void DecodeString() 
{

    CHAR* publicKey = 
        "-----BEGIN PUBLIC KEY-----"
        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+yyzdZaqcE7qOOZ8pyN"
        "o1n3PS2U/ewT2gGSQeixP+VixQGrxnssT3zlbeUND8CVX+tZGwkcIZZD09Rkx9vh"
        "z7vLUFD7dngupo/aL6pfehb95citD31DUswc9BTJjQySpSSG6zWDSBJMELDYaCa4"
        "MIU7odoCg2EbQBwRWX7upWiR+shyxnPYklY8ZUpVCtIdHXmPO5eMaI1elftqNw1N"
        "n/Id4pFFif11Lmny3s3ADfItuyMfTwU6jwgsPaoqrX5FCnurlAVl/mcfpMVpsPju"
        "XWw2IlvZP5SkTW4G6V+Bt+xDI6SW3dvMi6gJngHLUKekbhZxcFWuv3hus8ojpo+I"
        "mwIDAQAB"
        "-----END PUBLIC KEY-----";

    BYTE* derPubKey;
    DWORD derPubKeyLen;
    BOOL b = CryptStringToBinaryA(publicKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &derPubKeyLen, NULL, NULL);
    DWORD error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    derPubKey = new BYTE[derPubKeyLen];
    b = CryptStringToBinaryA(publicKey, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen, NULL, NULL);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    CERT_PUBLIC_KEY_INFO *publicKeyInfo;
    DWORD publicKeyInfoLen;
    HCRYPTPROV hProv = 0;
    HCRYPTKEY hKey = 0;
    b = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen, CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    b = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    b = CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    //same test decrypt
    CHAR* sameTest = "nJZ6MN6MIrpbLQiRvfLFIHHzneQBe2rucaKSykXeHgf8Zth5FNPZPdiPhWcHq0/K"
        "KgRHv2ON+gPyFbjsdDl2cixPgNGXs1FfI/RvkH+Icn+6rYq5uPBM5oQVriyiWI9/"
        "QiC56LP0ooouqLg9e2U5zJmC/ftCODkFyL748Fx3godXzDl1mNB7bx/Ua6Z93KeB"
        "OgNvYZH3tcZZYlgoX4GVf4ocO0aZ8pQjEB8p9hMWfIDRCIckDAncy21tHDmWDqZ4"
        "H7CZjbdNyaiWe5Cr6+CYs25+r3AdIlXOKWuphgbckKDHh4r7nMX0AX+iHXGjCgkM"
        "iwi4yz7wF+Ow/CcGHkAMTQ==";

    BYTE* pbEncrypt = 0;
    DWORD cbEncrypt = 0;
    b = CryptStringToBinaryA(sameTest, 0, CRYPT_STRING_BASE64, NULL, &cbEncrypt, NULL, NULL);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    pbEncrypt = new BYTE[cbEncrypt];
    printf("%s\n",(CHAR*)pbEncrypt);
    b = CryptStringToBinaryA(sameTest, 0, CRYPT_STRING_BASE64, pbEncrypt, &cbEncrypt, NULL, NULL);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    printf("%s\n",(CHAR*)pbEncrypt);
    b = CryptDecrypt(hKey,NULL,FALSE,0,pbEncrypt,&cbEncrypt);
    error = GetLastError();
    _ASSERT(error == 0);
    _ASSERT(b == TRUE);
    printf("%s\n",(CHAR*)pbEncrypt);
}

回答1:

You can't use the public key to decrypt something encrypted with the private key. The public key is used only for encryption, while the private key can be used only for decryption.

From Wikipedia:

[...] The distinguishing technique used in public-key cryptography is the use of asymmetric key algorithms, where the key used to encrypt a message is not the same as the key used to decrypt it. Each user has a pair of cryptographic keys - a public encryption key and a private decryption key. The publicly available encrypting-key is widely distributed, while the private decrypting-key is known only to the recipient. Messages are encrypted with the recipient's public key, and can be decrypted only with the corresponding private key.[...]



标签: c++ cryptoapi