OpenSSL

密碼學和 SSL/TLS 工具組

migration_guide

名稱

ossl-guide-migration、migration_guide - OpenSSL 指南:從舊版 OpenSSL 版本進行移轉

語法

有關詳細資訊,請參閱個別手冊頁面。

說明

本指南詳述移轉至新版 OpenSSL 所需的變更。目前涵蓋 OpenSSL 3.0 和 3.1。有關早期版本,請參閱 https://github.com/openssl/openssl/blob/master/CHANGES.md。有關 OpenSSL 3.0 中引入的一些主要概念的概觀,請參閱 crypto(7)

OPENSSL 3.1

OpenSSL 3.0 的主要變更

OpenSSL 3.1 中的 FIPS 提供者包含一些未經 FIPS 驗證的演算法,因此屬性查詢 fips=yes 對想要以 FIPS 核准方式運作的應用程式是必要的。這些演算法為

三重 DES ECB
三重 DES CBC
EdDSA

自 OpenSSL 3.0 以來,沒有其他變更需要額外的移轉措施。

OPENSSL 3.0

OpenSSL 1.1.1 的主要變更

主要版本

OpenSSL 3.0 是主要版本,因此任何目前使用舊版 OpenSSL 的應用程式至少需要重新編譯才能與新版搭配使用。我們的目標是,如果這些應用程式先前與 OpenSSL 1.1.1 搭配使用,絕大多數應用程式將可以在 OpenSSL 3.0 中不變更地運作。不過,這並非保證,某些情況下可能需要進行一些變更。如果應用程式需要利用 OpenSSL 3.0 中的一些新功能,例如 FIPS 模組的可用性,則也可能需要進行變更。

授權變更

在先前版本中,OpenSSL 是在 雙重 OpenSSL 和 SSLeay 授權 下授權(兩個授權都適用)。從 OpenSSL 3.0 開始,這已改為 Apache 授權 v2

提供者和 FIPS 支援

OpenSSL 1.1.1 的主要變更之一是 Provider 概念的引入。Provider 會收集並提供演算法實作。使用 OpenSSL 3.0,您可以透過程式設計或設定檔指定您想要在任何特定應用程式中使用的 Provider。OpenSSL 3.0 預設附帶 5 個不同的 Provider。隨著時間推移,第三方可能會發行其他 Provider,這些 Provider 可以插入 OpenSSL。所有透過 Provider 提供的演算法實作都是透過「高階」API(例如以 EVP 為字首的函式)存取。無法使用 「低階 API」 存取這些實作。

可用的標準 Provider 之一是 FIPS Provider。這會提供 FIPS 驗證的加密演算法。FIPS Provider 預設為停用,需要在組態時間使用 enable-fips 選項明確啟用。如果啟用,FIPS Provider 會在其他標準 Provider 之外建置並安裝。不需要個別的安裝程序。不過,有一個專用的 install_fips make 目標,其特殊用途是僅將 FIPS Provider 安裝到現有的 OpenSSL 安裝中。

並非所有演算法在特定時刻都對應用程式可用。如果應用程式程式碼透過 EVP 介面使用任何摘要或密碼演算法,應用程式應驗證 EVP_EncryptInit(3)EVP_EncryptInit_ex(3)EVP_DigestInit(3) 函式的結果。如果要求的演算法不可用,這些函式會失敗。

另請參閱 「舊版演算法」 以取得有關舊版 Provider 的資訊。

另請參閱 「完成 FIPS 模組的安裝」「在應用程式中使用 FIPS 模組」

低階 API

OpenSSL 過去提供兩組 API 來呼叫加密演算法:「高階」API(例如 EVP API)和「低階」API。高階 API 通常設計為可跨所有演算法類型運作。「低階」API 則針對特定演算法實作。例如,EVP API 提供函式 EVP_EncryptInit_ex(3)EVP_EncryptUpdate(3)EVP_EncryptFinal(3) 來執行對稱式加密。這些函式可與演算法 AES、CHACHA、3DES 等一起使用。另一方面,若要使用低階 API 進行 AES 加密,您必須呼叫 AES 特定函式,例如 AES_set_encrypt_key(3)AES_encrypt(3) 等。3DES 的函式不同。OpenSSL 開發團隊長期以來非正式地不鼓勵使用低階 API。不過,在 OpenSSL 3.0 中,這變得更加正式。所有這些低階 API 都已標示為已棄用。您仍可以在應用程式中使用它們,但您可能會在編譯期間看到棄用警告(取決於編譯器對此的支援)。已棄用的 API 可能會從未來的 OpenSSL 版本中移除,因此強烈建議您更新程式碼以改用高階 API。

這在 「低階函式的棄用」 中有更詳細的說明。

舊式演算法

某些透過 EVP API 可用的密碼演算法,例如 MD2DES,現在被視為舊式演算法,強烈建議不要使用。這些舊式 EVP 演算法仍可在 OpenSSL 3.0 中使用,但並非預設。如果您想使用它們,則必須載入舊式提供者。這可能只要變更設定檔即可,也可以透過程式設計方式進行。請參閱 OSSL_PROVIDER-legacy(7) 以取得演算法的完整清單。使用 EVP API 來存取這些演算法的應用程式應改用較新的演算法。如果無法這麼做,則這些應用程式應確保已載入舊式提供者。這可以透過程式設計方式或透過設定檔來達成。請參閱 crypto(7) 手冊頁面以取得有關提供者的更多資訊。

引擎和「METHOD」API

支援提供者的重構在內部與用於支援引擎的 API 發生衝突,包括 ENGINE API 和任何建立或修改自訂「METHODS」的函式(例如 EVP_MD_meth_new(3)EVP_CIPHER_meth_new(3)EVP_PKEY_meth_new(3)RSA_meth_new(3)EC_KEY_METHOD_new(3) 等)。這些函式在 OpenSSL 3.0 中已不建議使用,而這些 API 的使用者應知道使用它們可能會繞過提供者選取和設定,造成意想不到的後果。這與撰寫為使用 OpenSSL 3.0 FIPS 模組的應用程式特別相關,如下所述。強烈建議外部引擎的作者和維護人員重構他們的程式碼,使用新的提供者 API 將引擎轉換為提供者,並避免使用不建議使用的函式。

