Win32 API 日本語リファレンス
ホームSecurity.Cryptography › CryptGenKey

CryptGenKey

関数
指定アルゴリズムの暗号鍵またはキーペアを生成する。
DLLADVAPI32.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// ADVAPI32.dll
#include <windows.h>

BOOL CryptGenKey(
    UINT_PTR hProv,
    ALG_ID Algid,
    CRYPT_KEY_FLAGS dwFlags,
    UINT_PTR* phKey
);

パラメーター

名前方向説明
hProvUINT_PTRinCryptAcquireContext の呼び出しによって作成された cryptographic service provider (CSP) へのハンドルです。
AlgidALG_IDin

キーを生成する対象のアルゴリズムを識別する ALG_ID 値です。このパラメーターの値は、使用する CSP によって異なります。

Microsoft Base Cryptographic Provider で使用する ALG_ID 値については、 Base Provider Algorithms を参照してください。

Microsoft Strong Cryptographic Provider または Microsoft Enhanced Cryptographic Provider で使用する ALG_ID 値については、 Enhanced Provider Algorithms を参照してください。

Diffie-Hellman CSP の場合は、次のいずれかの値を使用します。

意味
CALG_DH_EPHEM
"Ephemeral" Diffie-Hellman キーを指定します。
CALG_DH_SF
"Store and Forward" Diffie-Hellman キーを指定します。

この関数は、symmetric algorithms 用のセッションキーを生成するほか、public/private key pairs も生成できます。各 CryptoAPI クライアントは、通常 2 組の公開鍵/秘密鍵のペアを持ちます。これらのキーペアのいずれかを生成するには、Algid パラメーターに次のいずれかの値を設定します。

意味
AT_KEYEXCHANGE
キー交換
AT_SIGNATURE
デジタル署名
キー仕様として AT_KEYEXCHANGE および AT_SIGNATURE を指定した場合、キーの生成に使用されるアルゴリズム識別子は、使用するプロバイダーによって異なります。そのため、これらのキー仕様では、 CryptGetKeyParam から返される値 (KP_ALGID パラメーターを指定した場合) も、使用するプロバイダーによって異なります。キー仕様 AT_KEYEXCHANGE および AT_SIGNATURE に対して各プロバイダーが使用するアルゴリズム識別子を確認するには、 ALG_ID を参照してください。
dwFlagsCRYPT_KEY_FLAGSin

生成するキーの種類を指定します。セッションキー、RSA 署名キー、および RSA キー exchange keys のサイズは、キーの生成時に設定できます。キーサイズ (キーのモジュラスの長さをビット単位で表したもの) は、このパラメーターの上位 16 ビットで設定します。したがって、2,048 ビットの RSA 署名キーを生成する場合は、値 0x08000000 を他の任意の dwFlags 定義済み値とビットごとの OR 演算で組み合わせます。0x08000000 の上位 16 ビットは 0x0800、すなわち 10 進数で 2,048 です。RSA1024BIT_KEY 値を使用すると、1024 ビットの RSA キーを指定できます。

輸出規制の変更により、既定の CSP および既定の key length はオペレーティングシステムのバージョン間で変わる可能性があります。さまざまなオペレーティングシステムプラットフォーム間での相互運用性を確保するには、暗号化と復号で同じ CSP を使用し、dwFlags パラメーターを用いてキーの長さを明示的に設定することが重要です。

特に、既定の RSA Full Cryptographic Service Provider は Microsoft RSA Strong Cryptographic Provider です。既定の DSS Signature Diffie-Hellman Cryptographic Service Provider は Microsoft Enhanced DSS Diffie-Hellman Cryptographic Provider です。これらの CSP はいずれも、RC2 および RC4 に対して既定で 128 ビットの対称キー長を、公開鍵アルゴリズムに対して既定で 1,024 ビットのキー長を持ちます。

上位 16 ビットが 0 の場合は、既定のキーサイズが生成されます。最大値より大きい、または最小値より小さいキーを指定した場合、呼び出しは ERROR_INVALID_PARAMETER コードで失敗します。

次の表は、Windows XP 以降の署名キーおよび交換キーの最小、既定、最大の長さを示します。

