【问题标题】:How to use CAPI's CryptImportKey with PEM encode public key from OpenSSL?如何使用 CAPI 的 CryptImportKey 和 PEM 编码来自 OpenSSL 的公钥?
【发布时间】:2011-09-27 18:12:18
【问题描述】:

如何让 Microsoft 的 CryptoAPI CryptImportKey 函数导入 PEM 编码的密钥?它确实有效,但 CryptDecrypt 返回错误。

// 1. Generate a Public/Private RSA key pair like so:

openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -out public.pem -outform PEM -pubout

// 2. Create a digital signaure using OpenSSL

// Load Private key
//  -----BEGIN RSA PRIVATE KEY-----
//  BLAHBLAHBLAH
//  -----END RSA PRIVATE KEY-----

// Concat user details
std::string sUser = "John Doe | Business | john@na.com | 1316790394 | 0 | 1 | ProductName | 1";

// Get a one-way hash of it.
SHA1((const unsigned char *) sUser.c_str(),sUser.size(), hash);

// Create the digital signature ~ PKCS #1 v2.0 format (also known as OAEP encryption)
RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, pbData, &iDataLen, rsa_key);

// 3. Verify the signature using Windows CryptoAPI

// Load Public key
//  -----BEGIN PUBLIC KEY-----
//  BLAHBLAHBLAH
//  -----END PUBLIC KEY-----

// Convert from PEM format to DER format - removes header and footer and decodes from base64
CryptStringToBinaryA((char*)pbPublicPEM, iPEMSize, CRYPT_STRING_ANY, pbPublicDER, &iDERSize, NULL, NULL);

// Decode from DER format to CERT_PUBLIC_KEY_INFO. This has the public key in ASN.1 encoded
// format called "SubjectPublicKeyInfo" ... szOID_RSA_RSA
// Do I need to get the "public key" and "modulus" from this format and build a PUBLICKEYBLOB manually?
CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbPublicDER, iDERSize, CRYPT_ENCODE_ALLOC_FLAG, NULL, &pbPublicPBLOB, &iPBLOBSize );

// decode the RSA Public key itself to a PUBLICKEYBLOB ?
CryptDecodeObjectEx( X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pbPublicPBLOB->PublicKey.pbData, pbPublicPBLOB->PublicKey.cbData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &pbPKEY, &iPKEYSize );

// Get a context
CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);

// load the key
CryptImportKey(hCryptProv, pbPKEY, iPKEYSize, 0, CRYPT_OAEP, &hKey);

// Verify the signature
CryptDecrypt(hKey, 0, TRUE, 0, pbData, &iDataLen);

// CryptDecrypt returns NTE_NO_KEY -2146893811 0x8009000D

【问题讨论】:

  • 我认为您使用了错误的 API。 RSA_sign() 对哈希进行签名;使用 CryptVerifySignature() 来验证它。
  • 卢克,我认为你是对的......它正在工作。让我再做一些测试。我不敢相信我浪费了几天时间!

标签: c++ openssl cryptography pem mscapi


【解决方案1】:

您使用了错误的 API。 RSA_sign() 对哈希进行签名;使用CryptVerifySignature()进行验证。

【讨论】:

  • 你有使用 CryptVerifySignature() 的示例吗?我也在尝试,但失败了。
猜你喜欢
  • 1970-01-01
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 2019-06-13
相关资源
最近更新 更多