支援舊式引擎

如果 openssl 未在沒有引擎支援或不建議使用 API 支援的情況下建置,則引擎仍可運作。但是,它們的適用性將受到限制。

透過引擎提供的新的演算法仍可運作。

可透過自訂 OSSL_STORE 實作載入引擎支援的密鑰。在這種情況下,透過 ENGINE_load_private_key(3) 建立的 EVP_PKEY 物件將被視為舊式,且將繼續運作。

為確保未來的相容性,應將引擎轉換為提供者。若要優先使用基於提供者的硬體卸載,您可以指定預設屬性以優先使用您的提供者。

設定基於引擎或基於應用程式的預設低階加密方法(例如 RSA_METHODEC_KEY_METHOD)仍然可行,而預設提供者中的金鑰會使用基於引擎的實作來執行加密作業。不過,使用 OSSL_DECODERPEM_d2i_ API 解碼建立的 EVP_PKEY 會是基於提供者。若要建立完整的舊版 EVP_PKEY,必須使用 EVP_PKEY_set1_RSA(3)EVP_PKEY_set1_EC_KEY(3) 或類似的函數。

版本編號配置

OpenSSL 版本編號配置已隨 OpenSSL 3.0 發行版變更。新的版本編號配置採用下列格式

主要版本.次要版本.修補程式

對於 OpenSSL 1.1.1 及以下版本,不同的修補程式等級會在發行版本號碼的結尾以字母表示。此方式將不再使用,修補程式等級會改以版本中的最後一個數字表示。第二個數字(次要版本)變更表示可能已新增新功能。主要版本號碼相同的 OpenSSL 版本在 API 和 ABI 上相容。如果主要版本號碼變更,則無法保證 API 和 ABI 相容。

如需更多資訊,請參閱 OpenSSL_version(3)

其他主要新功能
憑證管理通訊協定 (CMP,RFC 4210)

此功能也涵蓋 CRMF (RFC 4211) 和 HTTP 傳輸 (RFC 6712)。請參閱 openssl-cmp(1)OSSL_CMP_exec_certreq(3) 作為入門。

HTTP(S) 用戶端

支援 GET 和 POST、重新導向、一般和 ASN.1 編碼內容、代理伺服器和逾時功能的完整 HTTP(S) 用戶端。

金鑰衍生函數 API (EVP_KDF)

此功能簡化了新增 KDF 和 PRF 實作的程序。

先前 KDF 演算法已硬塞到使用 EVP_PKEY 物件,這並非合乎邏輯的對應。使用 EVP_PKEY (scrypt、TLS1 PRF 和 HKDF) 的 KDF 演算法的現有應用程式可能會比較慢,因為它們在內部使用 EVP_KDF 橋接。所有新的應用程式都應該使用新的 EVP_KDF(3) 介面。另請參閱 OSSL_PROVIDER-default(7) 中的「金鑰衍生函數 (KDF)」OSSL_PROVIDER-FIPS(7) 中的「金鑰衍生函數 (KDF)」

訊息驗證碼 API (EVP_MAC)

此功能簡化了新增 MAC 實作的程序。

這包含一個通用 EVP_PKEY 到 EVP_MAC 橋接,以促進持續使用 MAC 透過原始私鑰在功能中,例如 EVP_DigestSign(3)EVP_DigestVerify(3)

所有新的應用程式都應該使用新的 EVP_MAC(3) 介面。另請參閱 「OSSL_PROVIDER-default(7) 中的訊息驗證碼 (MAC)」「OSSL_PROVIDER-FIPS(7) 中的訊息驗證碼 (MAC)」

演算法擷取

使用對便利功能的呼叫,例如 EVP_sha256() 和 EVP_aes_256_gcm(),在使用提供者時可能會產生效能損失。從提供者擷取演算法涉及透過名稱搜尋演算法。這比直接存取方法表慢很多。建議在演算法被使用多次時預先擷取演算法。請參閱 「crypto(7) 中的效能」「crypto(7) 中的明確擷取」「crypto(7) 中的隱含擷取」

支援 Linux Kernel TLS

為了使用 KTLS,必須使用 enable-ktls 組態選項編譯支援。它也必須在執行時使用 SSL_OP_ENABLE_KTLS 選項啟用。

新演算法
  • KDF 演算法「單步驟」和「SSH」

    請參閱 EVP_KDF-SS(7)EVP_KDF-SSHKDF(7)

  • MAC 演算法「GMAC」和「KMAC」

    請參閱 EVP_MAC-GMAC(7)EVP_MAC-KMAC(7)

  • KEM 演算法「RSASVE」

    請參閱 EVP_KEM-RSA(7)

  • 加密演算法「AES-SIV」

    請參閱 「EVP_EncryptInit(3) 中的 SIV 模式」

  • EVP 層支援的 AES 金鑰包裝反向加密。

    反向加密使用 AES 解密進行包裝,並使用 AES 加密進行解包裝。演算法為:「AES-128-WRAP-INV」、「AES-192-WRAP-INV」、「AES-256-WRAP-INV」、「AES-128-WRAP-PAD-INV」、「AES-192-WRAP-PAD-INV」和「AES-256-WRAP-PAD-INV」。

  • 新增 CTS 加密到 EVP 層。

    演算法為:「AES-128-CBC-CTS」、「AES-192-CBC-CTS」、「AES-256-CBC-CTS」、「CAMELLIA-128-CBC-CTS」、「CAMELLIA-192-CBC-CTS」和「CAMELLIA-256-CBC-CTS」。支援 CS1、CS2 和 CS3 變體。

