如何使用Windows CryptoAPI生成SHA256withRSA签名?

时间:2015-03-19 19:56:20

标签: c++ windows cryptoapi

我需要在Windows中使用SHA256withRSA算法(带有SHA-256哈希函数的RSASSA-PKCS1-V1_5-SIGN)签署一些数据,并且我有一些验证错误。我想知道是否有人有尝试这样做的经验。

我正在做的总结:

CryptAcquireContextW with MS_ENH_RSA_AES_PROV and PROV_RSA_AES
CryptImportKey after running CryptStringToBinary on a pem and applying to that CryptDecodeObjectEx with PKCS_RSA_PRIVATE_KEY
CryptCreateHash with CALG_SHA_256
CryptHashData and CryptSignHash using AT_KEYEXCHANGE to use the imported key (AT_SIGNATURE didn't work)

如果您想要详细版本,请点击此处:

创建CSP

WCHAR const container[] = L"ContainerName";
HCRYPTPROV provider;
CryptAcquireContextW(
    &provider,
    container,
    MS_ENH_RSA_AES_PROV,
    PROV_RSA_AES,
    0));

导入我的私钥

char const key_string[] = "-----BEGIN RSA PRIVATE KEY-----"
                          "<base64 encoded key>"
                          "-----END RSA PRIVATE KEY-----";
DWORD key_bytes_size;
BYTE* key_bytes;
CryptStringToBinaryA(
    key_string,
    0,
    CRYPT_STRING_BASE64HEADER,
    nullptr, &key_bytes_size,
    nullptr, nullptr);
key_bytes = new BYTE[key_bytes_size];
CryptStringToBinaryA(
    key_string,
    0,
    CRYPT_STRING_BASE64HEADER,
    key_bytes, &key_bytes_size,
    nullptr, nullptr);

DWORD key_blob_size;
BYTE* key_blob;
CryptDecodeObjectEx(
    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    PKCS_RSA_PRIVATE_KEY,
    key_bytes, key_bytes_size,
    0, nullptr, 
    nullptr, &key_blob_size);
key_blob = new BYTE[key_blob_size];
CryptDecodeObjectEx(
    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    PKCS_RSA_PRIVATE_KEY,
    key_bytes, key_bytes_size,
    0, nullptr, 
    key_blob, &key_blob_size);

HCRYPTKEY key_handle;
CryptImportKey(
    provider,  // The one I created before
    key_blob, key_blob_size, 
    nullptr, 0,
    &key_handle);

(我讨厌API如此冗长,特别是要求长度然后填充缓冲区的两步舞蹈) 完成此操作后,我会哈希并对我的数据进行签名:

char const data[] = "Stuff to sign";
HCRYPTHASH hash_handle;
CryptCreateHash(provider, CALG_SHA_256, 0, 0, &hash_handle);

DWORD data_length = std::strlen(data);
CryptHashData(
    hash_handle,
    reinterpret_cast<const BYTE*>(data), data_length,
    0); 

DWORD signature_size;
BYTE* signature;
CryptSignHash(
    hash_handle,
    AT_KEYEXCHANGE,  // AT_SIGNATURE didn't work
    nullptr, 0,
    nullptr, signature_size);
signature = new BYTE[signature_size];
CryptSignHash(
    hash_handle,
    AT_KEYEXCHANGE,  // AT_SIGNATURE didn't work
    nullptr, 0,
    signature, signature_size);

这会产生我想要的那种签名吗?我应该为AcquireContext调用设置不同的参数吗?

0 个答案:

没有答案