OpenSSL

密碼學和 SSL/TLS 工具包

passphrase-encoding

名稱

passphrase-encoding - OpenSSL 的不同部分如何處理密語字元編碼

說明

在充滿各種字元編碼的現代世界中,密語的處理變得越來越複雜。本手冊頁面試圖概述 OpenSSL 函式庫的不同部分目前如何解決此問題。

一般情況

OpenSSL 函式庫通常不會以任何特殊方式處理密語,並信任應用程式或使用者選擇適當的字元集,並在受影響物件的生命週期中堅持使用該字元集。這表示對於使用 ISO-8859-1 編碼的密語加密的物件,需要使用 ISO-8859-1 編碼的密語解密該物件。使用錯誤的編碼預期會導致解密失敗。

PKCS#12

PKCS#12 在密語編碼方面略有不同。該標準規定密語應編碼為 ASN.1 BMPString,其中包含基本多語言平面的碼點,並以大端序(UCS-2 BE)編碼。

OpenSSL 嘗試以以下方式之一適應這些需求

  1. 將接收到的密語視為 UTF-8 編碼,並嘗試將其重新編碼為 UTF-16(對於 U+0000 至 U+D7FF 和 U+E000 至 U+FFFF 的字元,這與 UCS-2 相同,但對於任何其他字元,這將成為擴充),或如果失敗,則繼續執行步驟 2。

  2. 假設密語以 ASCII 或 ISO-8859-1 編碼,並適時地在每個位元組前面加上一個零位元組,以取得字元的 UCS-2 編碼,並將其儲存為 BMPString。

    請注意,由於沒有檢查您的語言環境,因此這可能會產生 UCS-2/UTF-16 字元,這些字元不對應於其他字元集的原始密語字元,例如任何 ISO-8859-X 編碼(ISO-8859-1 除外) (或對於 Windows,CP 1252,但 0x80-0x9F 範圍內的額外「圖形」字元除外)。

早於 1.1.0 的 OpenSSL 版本僅執行變體 2,這就是 OpenSSL 仍然這樣做的原因,以便能夠讀取舊版本產生的檔案。

請注意,此方法並非完全沒有錯誤。

以 ISO-8859-2 編碼的通行詞很可能包含 0xC3 0xAF(在 ISO-8859-2 編碼中,分別為「帶短音符的拉丁大寫字母 A」和「帶點的拉丁大寫字母 Z」)等順序,但會被誤解為完全有效的 UTF-8 編碼碼點 U+00EF(帶分音符的拉丁小寫字母 I),如果通行詞不包含任何會導致 UTF-8 無效的內容。包含此類位元組順序的通行詞在 OpenSSL 1.1.0 及更新版本中會產生與 OpenSSL 1.1.0 之前的版本不同的結果。

0x00 0xC3 0x00 0xAF                    # OpenSSL older than 1.1.0
0x00 0xEF                              # OpenSSL 1.1.0 and newer

同樣地,提供給 OpenSSL 1.1.0 之前版本的任何以 UTF-8 編碼的內容都會被誤解為 ISO-8859-1 順序。

OSSL_STORE

ossl_store(7) 作為一個通用介面,可存取各種物件,這些物件可能受通行詞、PIN 或其他項目保護。此 API 規定通行詞應以 UTF-8 編碼,而任何其他通行詞編碼都可能產生未定義的結果。此 API 依賴應用程式來確保 UTF-8 編碼,且不會檢查是否為 UTF-8 編碼,因此它取得的內容也會傳遞給底層載入器。

建議

此部分假設您知道用於加密的通行詞,但它可能已使用與目前輸入方法不同的字元編碼進行編碼。例如,通行詞可能在預設編碼為 ISO-8859-1 時使用(即「天真的」導致位元組順序 0x6E 0x61 0xEF 0x76 0x65),而您現在處於預設編碼為 UTF-8 的環境中(即「天真的」導致位元組順序 0x6E 0x61 0xC3 0xAF 0x76 0x65)。每當提到您應使用特定字元編碼時,應理解為您在輸入通行詞時,可以變更輸入方法以使用所提到的編碼,或使用一些合適的工具將通行詞從預設編碼轉換為目標編碼。

另請注意,以下小節討論人類可讀的通行詞。這與 PKCS#12 物件特別相關,其中假設通行詞為人類可讀。對於其他物件,使用任何位元組順序(例如已儲存的來自 /dev/urandom 的位元組順序)都是合法的,這使得任何字元編碼討論都無關緊要;在這種情況下,只需使用相同的位元組順序即可。

建立新物件

要建立新的密語保護物件,請確定密語使用 UTF-8 編碼。這是大多數現代 Unix 的預設值,但其他平台可能需要執行一些工作。特別是對於 Windows,設定環境變數 OPENSSL_WIN32_UTF8 會將在 [Windows] 主控台提示字元輸入的任何內容轉換為 UTF-8(命令列和個別提示的密語)。

開啟現有物件

對於開啟密語保護物件,且您知道用於加密密語的字元編碼,請務必再次使用相同的編碼。

對於開啟密語保護物件,但不知道所使用的字元編碼,或不知道產生應用程式,請嘗試下列其中一項

  1. 嘗試使用您環境中字元編碼的密語。其位元組序列可能完全正確。

  2. 將密語轉換為 UTF-8,並嘗試使用結果。特別是對於 PKCS#12,這應開啟根據規格建立的任何物件。

  3. 執行純粹數學的 ISO-8859-1 轉 UTF-8 轉換,並嘗試使用結果。這與先前的嘗試不同,因為 ISO-8859-1 直接對應到 U+0000 至 U+00FF,而其他非 UTF-8 字元集則不然。

    這也處理了使用低於 1.1.0 版的 OpenSSL 時,使用 UTF-8 編碼字串的情況。(例如,ï,在 UTF-8 中編碼時為 0xC3 0xAF,在以純粹方式重新編碼時會變成 0xC3 0x83 0xC2 0xAF。然後轉換為 BMPString 會產生 0x00 0xC3 0x00 0xA4 0x00 0x00,這是低於 1.1.0 版的 OpenSSL 使用的錯誤/不符合規定的編碼)

另請參閱

evp(7)ossl_store(7)EVP_BytesToKey(3)EVP_DecryptInit(3)PEM_do_header(3)PKCS12_parse(3)PKCS12_newpass(3)d2i_PKCS8PrivateKey_bio(3)

版權所有 2018-2021 The OpenSSL Project Authors。保留所有權利。

根據 Apache 授權條款 2.0(「授權條款」)授權。您不得在不遵守授權條款的情況下使用此檔案。您可以在原始程式碼散佈中的 LICENSE 檔案中取得副本,或至 https://www.openssl.org/source/license.html 取得。