CMS 和 PKCS#7 更新
  • 新增 CAdES-BES 簽章驗證支援。

  • 新增 CAdES-BES 簽章配置和屬性支援 (RFC 5126) 至 CMS API。

  • 新增 AuthEnvelopedData 內容類型結構 (RFC 5083) 使用 AES_GCM

    這使用加密訊息語法的 AES-GCM 參數 (RFC 5084)。其目的是支援使用 AES GCM 模式進行驗證和加密的數位信封的加密和解密。

  • PKCS7_get_octet_string(3)PKCS7_type_is_other(3) 已公開。

PKCS#12 API 更新

使用 PKCS12_create() 函式建立 pkcs12 的預設演算法已變更為較新的 PBKDF2 和 AES 為基礎的演算法。預設 MAC 迭代次數已變更為 PKCS12_DEFAULT_ITER,使其等於基於密碼的加密迭代次數。預設摘要演算法已變更為 SHA-256,用於 MAC 計算。pkcs12 應用程式現在支援 -legacy 選項,可還原先前的預設演算法,以支援與舊系統的互通性。

新增接受函式庫內容 OSSL_LIB_CTX 和 (相關時) 屬性查詢的增強 PKCS#12 API。其他處理 PKCS#7 和 PKCS#8 物件的 API 也已在需要時進行增強。這包括

PKCS12_add_key_ex(3), PKCS12_add_safe_ex(3), PKCS12_add_safes_ex(3), PKCS12_create_ex(3), PKCS12_decrypt_skey_ex(3), PKCS12_init_ex(3), PKCS12_item_decrypt_d2i_ex(3), PKCS12_item_i2d_encrypt_ex(3), PKCS12_key_gen_asc_ex(3), PKCS12_key_gen_uni_ex(3), PKCS12_key_gen_utf8_ex(3), PKCS12_pack_p7encdata_ex(3), PKCS12_pbe_crypt_ex(3), PKCS12_PBE_keyivgen_ex(3), PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(3), PKCS5_pbe2_set_iv_ex(3), PKCS5_pbe_set0_algor_ex(3), PKCS5_pbe_set_ex(3), PKCS5_pbkdf2_set_ex(3), PKCS5_v2_PBE_keyivgen_ex(3), PKCS5_v2_scrypt_keyivgen_ex(3), PKCS8_decrypt_ex(3), PKCS8_encrypt_ex(3), PKCS8_set0_pbe_ex(3).

作為此變更的一部分,EVP_PBE_xxx API 也能接受函式庫內容和屬性查詢,並會呼叫支援這些參數的金鑰/IV 衍生函式的延伸版本。這包括 EVP_PBE_CipherInit_ex(3), EVP_PBE_find_ex(3)EVP_PBE_scrypt_ex(3)

PKCS#12 KDF 與 FIPS

與 1.x.y 不同,當 PKCS#12 結構使用與 FIPS 提供者不符的 MAC 建立時,所使用的 PKCS12KDF 演算法並非 FIPS 可核准的機制。

請參閱 EVP_KDF-PKCS12KDF(7)PKCS12_create(3)openssl-pkcs12(1)OSSL_PROVIDER-FIPS(7)

Windows 執行緒同步變更

Windows 執行緒同步在作業系統支援時使用讀寫原語 (SRWLock),否則會繼續使用 CriticalSection。

追蹤 API

已新增一個新的通用追蹤 API,提供透過追蹤輸出啟用儀器的支援。此功能主要作為開發人員的輔助工具,且預設為停用。若要使用它,OpenSSL 需要使用 enable-trace 選項進行設定。

如果已啟用追蹤 API,應用程式可以透過將 BIO 註冊為追蹤頻道來啟用追蹤輸出,以進行多項追蹤和除錯類別。請參閱 OSSL_trace_enabled(3)

金鑰驗證更新

EVP_PKEY_public_check(3)EVP_PKEY_param_check(3) 現在可支援更多金鑰類型。這包括 RSA、DSA、ED25519、X25519、ED448 和 X448。先前 (在 1.1.1 中),它們會傳回 -2。對於沒有參數的金鑰類型,EVP_PKEY_param_check(3) 會永遠傳回 1。

其他值得注意的非建議事項和變更
OpenSSL 錯誤碼的功能碼部分不再相關

此碼現在永遠設定為零。相關功能已非建議使用。

已清理 STACK 和 HASH 巨集

類型安全包裝器已在各處宣告,並實作一次。請參閱 DEFINE_STACK_OF(3)DEFINE_LHASH_OF_EX(3)

已移除 RAND_DRBG 子系統

新的 EVP_RAND(3) 是部分替代品:不包含 DRBG 回呼架構。RAND_DRBG API 不太符合 EVP_RAND 和 EVP_RAND_CTX 實作的新提供者概念。

已移除 FIPS_mode() 和 FIPS_mode_set()

這些功能是舊版 API,不適用於新的提供者模型。應用程式應改用 EVP_default_properties_is_fips_enabled(3)EVP_default_properties_enable_fips(3)

金鑰產生較慢

Miller-Rabin 測試現在使用 64 輪,用於所有質數產生,包括 RSA 金鑰產生。這會影響較大金鑰大小的時間。

一般 2 質數 RSA 金鑰的預設金鑰產生方法已變更為 FIPS186-4 B.3.6 方法 (基於輔助可能質數的可能質數產生)。此方法比原始方法慢。

將 PBKDF2 變更為符合 SP800-132,而不是較舊的 PKCS5 RFC2898

這會檢查 salt 長度至少為 128 位元、衍生金鑰長度至少為 112 位元,以及迭代次數至少為 1000。為了向後相容性,這些檢查在預設提供者中預設為停用,但在 FIPS 提供者中預設為啟用。

若要啟用或停用檢查,請參閱 EVP_KDF-PBKDF2(7) 中的 OSSL_KDF_PARAM_PKCS5。可以使用 EVP_KDF_derive(3) 設定參數。

強制執行最小 DH 模數大小為 512 位元

較小的尺寸現在會導致錯誤。

SM2 金鑰變更

具有 SM2 曲線的 EC EVP_PKEY 已重新設計,以自動變成 EVP_PKEY_SM2,而不是 EVP_PKEY_EC。

