将 PEM 编码的 X.509 证书加载到 Windows CryptoAPI
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1231178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Load an PEM encoded X.509 certificate into Windows CryptoAPI
提问by Migs
I need to load a PEM encoded X.509 certificate into a Windows Crypto API context to use with C++. They are the ones that have -----BEGIN RSA XXX KEY-----
and -----END RSA XXX KEY-----
. I found examples for Python and .NET but they use specific functions I can't relate to the plain Windows Crypto API.
我需要将 PEM 编码的 X.509 证书加载到 Windows Crypto API 上下文中以与 C++ 一起使用。他们是那些拥有-----BEGIN RSA XXX KEY-----
和 的人 -----END RSA XXX KEY-----
。我找到了 Python 和 .NET 的示例,但它们使用了我无法与普通 Windows Crypto API 相关的特定功能。
I understand how to encrypt/decrypt once I've got a HCRYPTKEY.
BUT, I just don't get how to import the Base64 blob in the .PEM file(s) and get a HCRYPTKEY
that I can use out of it.
一旦我获得了 HCRYPTKEY,我就知道如何加密/解密。但是,我只是不知道如何在 .PEM 文件中导入 Base64 blob 并获得一个HCRYPTKEY
我可以使用的。
I have that strange feeling that there is more to it than simply calling CryptDecodeObject()
.
我有一种奇怪的感觉,它不仅仅是简单地调用CryptDecodeObject()
.
Any pointers that can put me on track? I've already lost two days doing "trial & error" programming and getting nowhere.
任何可以让我走上正轨的指针?我已经浪费了两天时间进行“试错”编程,但一无所获。
回答by rimono
KJKHyperionsaid in his answer:
KJKHyperion在他的回答中说:
I discovered the "magic" sequence of calls to import a RSA public key in PEM format. Here you go:
- decode the key into a binary blob with CryptStringToBinary; pass CRYPT_STRING_BASE64HEADERin dwFlags
- decode the binary key blob into a CERT_PUBLIC_KEY_INFO with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and X509_PUBLIC_KEY_INFOin lpszStructType
- decode the PublicKey blob from the CERT_PUBLIC_KEY_INFO into a RSA key blob with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and RSA_CSP_PUBLICKEYBLOBin lpszStructType
- import the RSA key blob with CryptImportKey
我发现了以 PEM 格式导入 RSA 公钥的“神奇”调用序列。干得好:
- 使用CryptStringToBinary将密钥解码为二进制 blob ;在 dwFlags 中传递CRYPT_STRING_BASE64HEADER
- 使用CryptDecodeObjectEx将二进制密钥 blob 解码为 CERT_PUBLIC_KEY_INFO ;通过 dwCertEncodingType 中的 X509_ASN_ENCODING 和lpszStructType中的 X509_PUBLIC_KEY_INFO
- 使用CryptDecodeObjectEx 将来自 CERT_PUBLIC_KEY_INFO 的 PublicKey blob 解码为 RSA 密钥 blob ;通过 dwCertEncodingType 中的 X509_ASN_ENCODING 和lpszStructType中的 RSA_CSP_PUBLICKEYBLOB
- 使用CryptImportKey导入 RSA 密钥 blob
This sequence really helped me understand what's going on, but it didn't work for me as-is. The second call to CryptDecodeObjectEx
gave me an error:
"ASN.1 bad tag value met".
After many attempts at understanding Microsoft documentation, I finally realized that the output of the fist decode cannot be decoded as ASN again, and that it is actually ready for import. With this understanding I found the answer in the following link:
这个序列确实帮助我了解发生了什么,但它对我来说并不适用。第二次调用给CryptDecodeObjectEx
了我一个错误:“ASN.1 bad tag value met”。经过多次尝试理解微软文档,我终于意识到第一次解码的输出无法再次解码为ASN,并且它实际上已经准备好导入。有了这种理解,我在以下链接中找到了答案:
http://www.ms-news.net/f2748/problem-importing-public-key-4052577.html
http://www.ms-news.net/f2748/problem-importing-public-key-4052577.html
Following is my own program that imports a public key from a .pem file to a CryptApi context:
以下是我自己的程序,它将公钥从 .pem 文件导入到 CryptApi 上下文:
int main()
{
char pemPubKey[2048];
int readLen;
char derPubKey[2048];
size_t derPubKeyLen = 2048;
CERT_PUBLIC_KEY_INFO *publicKeyInfo;
int publicKeyInfoLen;
HANDLE hFile;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
/*
* Read the public key cert from the file
*/
hFile = CreateFileA( "c:\pub.pem", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
fprintf( stderr, "Failed to open file. error: %d\n", GetLastError() );
}
if ( !ReadFile( hFile, pemPubKey, 2048, &readLen, NULL ) )
{
fprintf( stderr, "Failed to read file. error: %d\n", GetLastError() );
}
/*
* Convert from PEM format to DER format - removes header and footer and decodes from base64
*/
if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen, NULL, NULL ) )
{
fprintf( stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError() );
}
/*
* Decode from DER format to CERT_PUBLIC_KEY_INFO
*/
if ( !CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen ) )
{
fprintf( stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError() );
return -1;
}
/*
* Acquire context
*/
if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) )
{
{
printf( "CryptAcquireContext failed - err=0x%x.\n", GetLastError() );
return -1;
}
}
/*
* Import the public key using the context
*/
if ( !CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey ) )
{
fprintf( stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError() );
return -1;
}
LocalFree( publicKeyInfo );
/*
* Now use hKey to encrypt whatever you need.
*/
return 0;
}
回答by KJKHyperion
I discovered the "magic" sequence of calls to import a RSA public key in PEM format. Here you go:
我发现了以 PEM 格式导入 RSA 公钥的“神奇”调用序列。干得好:
- decode the key into a binary blob with CryptStringToBinary; pass CRYPT_STRING_BASE64HEADERin dwFlags
- decode the binary key blob into a CERT_PUBLIC_KEY_INFO with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and X509_PUBLIC_KEY_INFOin lpszStructType
- decode the PublicKey blob from the CERT_PUBLIC_KEY_INFO into a RSA key blob with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and RSA_CSP_PUBLICKEYBLOBin lpszStructType
- import the RSA key blob with CryptImportKey
- 使用CryptStringToBinary将密钥解码为二进制 blob ;在 dwFlags 中传递CRYPT_STRING_BASE64HEADER
- 使用CryptDecodeObjectEx将二进制密钥 blob 解码为 CERT_PUBLIC_KEY_INFO ;通过 dwCertEncodingType 中的 X509_ASN_ENCODING 和lpszStructType中的 X509_PUBLIC_KEY_INFO
- 使用CryptDecodeObjectEx 将来自 CERT_PUBLIC_KEY_INFO 的 PublicKey blob 解码为 RSA 密钥 blob ;通过 dwCertEncodingType 中的 X509_ASN_ENCODING 和lpszStructType中的 RSA_CSP_PUBLICKEYBLOB
- 使用CryptImportKey导入 RSA 密钥 blob
回答by jarmond
I'm currently facing the same difficulty. I haven't finished coding a solution but as I understand it you need to strip off the ----- BEGIN etc ----- and ----- END etc ------ tags and decode the Base64.
我目前面临同样的困难。我还没有完成解决方案的编码,但据我所知,您需要去除 ----- BEGIN 等 ----- 和 ----- END 等 ------ 标签并解码 Base64 .
This leaves you with a DER encoded string, which you need to parse to get the modulus and public exponent. From those you can populate the PUBLICKEYSTRUC and RSAPUBKEY structures. Good luck ;-)
这为您留下了一个 DER 编码的字符串,您需要对其进行解析以获得模数和公共指数。您可以从中填充 PUBLICKEYSTRUC 和 RSAPUBKEY 结构。祝你好运 ;-)