CryptGenKey 函式 (wincrypt.h)

重要 此 API 已被取代。 新的和現有的軟體應該開始使用 密碼編譯新一代 API。 Microsoft 可能會在未來的版本中移除此 API。
 
CryptGenKey 函式會產生隨機密碼編譯會話密鑰公開/私鑰組。 在 phKey 中會傳回金鑰或金鑰組的句柄。 然後,此句柄可以視需要與任何需要密鑰句柄的 CryptoAPI 函式搭配使用。

呼叫應用程式必須在呼叫此函式時指定演算法。 由於此演算法類型會與金鑰一起保留,因此當執行實際的密碼編譯作業時,應用程式不需要稍後指定演算法。

語法

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,請使用下列其中一個值。

意義
CALG_DH_EPHEM
指定「暫時」Diffie-Hellman 鍵。
CALG_DH_SF
指定金鑰 Diffie-Hellman「儲存和轉寄」。
 

除了產生 對稱演算法的會話密鑰之外,此函式也可以產生 公用/私鑰組。 每個 CryptoAPI 用戶端通常會擁有兩個公開/私鑰組。 若要產生其中一個金鑰組,請將 Algid 參數設定為下列其中一個值。

意義
AT_KEYEXCHANGE
金鑰交換
AT_SIGNATURE
數位簽章
 
注意 指定金鑰規格AT_KEYEXCHANGE和AT_SIGNATURE時,用來產生金鑰的演演算法識別碼取決於使用的提供者。 因此,針對這些索引鍵規格,當指定 KP_ALGID 參數時, 從 CryptGetKeyParam (傳回的值) 取決於使用的提供者。 若要判斷不同提供者針對密鑰規格AT_KEYEXCHANGE和AT_SIGNATURE所使用的演算法識別碼,請參閱 ALG_ID
 

[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 位可以是零或下列一或多個值的組合。

意義
CRYPT_ARCHIVABLE
如果設定此旗標,則可以匯出索引鍵,直到呼叫 CryptDestroyKey 關閉其句柄為止。 這可讓新產生的金鑰在建立時匯出以進行封存或密鑰復原。 關閉句柄之後,就無法再匯出密鑰。
CRYPT_CREATE_IV
未使用這個旗標。
CRYPT_CREATE_SALT
如果設定此旗標,則會自動將索引鍵指派為隨機 Salt 值 。 您可以使用 CryptGetKeyParam 函式來擷取此 salt 值,並將 dwParam 參數設定為 KP_SALT。

如果未設定此旗標,則會將索引鍵指定為零的 salt 值。

當透過 CryptExportKey) (匯出具有非零 salt 值的索引鍵時,也必須取得 salt 值 ,並與 密鑰 BLOB 一起保存。

CRYPT_DATA_KEY
未使用這個旗標。
CRYPT_EXPORTABLE
如果設定此旗標,則可以使用 CryptExportKey 函式,將密鑰從 CSP 傳輸到密鑰 BLOB。 因為會話金鑰通常必須是可導出的,所以建立時通常應該設定此旗標。

如果未設定此旗標,則索引鍵無法匯出。 對於會話金鑰,這表示金鑰只能在目前的會話內使用,而且只有建立密鑰的應用程式才能使用它。 對於 公開/私鑰組,這表示私鑰無法傳輸或備份。

此旗標僅適用於會話金鑰和 私鑰 BLOB。 它不適用於一律可導出的公鑰。

CRYPT_FORCE_KEY_PROTECTION_HIGH
此旗標會指定強式密鑰保護。 設定此旗標時,系統會提示使用者在建立金鑰時輸入金鑰的密碼。 每當使用此金鑰時,系統會提示使用者輸入密碼。

此旗標僅供 Microsoft 提供的 CSP 使用。 第三方 CSP 會定義自己的強密鑰保護行為。

指定此旗標會導致在系統登錄中指定強鍵保護時,使用 CRYPT_USER_PROTECTED 旗標呼叫此函式相同的結果。

如果指定這個旗標,而且 hProv 參數中的提供者句柄是使用 CRYPT_VERIFYCONTEXTCRYPT_SILENT 旗標建立的,則此函式會將最後一個錯誤設定為 NTE_SILENT_CONTEXT 並傳回零。

Windows Server 2003 和 Windows XP: 不支援此旗標。

CRYPT_KEK
未使用這個旗標。
CRYPT_INITIATOR
未使用這個旗標。
CRYPT_NO_SALT
此旗標指定不會為四十位對稱密鑰配置任何 salt 值。 如需詳細資訊,請參閱 Salt 值功能
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
未使用這個旗標。

[out] phKey

函式複製新產生之金鑰句柄的位址。 當您完成使用金鑰時,請呼叫 CryptDestroyKey 函式來刪除金鑰的句柄。

傳回值

如果成功或零,則傳回非零。

如需擴充的錯誤資訊,請呼叫 GetLastError

開頭為 「NTE」 的錯誤碼是由所使用的特定 CSP 所產生。 下表列出一些可能的錯誤碼。

傳回碼 Description
ERROR_INVALID_HANDLE
其中一個參數指定無效的句柄。
ERROR_INVALID_PARAMETER
其中一個參數包含無效的值。 這通常是無效的指標。
NTE_BAD_ALGID
Algid 參數會指定此 CSP 不支持的演算法。
NTE_BAD_FLAGS
dwFlags 參數包含無效的值。
NTE_BAD_UID
hProv 參數不包含有效的內容句柄。
NTE_FAIL
函式會以非預期的方式失敗。
NTE_SILENT_CONTEXT
提供者無法執行動作,因為內容是以無訊息方式取得。

備註

如果為 對稱區塊加密產生密鑰,則密鑰預設會設定為加密 區塊鏈結 (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

另請參閱

CryptAcquireContext

CryptDestroyKey

CryptExportKey

CryptGetKeyParam

CryptImportKey

CryptSetKeyParam

金鑰產生和 Exchange 函式

密碼編譯服務提供者的線程問題