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

CryptDeriveKey

関数
ハッシュデータから暗号鍵を導出して生成する。
DLLADVAPI32.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

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

BOOL CryptDeriveKey(
    UINT_PTR hProv,
    ALG_ID Algid,
    UINT_PTR hBaseData,
    DWORD dwFlags,
    UINT_PTR* phKey
);

パラメーター

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

キーを生成する対象の対称暗号アルゴリズムを識別する ALG_ID 構造体です。利用可能なアルゴリズムは CSP ごとに異なる可能性が高くなります。キー仕様 AT_KEYEXCHANGE および AT_SIGNATURE に対して各プロバイダーが使用するアルゴリズム識別子の詳細については、 ALG_ID を参照してください。

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

hBaseDataUINT_PTRin

正確なベースデータが供給されたハッシュオブジェクトへのハンドルです。

このハンドルを取得するには、アプリケーションはまず CryptCreateHash でハッシュオブジェクトを作成し、続いて CryptHashData でベースデータをハッシュオブジェクトに追加する必要があります。この手順については Hashes and Digital Signatures で詳しく説明しています。

dwFlagsDWORDin

生成するキーの種類を指定します。

セッションキーのサイズは、キーの生成時に設定できます。キーサイズ(キーのモジュラスの長さをビット単位で表したもの)は、このパラメーターの上位 16 ビットで設定します。したがって、128 ビットの RC4 セッションキーを生成する場合は、値 0x00800000 を他の任意の dwFlags の定義済み値とビットごとの OR 演算で組み合わせます。輸出規制の変更により、既定の CSP および既定のキー長はオペレーティングシステムのリリース間で変わる場合があります。暗号化と復号化の双方で同じ CSP を使用すること、および dwFlags パラメーターを使用してキー長を明示的に設定することが、異なるオペレーティングシステムプラットフォーム間での相互運用性を確保するうえで重要です。

このパラメーターの下位 16 ビットはゼロにするか、または以下のフラグの 1 つ以上をビットごとの OR 演算子で組み合わせて指定できます。

意味
CRYPT_CREATE_SALT
通常、セッションキーがハッシュ値から作成される場合、余りのビットがいくつか生じます。たとえば、ハッシュ値が 128 ビットでセッションキーが 40 ビットの場合、88 ビットが余ります。

このフラグが設定されている場合、未使用のハッシュ値ビットに基づいてキーにソルト値が割り当てられます。このソルト値は、 CryptGetKeyParam 関数の dwParam パラメーターを KP_SALT に設定することで取得できます。

このフラグが設定されていない場合、キーにはゼロのソルト値が与えられます。

ゼロ以外のソルト値を持つキーを(CryptExportKey を使用して)エクスポートする場合は、ソルト値も取得し、キー BLOB とともに保持する必要があります。

CRYPT_EXPORTABLE
このフラグが設定されている場合、セッションキーは CryptExportKey 関数を通じて CSP からキー BLOB へ転送できます。キーは一般にエクスポート可能である必要があるため、通常はこのフラグを設定すべきです。

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

このフラグは公開鍵/秘密鍵のペアには適用されません。

CRYPT_NO_SALT
このフラグは、40 ビットの対称キーソルト値を割り当てないことを指定します。詳細については、 Salt Value Functionality を参照してください。
CRYPT_UPDATE_KEY
一部の CSP は、複数のハッシュ値から導出されるセッションキーを使用します。この場合、CryptDeriveKey を複数回呼び出す必要があります。

このフラグが設定されている場合、新しいセッションキーは生成されません。代わりに、phKey で指定されたキーが変更されます。このフラグの正確な動作は、生成されるキーの種類および使用する特定の CSP によって異なります。

Microsoft の暗号サービスプロバイダーはこのフラグを無視します。