キーの種類とプロバイダー 最小の長さ 既定の長さ 最大の長さ
RSA Base Provider

Signature and ExchangeKeys

384 512 16,384
RSA Strong and Enhanced Providers

Signature and Exchange Keys

384 1,024 16,384
DSS Base Providers

Signature Keys

512 1,024 1,024
DSS Base Providers

Exchange Keys

該当なし 該当なし 該当なし
DSS/DH Base Providers

Signature Keys

512 1,024 1,024
DSS/DH Base Providers

Exchange Keys

512 512 1,024
DSS/DH Enhanced Providers

Signature Keys

512 1,024 1,024
DSS/DH Enhanced Providers

Exchange Keys

512 1,024 4,096

セッションキーの長さについては、CryptDeriveKey を参照してください。

Microsoft プロバイダーを使用して生成されるキーの詳細については、 Microsoft Cryptographic Service Providers を参照してください。

このパラメーターの下位 16 ビットは、0 にするか、次の値のうち 1 つ以上を組み合わせて指定できます。

意味
CRYPT_ARCHIVABLE
このフラグを設定すると、CryptDestroyKey の呼び出しによってハンドルが閉じられるまでの間、キーをエクスポートできます。これにより、新しく生成したキーを作成時にエクスポートして、アーカイブやキーの回復に利用できます。ハンドルが閉じられた後は、キーはエクスポートできなくなります。
CRYPT_CREATE_IV
このフラグは使用されません。
CRYPT_CREATE_SALT
このフラグを設定すると、キーには自動的にランダムな salt value が割り当てられます。この salt 値は、 CryptGetKeyParam 関数の dwParam パラメーターに KP_SALT を設定して取得できます。

このフラグを設定しない場合、キーには 0 の salt 値が与えられます。

0 以外の salt 値を持つキーを (CryptExportKey を通じて) エクスポートする場合は、salt value も取得して key BLOB とともに保持する必要があります。

CRYPT_DATA_KEY
このフラグは使用されません。
CRYPT_EXPORTABLE
このフラグを設定すると、 CryptExportKey 関数を使用してキーを CSP から key BLOB に転送できます。一般にセッションキーはエクスポート可能である必要があるため、通常はセッションキーの作成時にこのフラグを設定します。

このフラグを設定しない場合、キーはエクスポートできません。セッションキーの場合、これはキーが現在のセッション内でのみ利用可能であり、それを作成したアプリケーションのみが使用できることを意味します。public/private key pair の場合、これは秘密鍵を転送したりバックアップしたりできないことを意味します。

このフラグは、セッションキーおよび private key BLOBs にのみ適用されます。常にエクスポート可能な公開鍵には適用されません。

CRYPT_FORCE_KEY_PROTECTION_HIGH
このフラグは強力なキー保護を指定します。このフラグを設定すると、キーの作成時にキー用のパスワードの入力を求められます。以降、このキーを使用するたびにパスワードの入力を求められます。

このフラグは、Microsoft が提供する CSP でのみ使用されます。サードパーティ製の CSP は、強力なキー保護について独自の動作を定義します。

このフラグを指定すると、システムレジストリで強力なキー保護が指定されている場合に CRYPT_USER_PROTECTED フラグを指定してこの関数を呼び出した場合と同じ結果になります。

このフラグが指定され、かつ hProv パラメーターのプロバイダーハンドルが CRYPT_VERIFYCONTEXT フラグまたは CRYPT_SILENT フラグを使用して作成された場合、この関数は最後のエラーを NTE_SILENT_CONTEXT に設定し、0 を返します。

Windows Server 2003 および Windows XP: このフラグはサポートされていません。

