2011-09-27 136 views
2

如何获得Microsoft的CryptoAPI CryptImportKey函数以导入PEM编码密钥?它实际上工作,但CryptDecrypt返回一个错误。如何将CAPI的CryptImportKey与来自OpenSSL的PEM编码公钥一起使用?

// 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 | [email protected] | 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 
+2

我想你使用的是错误的API。 RSA_sign()签名一个散列;使用CryptVerifySignature()来验证它。 – Luke

+0

卢克,我认为你是对的......它工作。让我再做一些测试。我无法相信我浪费了几天的时间! – pcunite

回答

2

您使用的是错误的API。 RSA_sign()签署散列;使用CryptVerifySignature()来验证它。

相关问题