CRYPT_SERVER
1024 (0x400)
このフラグは Schannel プロバイダーでのみ使用されます。このフラグが設定されている場合、生成されるキーはサーバー書き込みキーになります。それ以外の場合はクライアント書き込みキーになります。
phKeyUINT_PTR*out新しく生成されたキーのハンドルのアドレスを受け取る HCRYPTKEY 変数へのポインターです。キーの使用が終わったら、CryptDestroyKey 関数を呼び出してハンドルを解放してください。

戻り値の型: BOOL

公式ドキュメント

ベースとなるデータ値から導出される暗号セッションキーを生成します。

戻り値

関数が成功した場合、ゼロ以外(TRUE)を返します。

関数が失敗した場合は、ゼロ(FALSE)を返します。拡張エラー情報を取得するには、 GetLastError を呼び出します。

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

戻り値 説明
ERROR_INVALID_HANDLE
いずれかのパラメーターが有効でないハンドルを指定しています。
ERROR_INVALID_PARAMETER
いずれかのパラメーターに有効でない値が含まれています。多くの場合、これは有効でないポインターです。
NTE_BAD_ALGID
Algid パラメーターが、この CSP がサポートしないアルゴリズムを指定しています。
NTE_BAD_FLAGS
dwFlags パラメーターに有効でない値が含まれています。
NTE_BAD_HASH
hBaseData パラメーターにハッシュオブジェクトへの有効なハンドルが含まれていません。
NTE_BAD_HASH_STATE
すでに「完了」とマークされているハッシュオブジェクトにデータを追加しようとしました。
NTE_BAD_UID
hProv パラメーターに有効なコンテキストハンドルが含まれていません。
NTE_FAIL
関数が何らかの予期しない形で失敗しました。
NTE_SILENT_CONTEXT
コンテキストがサイレントとして取得されたため、プロバイダーはアクションを実行できませんでした。

解説(Remarks)

対称ブロック暗号用のキーが生成される場合、キーは既定で、初期化ベクトルがゼロの暗号ブロック連鎖(CBC)モードで設定されます。この暗号モードは、データを一括暗号化するための適切な既定の方法を提供します。これらのパラメーターを変更するには、 CryptSetKeyParam 関数を使用します。

CryptDeriveKey 関数はハッシュを完了させます。CryptDeriveKey が呼び出された後は、ハッシュにこれ以上データを追加できません。 CryptHashDataCryptHashSessionKey をさらに呼び出すと失敗します。アプリケーションがハッシュの使用を終えた後は、 CryptDestroyHash を呼び出してハッシュオブジェクトを破棄する必要があります。

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

n を必要な導出キー長(バイト単位)とします。導出キーは、CryptDeriveKey によってハッシュ計算が完了した後のハッシュ値の先頭 n バイトです。ハッシュが SHA-2 ファミリーのメンバーではなく、必要なキーが 3DES または AES のいずれか用である場合、キーは次のように導出されます。
  1. 定数 0x36 を 64 回繰り返して 64 バイトのバッファーを作成します。k を入力パラメーター hBaseData が表すハッシュ値の長さとします。バッファーの先頭 k バイトを、バッファーの先頭 k バイトと入力パラメーター hBaseData が表すハッシュ値との XOR 演算の結果に設定します。
  2. 定数 0x5C を 64 回繰り返して 64 バイトのバッファーを作成します。バッファーの先頭 k バイトを、バッファーの先頭 k バイトと入力パラメーター hBaseData が表すハッシュ値との XOR 演算の結果に設定します。
  3. ステップ 1 の結果を、hBaseData パラメーターが表すハッシュ値の計算に使用したものと同じハッシュアルゴリズムを使用してハッシュします。
  4. ステップ 2 の結果を、hBaseData パラメーターが表すハッシュ値の計算に使用したものと同じハッシュアルゴリズムを使用してハッシュします。
  5. ステップ 3 の結果とステップ 4 の結果を連結します。
  6. ステップ 5 の結果の先頭 n バイトを導出キーとして使用します。
既定の 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 ビットの対称キー長を持ちます。

次の表に、アルゴリズムおよびプロバイダー別のセッションキーの最小、既定、最大のキー長を示します。

