0
我面臨着Microsoft CrypoAPI和OpenSSL之間的不兼容問題,我無法解決它。OpenSSL和MS CryptoAPI兼容性問題
我想RSA使用CAPI使用公鑰加密郵件,然後使用OpenSSL(使用私鑰)解密,但沒有運氣。
我做的步驟如下:
- 生成使用OpenSSL公鑰/私鑰對PEM格式。
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
- 然後在CAPI,我導入生成的密鑰是這樣的: dsadsa
const char* szPemPrivKey =
"-----BEGIN RSA PRIVATE KEY-----"
"MIIEpAIBAAKCAQEAvUT7PaQzzhSmyQKrnroWCk2tdy9O1BR6bINObhGXoDfK4tnU"
"qgpr0MbM8VjCvpgNjJT8m5RZkvSxcmaWZZQnXxr/SESnrmwk6CcRAvEk45M3LTix"
"N0TTUZzQdBbG9z0bgx1a1P866S87MOf6wbb9yUfV79N7J+xZRQC8mnRtvmzjRZ3W"
"MOcBZ8n1C106gOq//SwvB28mGWTpJ+opASv3mkxTydiDd5v7/yq2Lx4NrvJN+1E4"
"nOX6PLiTECFcvNYzZe9KDuJ5CJv45ifRUo9m5ebo759lKpL1X69ptG7RpHEYULYY"
"urwEGExC1jp/Nbft0zOehsF4wwFqwQVQ34m5LQIDAQABAoIBAD6dQISu+th1aovb"
"T01ugHYeJoHka66rq6iUc/Dj7wZ5DqynpbwvQGXMLua1F5AYG3tjmoIZvNxqCP4w"
"xBaMwc2rz8JnvBVu/3Kx4eXYQvzqqflS5QXExigcubV+B4qpc52Xq4IFgca88lcG"
"l6VYVXMuSa9Shk652PqD+OEcHWY+aygXETLGEAlO88iWe2LbzrD9I1faW8Mrj+wi"
"b9mVhZbjbrI+w9O7cfde4d9Lo4wzGrrunRa0THKUyfwJGtTJ3eP2jCWlE1ij3Xmy"
"c/Mf8U8RlMU8N/Ys77WtCXUA3DK0ge8HSITqvD1NHSyuPM0XqinTkRSg0Ri/tWo+"
"1C6gKJ0CgYEA9K9snRlfuQshwfyR40npJ8r5X9YApjfK8PrxsmdpOi8tpDyi5I66"
"fmnUsbV0ikM+9U898myUAF3SxZIZfw+LYI3ofdstnv6wc9+c9jP9wbGxSryiBurW"
"d3uPuemee7+CxTVEwI0PEAVerRSP+m6MZ/F+SRkQjyLmBXu7soxaspMCgYEAxgWL"
"/wkz6WCf37+9TUHO0MG7vOQ2sI7Bc+82dAa9fsxLwpncmkNxEv+hK3k7Jlr2J4pZ"
"SveRhcq3Ohm2aDRi5CfgQaZO4bGDop7ZYWZuW/MakZdCf8olWCifXEPWcxBo8FGW"
"9/3XEbXkW481HDrX4wyn2b3ptdSqMcdDMKmifT8CgYEA6vtVWYG2teSE5OED0b13"
"VinNV0YTlY1bLhYw6134ZlJMiL9ayBhx7VkBVDCo3Oc7nSYenaO8dqWj9u0Z4zYw"
"aeeecM9+foSlPIJxINhJSCy30Mha6j24/UICg05iTwFaOr2vayOMZZxikeF/a8ei"
"u2fmGZkil/Ox524ukYfMylUCgYAiFTJTYzIcKRVbXZUnhvwh0jaN/HmtSeTiH3ov"
"3jkfaepgRDtEEfeUXYtQAD2+DEnx5E4aKSJS9OE0jthmdx3OR07B/e31yqfthYnE"
"yeyUxvL7vB0mAZUL53IGX2a5x0lIk8J4TKiH09bKK4von/gojDUXtShUs5XXm4Rl"
"C8174QKBgQDbRGyg3VCwo3p0sdqm5UlCL0pc36T5bBUfkVGpJdBZxbIx283CvY35"
"OGqcYdiANMn+alg9IDXfuaFYgg1QTQSkF74CMi+gY7Z8n2OKsjF0cR8VkIYoI9BL"
"iDXvlWs2QVsv+1CIYmZdI8nkExirzRvBD75ZqNdGSWkrfuYnr/bpHg=="
"-----END RSA PRIVATE KEY-----";
const char* szPemPubKey =
"-----BEGIN PUBLIC KEY-----"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvUT7PaQzzhSmyQKrnroW"
"Ck2tdy9O1BR6bINObhGXoDfK4tnUqgpr0MbM8VjCvpgNjJT8m5RZkvSxcmaWZZQn"
"Xxr/SESnrmwk6CcRAvEk45M3LTixN0TTUZzQdBbG9z0bgx1a1P866S87MOf6wbb9"
"yUfV79N7J+xZRQC8mnRtvmzjRZ3WMOcBZ8n1C106gOq//SwvB28mGWTpJ+opASv3"
"mkxTydiDd5v7/yq2Lx4NrvJN+1E4nOX6PLiTECFcvNYzZe9KDuJ5CJv45ifRUo9m"
"5ebo759lKpL1X69ptG7RpHEYULYYurwEGExC1jp/Nbft0zOehsF4wwFqwQVQ34m5"
"LQIDAQAB"
"-----END PUBLIC KEY-----";
/*
..... some unrelated code here */
char derPubKey[2048];
size_t derPubKeyLen = 2048;
CERT_PUBLIC_KEY_INFO *publicKeyInfo;
int publicKeyInfoLen;
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
/*
* Convert from PEM format to DER format - removes header and footer and decodes from base64
*/
if (!CryptStringToBinaryA(szPemPubKey, 0, CRYPT_STRING_BASE64HEADER, (BYTE*)derPubKey, (DWORD*)&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, (BYTE*)derPubKey, derPubKeyLen,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, (DWORD*)&publicKeyInfoLen))
{
fprintf(stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError());
return -1;
}
// Create a temporary and volatile CSP context in order to import
// the key and use for signing
if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
printf("CryptAcquireContext failed with error 0x%.8X\n", GetLastError());
goto main_exit;
}
/*
* 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;
}
看來,關鍵是進口正確和hKey
是流行遲來。
- 到目前爲止,這麼好。然後我特林加密明文
char* plaintext = "123456";
LPBYTE pEncryptedData = NULL;
DWORD EncryptedDataLen = 0;
LPBYTE pEncryptedDataRev = NULL; /* I'll explain this later (: */
DWORD EncryptedDataRevLen = 0;
pEncryptedData = (LPBYTE) LocalAlloc(0, 500);
EncryptedDataLen = 6;
pEncryptedDataRev = (LPBYTE) LocalAlloc(0, 500);
EncryptedDataLen = 6;
CopyMemory(pEncryptedData, plaintext, 6);
if (CryptEncrypt(hKey, NULL, TRUE, 0, pEncryptedData, &EncryptedDataLen, 500)) {
DWORD dwBytesWritten = 0;
hFile = CreateFile(L"poc_enc", // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
ReverseStream(pEncryptedData, pEncryptedDataRev, EncryptedDataLen);
WriteFile(
hFile, // open file handle
pEncryptedData, // start of data to write
EncryptedDataLen, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
CloseHandle(hFile);
}
你可以看到,我倒有ReverseStrem()
加密的數據,那是因爲,我讀過的字節序這CAPI和OpenSSL使用不同。 (little-endian的CAPI和大端的OpenSSL)
void ReverseStream(LPBYTE Source, LPBYTE Destination, DWORD Size)
{
DWORD cnt = Size;
while(0<cnt)
{
Destination[Size-cnt] = Source[cnt];
cnt--;
}
}
- OK,現在麻煩來。加密的明文(123456)被寫入到一個名爲
poc_enc
文件,當我嘗試使用OpenSSL
openssl rsautl -decrypt -in poc_enc -out plaintext -inkey private.pem
解密它,我收到以下錯誤:
RSA operation error
16968:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:.\crypto\rsa\rsa_pk1.c:273:
16968:error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:.\crypto\rsa\rsa_eay.c:602:
任何想法如何解決這個問題?謝謝:)