與先前 OpenSSL 版本不同,這表示應用程式無法呼叫 EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2) 來取得 SM2 計算。

參數和金鑰產生也已重新設計,以產生 EVP_PKEY_SM2 參數和金鑰。應用程式現在必須直接產生 SM2 金鑰,並且不能先建立 EVP_PKEY_EC 金鑰。不再能夠匯入具有 SM2 橢圓曲線以外的網域參數的 SM2 金鑰。

SM2 金鑰驗證已與一般 EC 金鑰驗證分開,允許改善 SM2 驗證程序,以拒絕載入不符合 SM2 ISO 標準的私密金鑰。特別是,現在會正確拒絕範圍 1 <= k < n-1 以外的私密純量 k

已移除 EVP_PKEY_set_alias_type() 方法

此函式會在設定 EVP_PKEY 物件後使其可變。在 OpenSSL 3.0 中,已決定提供的金鑰不應能夠變更其類型,因此已移除此函式。

傳回內部金鑰的函式應視為唯讀

例如 EVP_PKEY_get0_RSA(3) 等函式在 OpenSSL 3.0 中的行為略有不同。先前,它們會傳回 libcrypto 內部使用的低階金鑰指標。從 OpenSSL 3.0 開始,此金鑰現在可能會儲存在提供者中。呼叫這些函式只會傳回內部金鑰的控制代碼,而 EVP_PKEY 最初使用此金鑰建構,例如使用 EVP_PKEY_assign_RSA(3)EVP_PKEY_set1_RSA(3) 等函式或巨集。如果 EVP_PKEY 握有提供者管理的金鑰,則這些函式現在會傳回金鑰的快取副本。在首次存取快取金鑰後發生的內部提供者金鑰變更不會反映在快取副本中。同樣地,應用程式程式碼對快取副本所做的任何變更也不會反映在內部提供者金鑰中。

由於上述原因,通常應將這些函式傳回的金鑰視為唯讀。為了強調這一點,EVP_PKEY_get0_RSA(3)EVP_PKEY_get0_DSA(3)EVP_PKEY_get0_EC_KEY(3)EVP_PKEY_get0_DH(3) 傳回的值已設為 const。這可能會中斷一些現有程式碼。應修改因這個變更而中斷的應用程式。建議的解決方案是重構程式碼,以避免使用這些已棄用的函式。如果無法做到這一點,應修改程式碼以改用 const 指標。EVP_PKEY_get1_RSA(3)EVP_PKEY_get1_DSA(3)EVP_PKEY_get1_EC_KEY(3)EVP_PKEY_get1_DH(3) 函式會繼續傳回非 const 指標,以使它們能夠「釋放」。但是,它們也應視為唯讀。

公開金鑰檢查已從 EVP_PKEY_derive() 移至 EVP_PKEY_derive_set_peer()

這可能會導致 EVP_PKEY_derive_set_peer(3) 產生錯誤,而不是在 EVP_PKEY_derive(3) 期間產生錯誤。若要停用此檢查,請使用 EVP_PKEY_derive_set_peer_ex(dh, peer, 0)。

列印格式對部分函數進行了美化變更

許多「列印」函數的輸出,例如 X509_signature_print(3)X509_print_ex(3)X509_CRL_print_ex(3) 和其他類似函數,已進行修正,因此 1.1.1 和 3.0 中觀察到的輸出可能存在美化差異。這也適用於 openssl x509openssl crl 應用程式的 -text 輸出。

已移除 openssl 程式中的互動模式

從現在開始,在沒有參數的情況下執行它等同於 openssl help

部分控制呼叫 (ctrl) 的錯誤回傳值已變更

一個重要的變更在於,以前用於對無效輸入回傳 -2 的控制項,現在會回傳 -1,表示一般錯誤狀況。

DH 和 DHX 金鑰類型有不同的可設定參數

以前 (在 1.1.1 中) 允許這些衝突參數,但現在會導致錯誤。請參閱 EVP_PKEY-DH(7) 以取得更多詳細資料。這會影響 openssl-genpkey(1) 產生 DH 參數的行為。

EVP_CIPHER_CTX_set_flags() 排序變更

如果使用提供者的加密,則只能在將加密指定給加密內容後,才能設定 EVP_CIPH_FLAG_LENGTH_BITS 旗標。請參閱 EVP_EncryptInit(3) 中的「FLAGS」 以取得更多資訊。

驗證操作內容參數

由於加密操作的實作已移至提供者,因此各種操作參數的驗證可能會延後到實際操作執行時,而以前則是在設定操作參數時立即發生。

例如,使用 EVP_PKEY_CTX_set_ec_paramgen_curve_nid() 設定不支援的曲線時,此函數呼叫不會失敗,但稍後使用 EVP_PKEY_CTX 的金鑰產生操作會失敗。

從錯誤碼中移除函數代碼

錯誤碼中的函數代碼部分現在總是設定為 0。因此已移除 ERR_GET_FUNC() 巨集。應用程式必須僅使用函式庫編號和原因代碼來解析錯誤碼。

ChaCha20-Poly1305 加密法不允許使用截斷的 IV 長度

在 OpenSSL 3.0 中,將 IV 長度設定為 12 以外的任何值都會導致錯誤。在 OpenSSL 3.0 之前,ivlen 可以小於所需的 12 位元組長度,使用 EVP_CIPHER_CTX_ctrl(ctx, EVP_CRTL_AEAD_SET_IVLEN, ivlen, NULL)。這會導致 IV 具有前導零填充。

安裝和編譯

請參閱發行版頂端的 INSTALL.md 檔案,以取得有關如何建置和安裝 OpenSSL 3.0 的說明。請也參閱針對特定平台的各種 NOTES 檔案,以取得特定平台的說明。

從 OpenSSL 1.1.1 升級