プロバイダー アルゴリズム 最小キー長 既定キー長 最大キー長
MS Base RC4 and RC2 40 40 56
MS Base DES 56 56 56
MS Enhanced RC4 and RC2 40 128 128
MS Enhanced DES 56 56 56
MS Enhanced 3DES 112 112 112 112
MS Enhanced 3DES 168 168 168
MS Strong RC4 and RC2 40 128 128
MS Strong DES 56 56 56
MS Strong 3DES 112 112 112 112
MS Strong 3DES 168 168 168
DSS/DH Base RC4 and RC2 40 40 56
DSS/DH Base Cylink MEK 40 40 40
DSS/DH Base DES 56 56 56
DSS/DH Enh RC4 and RC2 40 128 128
DSS/DH Enh Cylink MEK 40 40 40
DSS/DH Enh DES 56 56 56
DSS/DH Enh 3DES 112 112 112 112
DSS/DH Enh 3DES 168 168 168

この関数を使用する例については、Example C Program: Deriving a Session Key from a Password を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

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

BOOL CryptDeriveKey(
    UINT_PTR hProv,
    ALG_ID Algid,
    UINT_PTR hBaseData,
    DWORD dwFlags,
    UINT_PTR* phKey
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CryptDeriveKey(
    UIntPtr hProv,   // UINT_PTR
    uint Algid,   // ALG_ID
    UIntPtr hBaseData,   // UINT_PTR
    uint dwFlags,   // DWORD
    out UIntPtr phKey   // UINT_PTR* out
);
<DllImport("ADVAPI32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CryptDeriveKey(
    hProv As UIntPtr,   ' UINT_PTR
    Algid As UInteger,   ' ALG_ID
    hBaseData As UIntPtr,   ' UINT_PTR
    dwFlags As UInteger,   ' DWORD
    <Out> ByRef phKey As UIntPtr   ' UINT_PTR* out
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' hProv : UINT_PTR
' Algid : ALG_ID
' hBaseData : UINT_PTR
' dwFlags : DWORD
' phKey : UINT_PTR* out
Declare PtrSafe Function CryptDeriveKey Lib "advapi32" ( _
    ByVal hProv As LongPtr, _
    ByVal Algid As Long, _
    ByVal hBaseData As LongPtr, _
    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

CryptDeriveKey = ctypes.windll.advapi32.CryptDeriveKey
CryptDeriveKey.restype = wintypes.BOOL
CryptDeriveKey.argtypes = [
    ctypes.c_size_t,  # hProv : UINT_PTR
    wintypes.DWORD,  # Algid : ALG_ID
    ctypes.c_size_t,  # hBaseData : UINT_PTR
    wintypes.DWORD,  # dwFlags : DWORD
    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')
CryptDeriveKey = Fiddle::Function.new(
  lib['CryptDeriveKey'],
  [
    Fiddle::TYPE_UINTPTR_T,  # hProv : UINT_PTR
    -Fiddle::TYPE_INT,  # Algid : ALG_ID
    Fiddle::TYPE_UINTPTR_T,  # hBaseData : UINT_PTR
    -Fiddle::TYPE_INT,  # dwFlags : DWORD
    Fiddle::TYPE_VOIDP,  # phKey : UINT_PTR* out
  ],
  Fiddle::TYPE_INT)
#[link(name = "advapi32")]
extern "system" {
    fn CryptDeriveKey(
        hProv: usize,  // UINT_PTR
        Algid: u32,  // ALG_ID
        hBaseData: usize,  // UINT_PTR
        dwFlags: u32,  // DWORD
        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 CryptDeriveKey(UIntPtr hProv, uint Algid, UIntPtr hBaseData, uint dwFlags, out UIntPtr phKey);
"@
$api = Add-Type -MemberDefinition $sig -Name 'ADVAPI32_CryptDeriveKey' -Namespace Win32 -PassThru
# $api::CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey)
#uselib "ADVAPI32.dll"
#func global CryptDeriveKey "CryptDeriveKey" sptr, sptr, sptr, sptr, sptr
; CryptDeriveKey hProv, Algid, hBaseData, dwFlags, varptr(phKey)   ; 戻り値は stat
; hProv : UINT_PTR -> "sptr"
; Algid : ALG_ID -> "sptr"
; hBaseData : UINT_PTR -> "sptr"
; dwFlags : DWORD -> "sptr"
; phKey : UINT_PTR* out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "ADVAPI32.dll"
#cfunc global CryptDeriveKey "CryptDeriveKey" sptr, int, sptr, int, var
; res = CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey)
; hProv : UINT_PTR -> "sptr"
; Algid : ALG_ID -> "int"
; hBaseData : UINT_PTR -> "sptr"
; dwFlags : DWORD -> "int"
; phKey : UINT_PTR* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL CryptDeriveKey(UINT_PTR hProv, ALG_ID Algid, UINT_PTR hBaseData, DWORD dwFlags, UINT_PTR* phKey)
#uselib "ADVAPI32.dll"
#cfunc global CryptDeriveKey "CryptDeriveKey" intptr, int, intptr, int, var
; res = CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey)
; hProv : UINT_PTR -> "intptr"
; Algid : ALG_ID -> "int"
; hBaseData : UINT_PTR -> "intptr"
; dwFlags : DWORD -> "int"
; phKey : UINT_PTR* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	advapi32 = windows.NewLazySystemDLL("ADVAPI32.dll")
	procCryptDeriveKey = advapi32.NewProc("CryptDeriveKey")
)

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

extern "advapi32" fn CryptDeriveKey(
    hProv: usize, // UINT_PTR
    Algid: u32, // ALG_ID
    hBaseData: usize, // UINT_PTR
    dwFlags: u32, // DWORD
    phKey: [*c]usize // UINT_PTR* out
) callconv(std.os.windows.WINAPI) i32;
proc CryptDeriveKey(
    hProv: uint,  # UINT_PTR
    Algid: uint32,  # ALG_ID
    hBaseData: uint,  # UINT_PTR
    dwFlags: uint32,  # DWORD
    phKey: ptr uint  # UINT_PTR* out
): int32 {.importc: "CryptDeriveKey", stdcall, dynlib: "ADVAPI32.dll".}
pragma(lib, "advapi32");
extern(Windows)
int CryptDeriveKey(
    size_t hProv,   // UINT_PTR
    uint Algid,   // ALG_ID
    size_t hBaseData,   // UINT_PTR
    uint dwFlags,   // DWORD
    size_t* phKey   // UINT_PTR* out
);
ccall((:CryptDeriveKey, "ADVAPI32.dll"), stdcall, Int32,
      (Csize_t, UInt32, Csize_t, UInt32, Ptr{Csize_t}),
      hProv, Algid, hBaseData, dwFlags, phKey)
# hProv : UINT_PTR -> Csize_t
# Algid : ALG_ID -> UInt32
# hBaseData : UINT_PTR -> Csize_t
# dwFlags : DWORD -> UInt32
# phKey : UINT_PTR* out -> Ptr{Csize_t}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t CryptDeriveKey(
    uintptr_t hProv,
    uint32_t Algid,
    uintptr_t hBaseData,
    uint32_t dwFlags,
    uintptr_t* phKey);
]]
local advapi32 = ffi.load("advapi32")
-- advapi32.CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey)
-- hProv : UINT_PTR
-- Algid : ALG_ID
-- hBaseData : UINT_PTR
-- dwFlags : DWORD
-- phKey : UINT_PTR* out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('ADVAPI32.dll');
const CryptDeriveKey = lib.func('__stdcall', 'CryptDeriveKey', 'int32_t', ['uintptr_t', 'uint32_t', 'uintptr_t', 'uint32_t', 'uintptr_t *']);
// CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey)
// hProv : UINT_PTR -> 'uintptr_t'
// Algid : ALG_ID -> 'uint32_t'
// hBaseData : UINT_PTR -> 'uintptr_t'
// dwFlags : DWORD -> 'uint32_t'
// phKey : UINT_PTR* out -> 'uintptr_t *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("ADVAPI32.dll", {
  CryptDeriveKey: { parameters: ["usize", "u32", "usize", "u32", "pointer"], result: "i32" },
});
// lib.symbols.CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey)
// hProv : UINT_PTR -> "usize"
// Algid : ALG_ID -> "u32"
// hBaseData : UINT_PTR -> "usize"
// dwFlags : DWORD -> "u32"
// phKey : UINT_PTR* out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t CryptDeriveKey(
    size_t hProv,
    uint32_t Algid,
    size_t hBaseData,
    uint32_t dwFlags,
    size_t* phKey);
