Как экспортировать ключи RSA, сгенерированные из CNG API?

#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 , но делать дополнительные шаги:

  1. использовать BCryptExportKey (или NCryptExportKey ) с BCRYPT_RSAFULLPRIVATE_BLOB (но не BCRYPT_RSAPRIVATE_BLOB ) или BCRYPT_RSAPUBLIC_BLOB
  2. закодируйте полученный результат BCRYPT_RSAKEY_BLOB с CNG_RSA_PRIVATE_KEY_BLOB помощью или CNG_RSA_PUBLIC_KEY_BLOB и поместите в CRYPT_PRIVATE_KEY_INFO
  3. кодировать CRYPT_PRIVATE_KEY_INFO с помощью PKCS_PRIVATE_KEY_INFO
  4. вызов 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 У меня возникли проблемы с фактическим отключением шифрования и дешифрования — в смысле ?