CRYPT_KEK
このフラグは使用されません。
CRYPT_INITIATOR
このフラグは使用されません。
CRYPT_NO_SALT
このフラグは、40 ビットの symmetric key に対して salt value を割り当てないことを指定します。詳細については、 Salt Value Functionality を参照してください。
CRYPT_ONLINE
このフラグは使用されません。
CRYPT_PREGEN
このフラグは、Diffie-Hellman または DSS キーの初期生成を指定します。このフラグは Diffie-Hellman および DSS CSP でのみ有効です。使用する場合、dwFlags パラメーターの上位 16 ビットでキーの長さを指定しない限り、既定のキー長が使用されます。CryptSetKeyParam を使用して PREGEN Diffie-Hellman または DSS キーにキー長に関わるパラメーターを設定する場合、それらのキー長はここで設定したキー長と互換性がなければなりません。
CRYPT_RECIPIENT
このフラグは使用されません。
CRYPT_SF
このフラグは使用されません。
CRYPT_SGCKEY
このフラグは使用されません。
CRYPT_USER_PROTECTED
このフラグを設定すると、特定の操作がこのキーを使用しようとしたときに、ダイアログボックスやその他の方法でユーザーに通知されます。正確な動作は、使用される CSP によって指定されます。プロバイダーコンテキストが CRYPT_SILENT フラグを設定して開かれていた場合、このフラグを使用すると失敗し、最後のエラーが NTE_SILENT_CONTEXT に設定されます。
CRYPT_VOLATILE
このフラグは使用されません。
phKeyUINT_PTR*out関数が新しく生成したキーのハンドルをコピーするアドレスです。キーの使用が終わったら、CryptDestroyKey 関数を呼び出してキーへのハンドルを削除してください。

戻り値の型: BOOL

公式ドキュメント

ランダムな暗号セッションキー、または公開鍵/秘密鍵のペアを生成します。キーまたはキーペアへのハンドルが phKey に返されます。このハンドルは、キーハンドルを必要とする任意の CryptoAPI 関数で必要に応じて使用できます。

戻り値

成功した場合は 0 以外の値を、それ以外の場合は 0 を返します。

拡張エラー情報を取得するには、 GetLastError を呼び出します。

"NTE" で始まるエラーコードは、使用されている特定の CSP によって生成されます。考えられるエラーコードの一部を次の表に示します。

戻り値 説明
ERROR_INVALID_HANDLE
いずれかのパラメーターが、有効でないハンドルを指定しています。
ERROR_INVALID_PARAMETER
いずれかのパラメーターが、有効でない値を含んでいます。これは多くの場合、有効でないポインターです。
NTE_BAD_ALGID
Algid パラメーターが、この CSP がサポートしていないアルゴリズムを指定しています。
NTE_BAD_FLAGS
dwFlags パラメーターが、有効でない値を含んでいます。
NTE_BAD_UID
hProv パラメーターが、有効なコンテキストハンドルを含んでいません。
NTE_FAIL
関数が何らかの予期しない方法で失敗しました。
NTE_SILENT_CONTEXT
コンテキストが silent として取得されたため、プロバイダーはアクションを実行できませんでした。

解説(Remarks)

symmetric block ciphers 用にキーを生成する場合、キーは既定で、初期化ベクトルを 0 とした cipher block chaining (CBC) モードで設定されます。この cipher mode は、データを一括で暗号化するための適切な既定の方法を提供します。これらのパラメーターを変更するには、 CryptSetKeyParam 関数を使用します。

適切な key length を選択するには、次の方法が推奨されます。

次の例は、ランダムなセッションキーの作成を示しています。この例の完全なコンテキストを含む例については、Example C Program: Encrypting a File を参照してください。この関数を使用する別の例については、Example C Program: Decrypting a File を参照してください。

//-------------------------------------------------------------------
//  Declare the handle to the key.
HCRYPTKEY hKey; 
//-------------------------------------------------------------------
//  This example assumes that a cryptographic context 
//  has been acquired, and that it is stored in hCryptProv.
//---------------------------------------------------------------
//  Create a random session key. 

 if(CryptGenKey(
          hCryptProv, 
          ENCRYPT_ALGORITHM, 
          KEYLENGTH | CRYPT_EXPORTABLE, 
          &hKey))
 {
         printf("A session key has been created.\n");
 } 
 else
 {
          printf("Error during CryptGenKey.\n"); 
          exit(1);
 }