C, "ADVAPI32.dll");
// $ffi->CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey);
// hProv : UINT_PTR
// Algid : ALG_ID
// hBaseData : UINT_PTR
// dwFlags : DWORD
// 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 CryptDeriveKey(
        long hProv,   // UINT_PTR
        int Algid,   // ALG_ID
        long hBaseData,   // UINT_PTR
        int dwFlags,   // DWORD
        LongByReference phKey   // UINT_PTR* out
    );
}
@[Link("advapi32")]
lib LibADVAPI32
  fun CryptDeriveKey = CryptDeriveKey(
    hProv : LibC::SizeT,   # UINT_PTR
    Algid : UInt32,   # ALG_ID
    hBaseData : LibC::SizeT,   # UINT_PTR
    dwFlags : UInt32,   # DWORD
    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 CryptDeriveKeyNative = Int32 Function(UintPtr, Uint32, UintPtr, Uint32, Pointer<UintPtr>);
typedef CryptDeriveKeyDart = int Function(int, int, int, int, Pointer<UintPtr>);
final CryptDeriveKey = DynamicLibrary.open('ADVAPI32.dll')
    .lookupFunction<CryptDeriveKeyNative, CryptDeriveKeyDart>('CryptDeriveKey');
// hProv : UINT_PTR -> UintPtr
// Algid : ALG_ID -> Uint32
// hBaseData : UINT_PTR -> UintPtr
// dwFlags : DWORD -> Uint32
// phKey : UINT_PTR* out -> Pointer<UintPtr>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CryptDeriveKey(
  hProv: NativeUInt;   // UINT_PTR
  Algid: DWORD;   // ALG_ID
  hBaseData: NativeUInt;   // UINT_PTR
  dwFlags: DWORD;   // DWORD
  phKey: Pointer   // UINT_PTR* out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptDeriveKey';
import Foreign
import Foreign.C.Types
import Foreign.C.String

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

let cryptderivekey =
  foreign "CryptDeriveKey"
    (size_t @-> uint32_t @-> size_t @-> uint32_t @-> (ptr size_t) @-> returning int32_t)
(* hProv : UINT_PTR -> size_t *)
(* Algid : ALG_ID -> uint32_t *)
(* hBaseData : UINT_PTR -> size_t *)
(* dwFlags : DWORD -> 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 ("CryptDeriveKey" crypt-derive-key :convention :stdcall) :int32
  (h-prov :uint64)   ; UINT_PTR
  (algid :uint32)   ; ALG_ID
  (h-base-data :uint64)   ; UINT_PTR
  (dw-flags :uint32)   ; DWORD
  (ph-key :pointer))   ; UINT_PTR* out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CryptDeriveKey = Win32::API::More->new('ADVAPI32',
    'BOOL CryptDeriveKey(WPARAM hProv, DWORD Algid, WPARAM hBaseData, DWORD dwFlags, LPVOID phKey)');
# my $ret = $CryptDeriveKey->Call($hProv, $Algid, $hBaseData, $dwFlags, $phKey);
# hProv : UINT_PTR -> WPARAM
# Algid : ALG_ID -> DWORD
# hBaseData : UINT_PTR -> WPARAM
# dwFlags : DWORD -> DWORD
# phKey : UINT_PTR* out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

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