在大部分情況下,從 OpenSSL 1.1.1 升級到 OpenSSL 3.0 應該是相當直接的。最有可能遇到問題的區域是在您的程式碼中使用低階 API(如上所述)。在這種情況下,您在編譯應用程式時可能會開始看到不建議使用的警告。如果發生這種情況,您有 3 個選項

  1. 忽略警告。它們只是警告。不建議使用的函數仍然存在,您仍然可以使用它們。但是請注意,它們可能會從未來的 OpenSSL 版本中移除。

  2. 禁止警告。請參閱您的編譯器文件,了解如何執行此操作。

  3. 移除您對低階 API 的使用。在這種情況下,您需要重新撰寫您的程式碼,以改用高階 API

錯誤碼變更

由於 OpenSSL 3.0 提供了一種全新的編碼器/解碼器機制,用於處理廣泛使用的檔案格式,因此在金鑰載入失敗時檢查特定錯誤原因代碼的應用程式程式碼可能需要更新。

受密碼保護的金鑰可能需要特別注意。如果僅將某些錯誤視為應再次詢問使用者密碼的指標,則值得測試這些場景並處理新相關的代碼。

可能還有更多情況需要特別處理,具體取決於呼叫應用程式程式碼。

從 OpenSSL 1.0.2 升級

從 OpenSSL 1.0.2 升級到 OpenSSL 3.0 可能會顯著困難得多。除了上述「從 OpenSSL 1.1.1 升級」部分中討論的問題外,需要注意的主要事項有

  1. 建置和安裝程序已大幅變更。

    請查看安裝頂端的 INSTALL.md 檔案,以取得有關如何為您的平台建置和安裝 OpenSSL 的說明。另請閱讀同一目錄中的各種 NOTES 檔案,以取得適用於您的平台的說明。

  2. 許多結構已在 OpenSSL 3.0 中變得不透明。

    結構定義已從公開標頭檔案中移除,並移至內部標頭檔案。實際上,這表示您無法再堆疊配置一些結構。相反地,它們必須透過一些函式呼叫來堆疊配置(這些函式名稱通常具有 _new 字尾)。此外,您必須使用「setter」或「getter」函式來存取這些結構中的欄位。

    例如,先前看起來像這樣的程式碼

    EVP_MD_CTX md_ctx;
    
    /* This line will now generate compiler errors */
    EVP_MD_CTX_init(&md_ctx);

    程式碼需要修正,看起來像這樣

    EVP_MD_CTX *md_ctx;
    
    md_ctx = EVP_MD_CTX_new();
    ...
    ...
    EVP_MD_CTX_free(md_ctx);
  3. 已新增對 TLSv1.3 的支援。

    這對 SSL/TLS 應用程式有許多影響。請參閱 TLS1.3 頁面 以取得進一步的詳細資料。

有關 OpenSSL 版本 1.0.2 和 1.1.0 之間重大變更的更多詳細資料,請參閱 OpenSSL 1.1.0 變更頁面

從 OpenSSL 2.0 FIPS 物件模組升級

OpenSSL 2.0 FIPS 物件模組是一個必須個別建置,然後整合到您的主要 OpenSSL 1.0.2 建置中的獨立下載。在 OpenSSL 3.0 中,FIPS 支援已完全整合到 OpenSSL 的主線版本中,不再是獨立下載。如需進一步資訊,請參閱 "完成 FIPS 模組的安裝"

函式呼叫 FIPS_mode() 和 FIPS_mode_set() 已從 OpenSSL 3.0 中移除。您應該重新撰寫應用程式,使其不使用它們。請參閱 fips_module(7)OSSL_PROVIDER-FIPS(7) 以取得詳細資料。

完成 FIPS 模組的安裝

如果已設定 FIPS 支援,FIPS 模組將會自動建置並安裝。目前的說明文件可以在 README-FIPS 檔案中找到。

程式設計

撰寫為與 OpenSSL 1.1.1 搭配使用的應用程式,大多數都只需要搭配 OpenSSL 3.0 使用即可。但是,如果您想要利用 OpenSSL 3.0 提供的一些新功能,則需要進行變更。為此,您需要瞭解 OpenSSL 3.0 中引入的一些新概念。請閱讀 crypto(7) 中的「函式庫內容」 以取得進一步的資訊。

函式庫內容

函式庫內容允許複雜應用程式的不同元件各自使用不同的函式庫內容,並載入具有不同組態設定的不同提供者。請參閱 crypto(7) 中的「函式庫內容」 以取得進一步的資訊。

如果使用者透過 OSSL_LIB_CTX_new(3) 建立 OSSL_LIB_CTX,則可能需要變更許多函式,以傳遞額外的參數來處理函式庫內容。

使用函式庫內容 - 應該變更的舊函式

如果需要函式庫背景,則所有會傳回 const EVP_MD * 的 EVP_* 摘要函式,例如 EVP_sha256(),都應該改用呼叫 EVP_MD_fetch(3)。請參閱 crypto(7) 中的「演算法擷取」

如果需要函式庫背景,則所有會傳回 const EVP_CIPHER * 的 EVP_* 加密函式,例如 EVP_aes_128_cbc(),都應該改用呼叫 EVP_CIPHER_fetch(3)。請參閱 crypto(7) 中的「演算法擷取」

有些函式可以傳入已設定函式庫背景的物件,例如 d2i_X509(3)d2i_X509_CRL(3)d2i_X509_REQ(3)d2i_X509_PUBKEY(3)。如果改為傳入 NULL,則建立的物件會設定為預設函式庫背景。如果需要函式庫背景,請使用 X509_new_ex(3)X509_CRL_new_ex(3)X509_REQ_new_ex(3)X509_PUBKEY_new_ex(3)

下面列出的所有函式,其名稱都有替代函式NAME_ex,後者會將 OSSL_LIB_CTX 當作額外的引數。已對應到其他名稱的函式會列在各自的名稱旁邊。

使用函式庫內容的新函式

如果需要,可以將函式庫內容傳遞給下列函式。傳遞 NULL 會使用預設的函式庫內容。

提供者

提供者在此處有詳細說明 crypto(7) 中的「提供者」。另請參閱 crypto(7) 中的「OPENSSL 提供者」

