Используя API следующего поколения для криптографии (также известный как CryptoAPI следующего поколения, известный как CryptoNG, известный как Cng, известный как BestCrypt, известный как bcrypt), я пытаюсь экспортировать только что созданную пару закрытых ключей RSA:
Редактировать : более короткая версия кода:
BCRYPT_ALG_HANDLE alg;
BCryptOpenAlgorithmProvider(out alg, BCRYPT_RSA_ALGORITHM, null, 0);
BCRYPT_KEY_HANDLE key;
BCryptGenerateKeyPair(alg, out key, 4096, 0);
DWORD cbResult;
BCryptExportKey(key, 0, BCRYPT_RSAFULLPRIVATE_BLOB, null, 0, out cbResult, 0);
более длинная версия кода :
NTSTATUS nt;
// Open the RSA algorithm provider
BCRYPT_ALG_HANDLE alg;
nt = BCryptOpenAlgorithmProvider(out alg, BCRYPT_RSA_ALGORITHM, null, 0);
NTStatusCheck(nt);
// Successfully opened the RSA algorithm provider
// Generate a 4096 bit RSA public-private key pair
BCRYPT_KEY_HANDLE key;
nt = BCryptGenerateKeyPair(alg, out key, 4096, 0);
NTStatusCheck(nt);
// Successfully generates a key pair (key <-- $4E737A0)
// Ask for the buffer size required to export the key pair
DWORD cbResult;
nt = BCryptExportKey(key, 0, BCRYPT_RSAFULLPRIVATE_BLOB, null, 0, out cbResult, 0);
NTStatusCheck(nt);
// Fails with 0xC0000008 (STATUS_INVALID_HANDLE)
Что я делаю не так?
Чтение бонусов
Полный минимальный пример (Delphi)
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, ComObj, ActiveX;
type
NTSTATUS = Cardinal;
const
BCRYPT_RSA_ALGORITHM: WideString = 'RSA';
BCRYPT_RSAFULLPRIVATE_BLOB: WideString = 'RSAFULLPRIVATEBLOB';
BCRYPT_RSAPRIVATE_BLOB: WideString = 'RSAPRIVATEBLOB';
BCRYPT_RSAPUBLIC_BLOB: WideString = 'RSAPUBLICBLOB';
LEGACY_RSAPRIVATE_BLOB: WideString = 'CAPIPRIVATEBLOB';
LEGACY_RSAPUBLIC_BLOB: WideString = 'CAPIPUBLICBLOB';
function BCryptOpenAlgorithmProvider(out hAlgorithm: THandle; pszAlgId, pszImplementation: PWideChar; dwFlags: Cardinal): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptGenerateKeyPair(hAlgorithm: THandle; out phKey: THandle; dwLength: Cardinal; dwFlags: Cardinal): NTSTATUS; stdcall; external 'bcrypt.dll';
function BCryptExportKey(hKey: THandle; hExportKey: THandle; pszBlobType: PWideChar; pbOutput: Pointer; cbOutput: Cardinal; out pcbResult: Cardinal; dwFlags: Cardinal): NTSTATUS; stdcall; external 'bcrypt.dll';
procedure Main;
var
nt: Cardinal;
alg: THandle;
key: THandle;
cbResult: Cardinal;
begin
// Open the RSA algorithm provider
WriteLn('Opening algorithm provider');
nt := BCryptOpenAlgorithmProvider({out} alg, PWideChar(BCRYPT_RSA_ALGORITHM), nil, 0);
OleCheck(HRESULT(nt));
// Generate a RSA public-private key pair
WriteLn('Generating key pair');
key := 0;
nt := BCryptGenerateKeyPair(alg, {out} key, 1024, 0);
OleCheck(HRESULT(nt));
// Ask for the buffer size required to export the key pair
WriteLn('Exporting full private blob');
cbResult := 0;
nt := BCryptExportKey(key, 0, PWideChar(BCRYPT_RSAFULLPRIVATE_BLOB), nil, 0, {out} cbResult, 0);
OleCheck(HRESULT(nt));
WriteLn('Success');
end;
begin
Main;
WriteLn('Press enter to close...');
ReadLn;
end.
Полный минимальный пример (C #)
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
internal static extern Int32 BCryptOpenAlgorithmProvider(out IntPtr phAlgorithm, [In] string pszAlgId, [In] string pszImplementation, [In] int dwFlags);
[DllImport("bcrypt.dll")]
internal static extern Int32 BCryptGenerateKeyPair([In] IntPtr hAlgorithm, out IntPtr phKey, [In] UInt32 dwLength, [In] UInt32 dwFlags);
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
internal static extern Int32 BCryptExportKey([In] IntPtr hKey, [In] IntPtr hExportKey, [MarshalAs(UnmanagedType.LPWStr)] [In] string pszBlobType, [MarshalAs(UnmanagedType.LPArray)] [Out] byte[] pbOutput, [In] int cbOutput, [In] ref UInt32 cbResult, [In] int dwFlags);
static void Main(string[] args)
{
Int32 nt;
IntPtr alg;
nt = BCryptOpenAlgorithmProvider(out alg, "RSA", null, 0);
if (nt < 0)
throw new COMException("Open algorithm", (int)nt);
IntPtr key;
nt = BCryptGenerateKeyPair(alg, out key, 1024, 0);
if (nt < 0)
throw new COMException("Generate key", nt);
UInt32 cbResult = 0;
nt = BCryptExportKey(key, IntPtr.Zero, "RSAPRIVATEBLOB", null, 0, ref cbResult, 0);
if (nt < 0)
throw new COMException("Export", nt);
}
}
}