CryptGenKey 函式 (wincrypt.h)
呼叫應用程式必須在呼叫此函式時指定演算法。 由於此演算法類型會與金鑰一起保留,因此當執行實際的密碼編譯作業時,應用程式不需要稍後指定演算法。
語法
BOOL CryptGenKey(
[in] HCRYPTPROV hProv,
[in] ALG_ID Algid,
[in] DWORD dwFlags,
[out] HCRYPTKEY *phKey
);
參數
[in] hProv
呼叫 CryptAcquireContext 所建立的密碼編譯服務提供者 (CSP) 句柄。
[in] Algid
識別要產生索引鍵之演算法 的ALG_ID 值。 此參數的值會因使用的 CSP 而有所不同。
如需 與 Microsoft 基底密碼編譯提供者搭配使用的ALG_ID值,請參閱 基底提供者演算法。
如需 要 與 Microsoft 強式密碼編譯提供者或 Microsoft 增強式密碼編譯提供者搭配使用的ALG_ID值,請參閱 增強提供者演算法。
針對 Diffie-Hellman CSP,請使用下列其中一個值。
值 | 意義 |
---|---|
|
指定「暫時」Diffie-Hellman 鍵。 |
|
指定金鑰 Diffie-Hellman「儲存和轉寄」。 |
除了產生 對稱演算法的會話密鑰之外,此函式也可以產生 公用/私鑰組。 每個 CryptoAPI 用戶端通常會擁有兩個公開/私鑰組。 若要產生其中一個金鑰組,請將 Algid 參數設定為下列其中一個值。
值 | 意義 |
---|---|
|
金鑰交換 |
|
數位簽章 |
[in] dwFlags
指定產生的金鑰類型。 產生金鑰時,可以設定會話金鑰、RSA 簽章金鑰和 RSA 金鑰 交換金鑰 的大小。 代表位中索引鍵模數長度的索引鍵大小會以此參數的上限 16 位設定。 因此,如果要產生 2,048 位 RSA 簽章密鑰,則值0x08000000會與任何其他 dwFlags 預先定義值搭配位 OR 運算結合。 0x08000000的上限 16 位是0x0800或十進位 2,048。 RSA1024BIT_KEY值可用來指定 1024 位 RSA 金鑰。
由於變更匯出控制限制,預設 CSP 和預設 金鑰長度 可能會在作業系統版本之間變更。 加密和解密都必須使用相同的 CSP,以及使用 dwFlags 參數明確設定密鑰長度,以確保不同作業系統平臺上的互操作性。
特別是,預設 RSA 完整密碼編譯服務提供者是 Microsoft RSA 強式密碼編譯提供者。 默認 DSS 簽章 Diffie-Hellman 密碼編譯服務提供者是 Microsoft 增強型 DSS Diffie-Hellman 密碼編譯提供者。 這些 CSP 都有 RC2 和 RC4 的預設 128 位對稱密鑰長度,以及公鑰演演算法的 1,024 位預設密鑰長度。
如果上限 16 位為零,則會產生預設金鑰大小。 如果指定大於最大值或小於最小值的索引鍵,則呼叫會失敗並出現ERROR_INVALID_PARAMETER程序代碼。
下表列出從 Windows XP 開始的最小、預設和最大簽章和交換密鑰長度。
金鑰類型和提供者 | 最小長度 | 默認長度 | 長度上限 |
---|---|---|---|
RSA 基底提供者 簽章和 ExchangeKeys |
384 | 512 | 16,384 |
RSA 強式和增強式提供者 簽章和 Exchange 金鑰 |
384 | 1,024 | 16,384 |
DSS 基底提供者 簽章金鑰 |
512 | 1,024 | 1,024 |
DSS 基底提供者 Exchange 金鑰 |
不適用 | 不適用 | 不適用 |
DSS/DH 基底提供者 簽章金鑰 |
512 | 1,024 | 1,024 |
DSS/DH 基底提供者 Exchange 金鑰 |
512 | 512 | 1,024 |
DSS/DH 增強提供者 簽章金鑰 |
512 | 1,024 | 1,024 |
DSS/DH 增強提供者 Exchange 金鑰 |
512 | 1,024 | 4,096 |
如需會話密鑰長度,請參閱 CryptDeriveKey。
如需使用 Microsoft 提供者產生的金鑰詳細資訊,請參閱 Microsoft 密碼編譯服務提供者。
此參數的較低 16 位可以是零或下列一或多個值的組合。
值 | 意義 |
---|---|
|
如果設定此旗標,則可以匯出索引鍵,直到呼叫 CryptDestroyKey 關閉其句柄為止。 這可讓新產生的金鑰在建立時匯出以進行封存或密鑰復原。 關閉句柄之後,就無法再匯出密鑰。 |
|
未使用這個旗標。 |
|
如果設定此旗標,則會自動將索引鍵指派為隨機 Salt 值 。 您可以使用 CryptGetKeyParam 函式來擷取此 salt 值,並將 dwParam 參數設定為 KP_SALT。
如果未設定此旗標,則會將索引鍵指定為零的 salt 值。 當透過 CryptExportKey) (匯出具有非零 salt 值的索引鍵時,也必須取得 salt 值 ,並與 密鑰 BLOB 一起保存。 |
|
未使用這個旗標。 |
|
如果設定此旗標,則可以使用 CryptExportKey 函式,將密鑰從 CSP 傳輸到密鑰 BLOB。 因為會話金鑰通常必須是可導出的,所以建立時通常應該設定此旗標。
如果未設定此旗標,則索引鍵無法匯出。 對於會話金鑰,這表示金鑰只能在目前的會話內使用,而且只有建立密鑰的應用程式才能使用它。 對於 公開/私鑰組,這表示私鑰無法傳輸或備份。 此旗標僅適用於會話金鑰和 私鑰 BLOB。 它不適用於一律可導出的公鑰。 |
|
此旗標會指定強式密鑰保護。 設定此旗標時,系統會提示使用者在建立金鑰時輸入金鑰的密碼。 每當使用此金鑰時,系統會提示使用者輸入密碼。
此旗標僅供 Microsoft 提供的 CSP 使用。 第三方 CSP 會定義自己的強密鑰保護行為。 指定此旗標會導致在系統登錄中指定強鍵保護時,使用 CRYPT_USER_PROTECTED 旗標呼叫此函式相同的結果。 如果指定這個旗標,而且 hProv 參數中的提供者句柄是使用 CRYPT_VERIFYCONTEXT 或 CRYPT_SILENT 旗標建立的,則此函式會將最後一個錯誤設定為 NTE_SILENT_CONTEXT 並傳回零。 Windows Server 2003 和 Windows XP: 不支援此旗標。 |
|
未使用這個旗標。 |
|
未使用這個旗標。 |
|
此旗標指定不會為四十位對稱密鑰配置任何 salt 值。 如需詳細資訊,請參閱 Salt 值功能。 |
|
未使用這個旗標。 |
|
此旗標會指定初始 Diffie-Hellman 或 DSS 金鑰產生。 此旗標僅適用於 Diffie-Hellman 和 DSS CSP。 使用時,除非 在 dwFlags 參數的上限 16 位中指定密鑰長度,否則會使用預設密鑰長度。 如果使用 CryptSetKeyParam 在 PREGEN Diffie-Hellman 或 DSS 金鑰上設定涉及金鑰長度的參數,密鑰長度必須與此處設定的金鑰長度相容。 |
|
未使用這個旗標。 |
|
未使用這個旗標。 |
|
未使用這個旗標。 |
|
如果設定此旗標,當用戶嘗試使用此金鑰時,會透過對話方塊或其他方法通知使用者。 精確的行為是由所使用的 CSP 所指定。 如果提供者內容是以設定CRYPT_SILENT旗標開啟,則使用此旗標會導致失敗,並將最後一個錯誤設定為 NTE_SILENT_CONTEXT。 |
|
未使用這個旗標。 |
[out] phKey
函式複製新產生之金鑰句柄的位址。 當您完成使用金鑰時,請呼叫 CryptDestroyKey 函式來刪除金鑰的句柄。
傳回值
如果成功或零,則傳回非零。
如需擴充的錯誤資訊,請呼叫 GetLastError。
開頭為 「NTE」 的錯誤碼是由所使用的特定 CSP 所產生。 下表列出一些可能的錯誤碼。
傳回碼 | Description |
---|---|
|
其中一個參數指定無效的句柄。 |
|
其中一個參數包含無效的值。 這通常是無效的指標。 |
|
Algid 參數會指定此 CSP 不支持的演算法。 |
|
dwFlags 參數包含無效的值。 |
|
hProv 參數不包含有效的內容句柄。 |
|
函式會以非預期的方式失敗。 |
|
提供者無法執行動作,因為內容是以無訊息方式取得。 |
備註
如果為 對稱區塊加密產生密鑰,則密鑰預設會設定為加密 區塊鏈結 (CBC) 模式,其初始化向量為零。 此 加密模式 提供良好的預設方法來大量加密數據。 若要變更這些參數,請使用 CryptSetKeyParam 函式。
若要選擇適當的 金鑰長度,建議使用下列方法:
- 列舉 CSP 支援的演算法,並取得每個演算法的最大和最小密鑰長度。 若要這樣做,請使用 PP_ENUMALGS_EX 呼叫 CryptGetProvParam 。
- 使用最小和最大長度來選擇適當的密鑰長度。 不一定建議選擇最大長度,因為這可能會導致效能問題。
- 選擇所需的金鑰長度之後,請使用 dwFlags 參數的上限 16 位來指定金鑰長度。
範例
下列範例示範如何建立隨機會話密鑰。 如需包含此範例完整內容的範例,請參閱 範例 C 程式:加密檔案。 如需使用此函式的另一個範例,請參閱 範例 C 程式:解密檔案。
//-------------------------------------------------------------------
// 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);
}
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows XP [僅限傳統型應用程式] |
最低支援的伺服器 | Windows Server 2003 [僅限桌面應用程式] |
目標平台 | Windows |
標頭 | wincrypt.h |
程式庫 | Advapi32.lib |
Dll | Advapi32.dll |
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應