擷取演算法和屬性查詢

隱式和明確擷取在此處有詳細說明 crypto(7) 中的「演算法擷取」

將 EVP 控制項和旗標對應到提供者 OSSL_PARAM(3) 參數

控制項的現有函式(例如 EVP_CIPHER_CTX_ctrl(3))和操作旗標(例如 EVP_MD_CTX_set_flags(3))在內部使用 OSSL_PARAMS 將資訊傳遞至/從提供者物件。請參閱 OSSL_PARAM(3) 以取得與參數相關的額外資訊。

對於密碼,請參閱 EVP_EncryptInit(3) 中的「控制項」EVP_EncryptInit(3) 中的「旗標」EVP_EncryptInit(3) 中的「參數」

對於摘要,請參閱 EVP_DigestInit(3) 中的「控制項」EVP_DigestInit(3) 中的「旗標」EVP_DigestInit(3) 中的「參數」

低階函式的棄用

在 OpenSSL 3.0 中,大量的 API 已被棄用。本節說明一些常見的棄用類別。請參閱 「已棄用函式對應」 以取得與這些類別相關的已棄用函式清單。

提供者取代引擎和低階方法覆寫

任何使用 ENGINE 的存取器都已棄用(例如 EVP_PKEY_set1_engine())。使用引擎的應用程式應改用提供者。

在新增提供者之前,演算法會透過變更演算法所使用的的方法來覆寫。所有這些方法(例如 RSA_new_method() 和 RSA_meth_new())現在都已棄用,且可用提供者取代。

已棄用的低階金鑰類型 i2d 和 d2i 函式

任何採用低階金鑰類型的 i2d 和 d2i 函式(例如 d2i_DHparams())都已棄用。應用程式應改用 OSSL_DECODER(3)OSSL_ENCODER(3) API 來讀取和寫入檔案。請參閱 d2i_RSAPrivateKey(3) 中的「移轉」 以取得進一步的詳細資料。

已棄用的低階金鑰物件 getter 和 setter

設定或取得低階金鑰物件(例如 EVP_PKEY_set1_DH() 或 EVP_PKEY_get0())的應用程式應改用 OSSL_ENCODER(請參閱 OSSL_ENCODER_to_bio(3))或 OSSL_DECODER(請參閱 OSSL_DECODER_from_bio(3))API,或另用 EVP_PKEY_fromdata(3)EVP_PKEY_todata(3)

已棄用的低階金鑰參數取得函式

直接存取低階物件的函式,例如 RSA_get0_n(3),現已棄用。應用程式應使用 EVP_PKEY_get_bn_param(3)EVP_PKEY_get_int_param(3)、l<EVP_PKEY_get_size_t_param(3)>、EVP_PKEY_get_utf8_string_param(3)EVP_PKEY_get_octet_string_param(3)EVP_PKEY_get_params(3) 之一,以存取 EVP_PKEY 的欄位。可取得的參數列於 EVP_PKEY-RSA(7) 中的「Common RSA parameters」EVP_PKEY-DH(7) 中的「DH parameters」EVP_PKEY-DSA(7) 中的「DSA parameters」EVP_PKEY-FFC(7) 中的「FFC parameters」EVP_PKEY-EC(7) 中的「Common EC parameters」EVP_PKEY-X25519(7) 中的「Common X25519, X448, ED25519 and ED448 parameters」。應用程式也可以使用 EVP_PKEY_todata(3) 來傳回所有欄位。

已棄用的低階金鑰參數設定函式

直接存取低階物件的函式,例如 RSA_set0_crt_params(3),現已棄用。應用程式應使用 EVP_PKEY_fromdata(3) 從使用者提供的金鑰資料建立新的金鑰。一旦建立金鑰,金鑰就應為不可變的,因此在需要時,使用者可以使用 EVP_PKEY_todata(3)OSSL_PARAM_merge(3)EVP_PKEY_fromdata(3) 來建立修改過的金鑰。有關使用參數產生金鑰的資訊,請參閱 EVP_PKEY-DH(7) 中的「範例」。有關使用參數產生金鑰的資訊,請參閱 「已棄用的低階金鑰產生函式」

已棄用的低階物件建立

低階物件是使用 RSA_new(3)RSA_up_ref(3)RSA_free(3) 等方法建立的。應用程式應改用高階 EVP_PKEY API,例如 EVP_PKEY_new(3)EVP_PKEY_up_ref(3)EVP_PKEY_free(3)。另請參閱 EVP_PKEY_CTX_new_from_name(3)EVP_PKEY_CTX_new_from_pkey(3)

EVP_PKEY 可以透過各種方式建立:請參閱 「已棄用的低階金鑰產生函式」「已棄用的低階金鑰讀寫函式」「已棄用的低階金鑰參數設定器」

已棄用的低階加密函式

低階加密函式,例如 AES_encrypt(3)AES_decrypt(3),很長一段時間以來都不建議使用。應用程式應改用高階 EVP API EVP_EncryptInit_ex(3)EVP_EncryptUpdate(3)EVP_EncryptFinal_ex(3),或 EVP_DecryptInit_ex(3)EVP_DecryptUpdate(3)EVP_DecryptFinal_ex(3)

已棄用的低階摘要函式

使用低階摘要函式,例如 SHA1_Init(3),很長一段時間以來都不建議使用。應用程式應改用高階 EVP API EVP_DigestInit_ex(3)EVP_DigestUpdate(3)EVP_DigestFinal_ex(3),或一次性的 EVP_Q_digest(3)

請注意,函式 SHA1(3)SHA224(3)SHA256(3)SHA384(3)SHA512(3) 已變更為使用 EVP_Q_digest(3) 的巨集。

已棄用的低階簽署函式

使用低階簽署函式,例如 DSA_sign(3),很長一段時間以來都不建議使用。應用程式應改用 EVP_DigestSign(3)EVP_DigestVerify(3)。請參閱 EVP_SIGNATURE-RSA(7)EVP_SIGNATURE-DSA(7)EVP_SIGNATURE-ECDSA(7)EVP_SIGNATURE-ED25519(7)

