KJKHyperion在他的答案中提到:
我发现了一组导入PEM格式RSA公钥的"神奇"调用序列。如下所示:
- 使用CryptStringToBinary将密钥解码为二进制数据块;在dwFlags参数中传递CRYPT_STRING_BASE64HEADER
- 使用CryptDecodeObjectEx将二进制密钥块解码为CERT_PUBLIC_KEY_INFO对象;在dwCertEncodingType参数中传递X509_ASN_ENCODING,lpszStructType参数中传递X509_PUBLIC_KEY_INFO
- 使用CryptDecodeObjectEx将CERT_PUBLIC_KEY_INFO对象中的PublicKey块解码为RSA密钥块;在dwCertEncodingType参数中传递X509_ASN_ENCODING,lpszStructType参数中传递RSA_CSP_PUBLICKEYBLOB
- 使用CryptImportKey导入RSA密钥块
这个步骤确实有助于我理解正在进行的操作,但它并不能直接用于我的情况。第二次调用CryptDecodeObjectEx
时出现了错误:"ASN.1 bad tag value met"。在多次尝试理解Microsoft文档后,我终于意识到第一次解码的输出不能再次被ASN解码,并且它实际上已经准备好进行导入。有了这个理解,我在以下链接中找到了答案:
http://www.ms-news.net/f2748/problem-importing-public-key-4052577.html
下面是我的程序,它将从.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;
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() );
}
if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen, NULL, NULL ) )
{
fprintf( stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError() );
}
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;
}
if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) )
{
{
printf( "CryptAcquireContext failed - err=0x%x.\n", GetLastError() );
return -1;
}
}
if ( !CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey ) )
{
fprintf( stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError() );
return -1;
}
LocalFree( publicKeyInfo );
return 0;
}