//-------------------------------------------------------------------
//  The key created can be exported into a key BLOB that can be
//  written to a file.
//  ...
//  When you have finished using the key, free the resource.
if (!CryptDestroyKey(hKey))
{
          printf("Error during CryptDestroyKey.\n"); 
          exit(1);
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// ADVAPI32.dll
#include <windows.h>

BOOL CryptGenKey(
    UINT_PTR hProv,
    ALG_ID Algid,
    CRYPT_KEY_FLAGS dwFlags,
    UINT_PTR* phKey
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CryptGenKey(
    UIntPtr hProv,   // UINT_PTR
    uint Algid,   // ALG_ID
    uint dwFlags,   // CRYPT_KEY_FLAGS
    out UIntPtr phKey   // UINT_PTR* out
);
<DllImport("ADVAPI32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CryptGenKey(
    hProv As UIntPtr,   ' UINT_PTR
    Algid As UInteger,   ' ALG_ID
    dwFlags As UInteger,   ' CRYPT_KEY_FLAGS
    <Out> ByRef phKey As UIntPtr   ' UINT_PTR* out
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' hProv : UINT_PTR
' Algid : ALG_ID
' dwFlags : CRYPT_KEY_FLAGS
' phKey : UINT_PTR* out
Declare PtrSafe Function CryptGenKey Lib "advapi32" ( _
    ByVal hProv As LongPtr, _
    ByVal Algid As Long, _
    ByVal dwFlags As Long, _
    ByRef phKey As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

CryptGenKey = ctypes.windll.advapi32.CryptGenKey
CryptGenKey.restype = wintypes.BOOL
CryptGenKey.argtypes = [
    ctypes.c_size_t,  # hProv : UINT_PTR
    wintypes.DWORD,  # Algid : ALG_ID
    wintypes.DWORD,  # dwFlags : CRYPT_KEY_FLAGS
    ctypes.POINTER(ctypes.c_size_t),  # phKey : UINT_PTR* out
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('ADVAPI32.dll')
CryptGenKey = Fiddle::Function.new(
  lib['CryptGenKey'],
  [
    Fiddle::TYPE_UINTPTR_T,  # hProv : UINT_PTR
    -Fiddle::TYPE_INT,  # Algid : ALG_ID
    -Fiddle::TYPE_INT,  # dwFlags : CRYPT_KEY_FLAGS
    Fiddle::TYPE_VOIDP,  # phKey : UINT_PTR* out
  ],
  Fiddle::TYPE_INT)
#[link(name = "advapi32")]
extern "system" {
    fn CryptGenKey(
        hProv: usize,  // UINT_PTR
        Algid: u32,  // ALG_ID
        dwFlags: u32,  // CRYPT_KEY_FLAGS
        phKey: *mut usize  // UINT_PTR* out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", SetLastError = true)]
public static extern bool CryptGenKey(UIntPtr hProv, uint Algid, uint dwFlags, out UIntPtr phKey);
"@
$api = Add-Type -MemberDefinition $sig -Name 'ADVAPI32_CryptGenKey' -Namespace Win32 -PassThru
# $api::CryptGenKey(hProv, Algid, dwFlags, phKey)
#uselib "ADVAPI32.dll"
#func global CryptGenKey "CryptGenKey" sptr, sptr, sptr, sptr
; CryptGenKey hProv, Algid, dwFlags, varptr(phKey)   ; 戻り値は stat
; hProv : UINT_PTR -> "sptr"
; Algid : ALG_ID -> "sptr"
; dwFlags : CRYPT_KEY_FLAGS -> "sptr"
; phKey : UINT_PTR* out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "ADVAPI32.dll"
#cfunc global CryptGenKey "CryptGenKey" sptr, int, int, var
; res = CryptGenKey(hProv, Algid, dwFlags, phKey)
; hProv : UINT_PTR -> "sptr"
; Algid : ALG_ID -> "int"
; dwFlags : CRYPT_KEY_FLAGS -> "int"
; phKey : UINT_PTR* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL CryptGenKey(UINT_PTR hProv, ALG_ID Algid, CRYPT_KEY_FLAGS dwFlags, UINT_PTR* phKey)
#uselib "ADVAPI32.dll"
#cfunc global CryptGenKey "CryptGenKey" intptr, int, int, var
; res = CryptGenKey(hProv, Algid, dwFlags, phKey)
; hProv : UINT_PTR -> "intptr"
; Algid : ALG_ID -> "int"
; dwFlags : CRYPT_KEY_FLAGS -> "int"
; phKey : UINT_PTR* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	advapi32 = windows.NewLazySystemDLL("ADVAPI32.dll")
	procCryptGenKey = advapi32.NewProc("CryptGenKey")
)

// hProv (UINT_PTR), Algid (ALG_ID), dwFlags (CRYPT_KEY_FLAGS), phKey (UINT_PTR* out)
r1, _, err := procCryptGenKey.Call(
	uintptr(hProv),
	uintptr(Algid),
	uintptr(dwFlags),
	uintptr(phKey),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function CryptGenKey(
  hProv: NativeUInt;   // UINT_PTR
  Algid: DWORD;   // ALG_ID
  dwFlags: DWORD;   // CRYPT_KEY_FLAGS
  phKey: Pointer   // UINT_PTR* out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptGenKey';
result := DllCall("ADVAPI32\CryptGenKey"
    , "UPtr", hProv   ; UINT_PTR
    , "UInt", Algid   ; ALG_ID
    , "UInt", dwFlags   ; CRYPT_KEY_FLAGS
    , "Ptr", phKey   ; UINT_PTR* out
    , "Int")   ; return: BOOL
●CryptGenKey(hProv, Algid, dwFlags, phKey) = DLL("ADVAPI32.dll", "bool CryptGenKey(int, dword, dword, void*)")
# 呼び出し: CryptGenKey(hProv, Algid, dwFlags, phKey)
# hProv : UINT_PTR -> "int"
# Algid : ALG_ID -> "dword"
# dwFlags : CRYPT_KEY_FLAGS -> "dword"
# phKey : UINT_PTR* out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "advapi32" fn CryptGenKey(
    hProv: usize, // UINT_PTR
    Algid: u32, // ALG_ID
    dwFlags: u32, // CRYPT_KEY_FLAGS
    phKey: [*c]usize // UINT_PTR* out
) callconv(std.os.windows.WINAPI) i32;
proc CryptGenKey(
    hProv: uint,  # UINT_PTR
    Algid: uint32,  # ALG_ID
    dwFlags: uint32,  # CRYPT_KEY_FLAGS
    phKey: ptr uint  # UINT_PTR* out
): int32 {.importc: "CryptGenKey", stdcall, dynlib: "ADVAPI32.dll".}
pragma(lib, "advapi32");
extern(Windows)
int CryptGenKey(
    size_t hProv,   // UINT_PTR
    uint Algid,   // ALG_ID
    uint dwFlags,   // CRYPT_KEY_FLAGS
    size_t* phKey   // UINT_PTR* out
);
ccall((:CryptGenKey, "ADVAPI32.dll"), stdcall, Int32,
      (Csize_t, UInt32, UInt32, Ptr{Csize_t}),
      hProv, Algid, dwFlags, phKey)
# hProv : UINT_PTR -> Csize_t
# Algid : ALG_ID -> UInt32
# dwFlags : CRYPT_KEY_FLAGS -> UInt32
# phKey : UINT_PTR* out -> Ptr{Csize_t}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t CryptGenKey(
    uintptr_t hProv,
    uint32_t Algid,
    uint32_t dwFlags,
    uintptr_t* phKey);
]]
local advapi32 = ffi.load("advapi32")
-- advapi32.CryptGenKey(hProv, Algid, dwFlags, phKey)
-- hProv : UINT_PTR
-- Algid : ALG_ID
-- dwFlags : CRYPT_KEY_FLAGS
-- phKey : UINT_PTR* out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('ADVAPI32.dll');
const CryptGenKey = lib.func('__stdcall', 'CryptGenKey', 'int32_t', ['uintptr_t', 'uint32_t', 'uint32_t', 'uintptr_t *']);
// CryptGenKey(hProv, Algid, dwFlags, phKey)
// hProv : UINT_PTR -> 'uintptr_t'
// Algid : ALG_ID -> 'uint32_t'
// dwFlags : CRYPT_KEY_FLAGS -> 'uint32_t'
// phKey : UINT_PTR* out -> 'uintptr_t *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("ADVAPI32.dll", {
  CryptGenKey: { parameters: ["usize", "u32", "u32", "pointer"], result: "i32" },
});
// lib.symbols.CryptGenKey(hProv, Algid, dwFlags, phKey)
// hProv : UINT_PTR -> "usize"
// Algid : ALG_ID -> "u32"
// dwFlags : CRYPT_KEY_FLAGS -> "u32"
// phKey : UINT_PTR* out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t CryptGenKey(
    size_t hProv,
    uint32_t Algid,
    uint32_t dwFlags,
    size_t* phKey);
C, "ADVAPI32.dll");
// $ffi->CryptGenKey(hProv, Algid, dwFlags, phKey);
// hProv : UINT_PTR
// Algid : ALG_ID
// dwFlags : CRYPT_KEY_FLAGS
// phKey : UINT_PTR* out
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Advapi32 extends StdCallLibrary {
    Advapi32 INSTANCE = Native.load("advapi32", Advapi32.class);
    boolean CryptGenKey(
        long hProv,   // UINT_PTR
        int Algid,   // ALG_ID
        int dwFlags,   // CRYPT_KEY_FLAGS
        LongByReference phKey   // UINT_PTR* out
    );
}
@[Link("advapi32")]
lib LibADVAPI32
  fun CryptGenKey = CryptGenKey(
    hProv : LibC::SizeT,   # UINT_PTR
    Algid : UInt32,   # ALG_ID
    dwFlags : UInt32,   # CRYPT_KEY_FLAGS
    phKey : LibC::SizeT*   # UINT_PTR* out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef CryptGenKeyNative = Int32 Function(UintPtr, Uint32, Uint32, Pointer<UintPtr>);
typedef CryptGenKeyDart = int Function(int, int, int, Pointer<UintPtr>);
final CryptGenKey = DynamicLibrary.open('ADVAPI32.dll')
    .lookupFunction<CryptGenKeyNative, CryptGenKeyDart>('CryptGenKey');
// hProv : UINT_PTR -> UintPtr
// Algid : ALG_ID -> Uint32
// dwFlags : CRYPT_KEY_FLAGS -> Uint32
// phKey : UINT_PTR* out -> Pointer<UintPtr>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CryptGenKey(
  hProv: NativeUInt;   // UINT_PTR
  Algid: DWORD;   // ALG_ID
  dwFlags: DWORD;   // CRYPT_KEY_FLAGS
  phKey: Pointer   // UINT_PTR* out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptGenKey';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "CryptGenKey"
  c_CryptGenKey :: CUIntPtr -> Word32 -> Word32 -> Ptr CUIntPtr -> IO CInt
-- hProv : UINT_PTR -> CUIntPtr
-- Algid : ALG_ID -> Word32
-- dwFlags : CRYPT_KEY_FLAGS -> Word32
-- phKey : UINT_PTR* out -> Ptr CUIntPtr
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let cryptgenkey =
  foreign "CryptGenKey"
    (size_t @-> uint32_t @-> uint32_t @-> (ptr size_t) @-> returning int32_t)
(* hProv : UINT_PTR -> size_t *)
(* Algid : ALG_ID -> uint32_t *)
(* dwFlags : CRYPT_KEY_FLAGS -> uint32_t *)
(* phKey : UINT_PTR* out -> (ptr size_t) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library advapi32 (t "ADVAPI32.dll"))
(cffi:use-foreign-library advapi32)

(cffi:defcfun ("CryptGenKey" crypt-gen-key :convention :stdcall) :int32
  (h-prov :uint64)   ; UINT_PTR
  (algid :uint32)   ; ALG_ID
  (dw-flags :uint32)   ; CRYPT_KEY_FLAGS
  (ph-key :pointer))   ; UINT_PTR* out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CryptGenKey = Win32::API::More->new('ADVAPI32',
    'BOOL CryptGenKey(WPARAM hProv, DWORD Algid, DWORD dwFlags, LPVOID phKey)');
# my $ret = $CryptGenKey->Call($hProv, $Algid, $dwFlags, $phKey);
# hProv : UINT_PTR -> WPARAM
# Algid : ALG_ID -> DWORD
# dwFlags : CRYPT_KEY_FLAGS -> DWORD
# phKey : UINT_PTR* out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目
使用する型