已棄用的低階 MAC 函式

低階 MAC 函式,例如 CMAC_Init(3),已棄用。應用程式應改用新的 EVP_MAC(3) 介面,使用 EVP_MAC_CTX_new(3)EVP_MAC_CTX_free(3)EVP_MAC_init(3)EVP_MAC_update(3)EVP_MAC_final(3) 或一次性的 MAC 函式 EVP_Q_mac(3)。請參閱 EVP_MAC(3)EVP_MAC-HMAC(7)EVP_MAC-CMAC(7)EVP_MAC-GMAC(7)EVP_MAC-KMAC(7)EVP_MAC-BLAKE2(7)EVP_MAC-Poly1305(7)EVP_MAC-Siphash(7) 以取得更多資訊。

請注意,一次性方法 HMAC() 仍可用於相容性目的,但如果需要函式庫內容,也可以改用 EVP_Q_MAC。

已棄用的低階驗證函式

長期以來,已非正式地勸阻使用低階驗證函式,例如 DH_check(3)。應用程式應改用高階 EVP_PKEY API,例如 EVP_PKEY_check(3)EVP_PKEY_param_check(3)EVP_PKEY_param_check_quick(3)EVP_PKEY_public_check(3)EVP_PKEY_public_check_quick(3)EVP_PKEY_private_check(3)EVP_PKEY_pairwise_check(3)

已棄用的低階金鑰交換函式

長期以來,已非正式地勸阻使用許多低階函式。應用程式應改用 EVP_PKEY_derive(3)。請參閱 EVP_KEYEXCH-DH(7)EVP_KEYEXCH-ECDH(7)EVP_KEYEXCH-X25519(7)

已棄用的低階金鑰產生函式

長期以來,已非正式地勸阻使用許多低階函式。應用程式應改用 EVP_PKEY_keygen_init(3)EVP_PKEY_generate(3),如 EVP_PKEY-DSA(7)EVP_PKEY-DH(7)EVP_PKEY-RSA(7)EVP_PKEY-EC(7)EVP_PKEY-X25519(7) 中所述。也可以使用一次性「快速」函式 EVP_PKEY_Q_keygen(3) 和最常見案例的巨集:<EVP_RSA_gen(3)> 和 EVP_EC_gen(3)

已棄用的低階金鑰讀取和寫入函式

長期以來,已非正式地勸阻使用低階物件(例如 DSA)。應取代用於讀取和寫入這些低階物件(例如 PEM_read_DSA_PUBKEY())的函式。應用程式應改用 OSSL_ENCODER_to_bio(3)OSSL_DECODER_from_bio(3)

已棄用的低階金鑰列印函式

長期以來,非正式地不鼓勵使用低階物件(例如 DSA)。應使用等效的 EVP_PKEY 函式取代用於列印這些低階物件的函式,例如 DSA_print()。應用程式應使用 EVP_PKEY_print_public(3)EVP_PKEY_print_private(3)EVP_PKEY_print_params(3)EVP_PKEY_print_public_fp(3)EVP_PKEY_print_private_fp(3)EVP_PKEY_print_params_fp(3) 之一。請注意,內部使用 OSSL_ENCODER_to_bio(3)OSSL_DECODER_from_bio(3)

已棄用的函式對應

下列函式已在 3.0 中棄用。

提供金鑰和演算法的 NID 處理

下列用於 NID(數值 ID)處理的函式已變更語意。

  • EVP_PKEY_id()、EVP_PKEY_get_id()

    此函式先前用於可靠地傳回 EVP_PKEY 物件的 NID,例如,透過呼叫 OBJ_nid2sn(3) 來查詢此類 EVP_PKEY 演算法的名稱。隨著 provider(7) 的推出,EVP_PKEY_id() 或其新的等效函式 EVP_PKEY_get_id(3) 現在也可能會傳回值 -1(EVP_PKEY_KEYMGMT),表示使用提供者來實作 EVP_PKEY 物件。因此,建議使用 EVP_PKEY_get0_type_name(3) 來擷取 EVP_PKEY 演算法的名稱。

在應用程式中使用 FIPS 模組

請參閱 fips_module(7)OSSL_PROVIDER-FIPS(7) 以取得詳細資料。

OpenSSL 命令列應用程式變更

新應用程式

openssl kdf 使用新的 EVP_KDF(3) API。 openssl kdf 使用新的 EVP_MAC(3) API。

新增選項

-provider_path-provider 可用於所有應用程式,且可多次使用以載入任何提供者,例如「舊版」提供者或第三方提供者。如果使用,則在需要時也必須指定「預設」提供者。必須在 -provider 選項之前指定 -provider_path

list 應用程式有許多新選項。請參閱 openssl-list(1) 以取得更多資訊。

openssl ca 使用的 -crl_lastupdate-crl_nextupdate 允許明確設定已產生 CRL 中的欄位。

移除選項

互動模式不再可用。

openssl passwd 使用的 -crypt 選項。openssl x509openssl dhparamopenssl dsaparamopenssl ecparam 使用的 -c 選項。

其他變更

命令列應用程式的輸出可能會有小幅變更。這些變更主要是大小寫和空白。不過,在某些情況下,會有其他差異。例如,openssl dhparam 輸出的 DH 參數現在會列出「P」、「Q」、「G」和「pcounter」,而不是「質數」、「產生器」、「子群組順序」和「計數器」。

現在,讀取金鑰、憑證和 CRL 的 openssl 指令會自動偵測輸入檔案的 PEM 或 DER 格式,因此不再需要明確指定輸入格式。不過,如果使用輸入格式選項,則會需要指定的格式。

openssl speed 不再使用低階 API 呼叫。這表示某些效能數字可能無法與先前版本相比較,因為會產生較高的開銷。這特別適用於測量較小資料區塊的效能。

