#windows #encryption #rsa #cng
Вопрос:
Я успешно сгенерировал ключи RSA, используя следующую последовательность API CNG:
BCryptOpenAlgorithmProvider(.., BCRYPT_RSA_ALGORITHM, ...); BCryptGenerateKeyPair(..., 2048/*Key size*/, ...); BCryptFinalizeKeyPair(...); BCryptExportKey(..., BCRYPT_RSAPRIVATE_BLOB, ...); BCryptExportKey(..., BCRYPT_RSAPUBLIC_BLOB, ...);
Я в замешательстве, хотя какая часть сгенерированного буфера должна быть закодирована в Base64 для записи файла PEM? Я не вижу «MIIE» в буфере, если я Base64 кодирую весь буфер, который есть в существующих допустимых файлах PEM.
Мы будем очень признательны за любые рекомендации.
Ответ №1:
действительно не нужно напрямую кодировать вывод base64 из BCryptExportKey
или NCryptExportKey
, но делать дополнительные шаги:
- использовать
BCryptExportKey
(илиNCryptExportKey
) сBCRYPT_RSAFULLPRIVATE_BLOB
(но неBCRYPT_RSAPRIVATE_BLOB
) илиBCRYPT_RSAPUBLIC_BLOB
- закодируйте полученный результат
BCRYPT_RSAKEY_BLOB
сCNG_RSA_PRIVATE_KEY_BLOB
помощью илиCNG_RSA_PUBLIC_KEY_BLOB
и поместите вCRYPT_PRIVATE_KEY_INFO
- кодировать
CRYPT_PRIVATE_KEY_INFO
с помощьюPKCS_PRIVATE_KEY_INFO
- вызов
CryptBinaryToStringA
только после этого в буфере появится «MIIE»
HRESULT bthr(BOOL b) { return b ? S_OK : HRESULT_FROM_WIN32(GetLastError()); } HRESULT ExportToPem(_In_ BCRYPT_KEY_HANDLE hKey, BOOL bPrivate, _Out_ PSTR* ppsz, _Out_ PULONG pcch) { HRESULT hr; CRYPT_PRIVATE_KEY_INFO PrivateKeyInfo = { 0, {const_castlt;PSTRgt;(szOID_RSA_RSA)} }; ULONG cbKey = 0; PUCHAR pbKey = 0;//really PBCRYPT_RSAKEY_BLOB PCWSTR pszBlobType; PCSTR lpszStructType; if (bPrivate) { pszBlobType = BCRYPT_RSAFULLPRIVATE_BLOB; lpszStructType = CNG_RSA_PRIVATE_KEY_BLOB; } else { pszBlobType = BCRYPT_RSAPUBLIC_BLOB; lpszStructType = CNG_RSA_PUBLIC_KEY_BLOB; } while (0 lt;= (hr = BCryptExportKey(hKey, 0, pszBlobType, pbKey, cbKey, amp;cbKey, 0))) { if (pbKey) { if (0 lt;= (hr = bthr(CryptEncodeObjectEx(X509_ASN_ENCODING, lpszStructType, pbKey, CRYPT_ENCODE_ALLOC_FLAG, 0, amp;PrivateKeyInfo.PrivateKey.pbData, amp;PrivateKeyInfo.PrivateKey.cbData)))) { hr = bthr(CryptEncodeObjectEx(X509_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO, amp;PrivateKeyInfo, CRYPT_ENCODE_ALLOC_FLAG, 0, amp;pbKey, amp;cbKey)); LocalFree(PrivateKeyInfo.PrivateKey.pbData); if (0 lt;= hr) { PSTR psz = 0; ULONG cch = 0; while (0 lt;= (hr = bthr(CryptBinaryToStringA( pbKey, cbKey, CRYPT_STRING_BASE64, psz, amp;cch)))) { if (psz) { *ppsz = psz, *pcch = cch; break; } if (!(psz = (PSTR)LocalAlloc(0, cch))) { hr = HRESULT_FROM_WIN32(GetLastError()); break; } } LocalFree(pbKey); } } break; } pbKey = (PUCHAR)alloca(cbKey); } return hr; }
и используйте его:
PSTR psz; ULONG cch; if (0 lt;= ExportToPem(hKey, bPrivate, amp;psz, amp;cch)) { PSTR pc = psz; ULONG cb; do { cb = min(cch, 0x100); DbgPrint("%.*s", cb, pc); } while (pc = cb, cch -= cb); LocalFree(psz); }
Комментарии:
1. Спасибо! С помощью этого я смог сгенерировать ключи Base64. У меня на самом деле возникают проблемы с шифрованием и дешифрованием, но я думаю, что это больше связано с тем, как я вызываю функции шифрования/дешифрования.
2. @Unknown1987 У меня возникли проблемы с фактическим отключением шифрования и дешифрования — в смысле ?