b<openssl dhparam>、openssl dsaopenssl gendsaopenssl dsaparamopenssl genrsaopenssl rsa 已修改為使用 PKEY API。openssl genrsaopenssl rsa 現在預設會寫入 PKCS #8 金鑰。

預設設定

「SHA256」現在是 openssl ts 使用的 TS 查詢的預設摘要。

已棄用的應用程式

openssl rsautl 已棄用,請改用 openssl pkeyutlopenssl dhparamopenssl dsaopenssl gendsaopenssl dsaparamopenssl genrsaopenssl rsaopenssl genrsaopenssl rsa 現在處於維護模式,且不會新增任何新功能。

TLS 變更

  • 新增 TLS 1.3 FFDHE 密鑰交換支援

    這使用 DH 安全質數命名群組。

  • 支援完全「可插入」TLSv1.3 群組。

    這表示提供者可以提供自己的群組實作(使用「密鑰交換」或「密鑰封裝」方法),而 libssl 會自動偵測並使用這些實作。

  • SSL 和 SSL_CTX 選項現在是 64 位元,而非 32 位元。

    在 SSL 和 SSL_CTX 物件上取得和設定選項的函數簽章已從「unsigned long」變更為「uint64_t」類型。

    這可能需要變更原始碼。例如,在預處理器 #if 條件中,不再可以使用 SSL_OP_ 巨集值。不過,仍然可以測試這些巨集是否已定義。

    請參閱 SSL_CTX_get_options(3)SSL_CTX_set_options(3)SSL_get_options(3)SSL_set_options(3)

  • SSL_set1_host() 和 SSL_add1_host() 變更

    這些函數現在接受 IP 文字位址和實際主機名稱。

  • 新增 SSL 選項 SSL_OP_CLEANSE_PLAINTEXT

    如果設定選項,openssl 會在將純文字位元組傳遞給應用程式後,清除(歸零)內部緩衝區中的純文字位元組。請注意,應用程式仍負責清除其他副本(例如:SSL_read(3) 收到的資料)。

  • 預設停用用戶端發起的重新協商。

    若要允許重新協商,請使用 -client_renegotiation 選項、SSL_OP_ALLOW_CLIENT_RENEGOTIATION 旗標或 ClientRenegotiation 設定參數(視情況而定)。

  • 現在預設 TLS 連線需要安全重新協商

    現在預設需要支援 RFC 5746 安全重新協商,才能建立 SSL 或 TLS 連線。需要連線到舊版對等方的應用程式,需要明確設定 SSL_OP_LEGACY_SERVER_CONNECT。因此,SSL_OP_LEGACY_SERVER_CONNECT 不再設定為 SSL_OP_ALL 的一部分。

  • 結合設定選項 no-ec 和 no-dh 不再停用 TLSv1.3

    通常,如果 OpenSSL 沒有 EC 或 DH 演算法,則無法支援與 TLSv1.3 的連線。不過,OpenSSL 現在透過提供者支援「可插入」群組。因此,第三方提供者可以提供群組實作,即使沒有內建的群組實作。在這種建置中嘗試建立 TLS 連線,但沒有在執行時間停用 TLSv1.3 或使用第三方提供者群組,可能會導致交握失敗。可以使用「no-tls1_3」設定選項在編譯時間停用 TLSv1.3。

  • SSL_CTX_set_ciphersuites() 和 SSL_set_ciphersuites() 變更。

    這些方法現在會忽略未知的密碼組。

  • 安全性回呼變更。

    安全性回呼,可由應用程式程式碼自訂,支援安全性作業 SSL_SECOP_TMP_DH。此作業定義為在「其他」參數中採用 EVP_PKEY。在大部分的地方,這都是傳遞的內容。所有這些地方都發生在伺服器端。不過,有一個此安全性作業的用戶端呼叫,傳遞的是 DH 物件。根據 SSL_SECOP_TMP_DH 的定義,這是錯誤的,而且與所有其他位置不一致。因此,這個用戶端呼叫已變更為傳遞 EVP_PKEY。

  • 新的 SSL 選項 SSL_OP_IGNORE_UNEXPECTED_EOF

    引入了 SSL 選項 SSL_OP_IGNORE_UNEXPECTED_EOF。如果設定了該選項,系統會忽略意外的 EOF,假裝已收到關閉通知,因此傳回的錯誤會變成 SSL_ERROR_ZERO_RETURN。

  • TLS 中基於 SHA1 和 MD5 簽章的安全性強度已降低。

    這導致 SSL 3、TLS 1.0、TLS 1.1 和 DTLS 1.0 不再使用預設安全性等級 1,而是需要安全性等級 0。安全性等級可以使用密碼組字串與 @SECLEVEL 變更,或呼叫 SSL_CTX_set_security_level(3)。這也表示,如果 ClientHello 遺漏簽章演算法擴充功能,握手會在安全性等級 1 的 TLS 1.2 中失敗。這是因為,雖然這個擴充功能是選用的,但如果沒有提供,OpenSSL 會退回到預設的簽章演算法組。這個預設組需要有 SHA1。

  • 在安全性等級 1 及以上,不再允許使用 SHA1 簽署的 X509 憑證。

    在 TLS/SSL 中,預設安全性等級為 1。可以使用密碼組字串與 @SECLEVEL 設定,或呼叫 SSL_CTX_set_security_level(3) 設定。如果葉憑證是用 SHA-1 簽署的,則在安全性等級未先降低的情況下,呼叫 SSL_CTX_use_certificate(3) 會失敗。在 TLS/SSL 之外,預設安全性等級為 -1(實際上為 0)。可以使用 X509_VERIFY_PARAM_set_auth_level(3) 或使用指令的 -auth_level 選項設定。

另請參閱

fips_module(7)

歷程

遷移指南是為 OpenSSL 3.0 建立的。

Copyright 2021-2024 The OpenSSL Project Authors。保留所有權利。

根據 Apache License 2.0(「授權」)授權。您只能在遵守授權的條件下使用這個檔案。您可以在原始程式碼散佈中的 LICENSE 檔案中取得副本,或前往 https://www.openssl.org/source/license.html 取得。