在 Linux 中使用 OpenSSL 包裝金鑰

本主題說明如何手動包裝金鑰,然後將金鑰匯入 Cloud KMS。如果您不想使用 Google Cloud CLI 在匯入金鑰前自動包裝金鑰,才需要按照本主題中的操作說明進行。如要瞭解兩者的差異,請參閱「金鑰匯入方式」。

完成本主題中的步驟大約需要 5 到 10 分鐘,不包括「事前準備」步驟。

事前準備

您必須先完成下列先決條件,才能包裝金鑰。

  1. 建立目標金鑰環和金鑰,並建立匯入工作
  2. 確認金鑰可在本機使用,且格式正確無誤,可匯入 Cloud KMS。
  3. 修補並重新編譯 OpenSSL

擷取包裝金鑰

本節說明如何從「事前準備」中建立的匯入工作擷取包裝金鑰。建議使用 Google Cloud 控制台。

控制台

  1. 前往 Google Cloud 控制台的「Key Management」(金鑰管理) 頁面。

    前往「Key Management」(金鑰管理) 頁面

  2. 按一下包含匯入工作的金鑰環名稱。

  3. 按一下頁面頂端的 [Import Jobs] (匯入工作) 分頁標籤。

  4. 依序按一下「更多」, 然後按一下彈出式選單中的「下載包裝金鑰」

gcloud

如要確認匯入工作是否處於啟用狀態,請執行 gcloud kms import-jobs describe 指令:

gcloud kms import-jobs describe IMPORT_JOB \
  --location LOCATION \
  --keyring KEY_RING \
  --format="value(state)"
state: ACTIVE

執行下列指令,將匯入工作的公開金鑰儲存至 ${HOME}/wrapping-key.pem

gcloud kms import-jobs describe \
  --location=LOCATION \
  --keyring=KEY_RING \
  --format="value(publicKey.pem)" \
  IMPORT_JOB > ${HOME}/wrapping-key.pem

REST

  1. 呼叫 ImportJob.get 方法。

  2. 透過 ImportJob.get 回應的 publicKey 欄位擷取公開金鑰。這個值的類型為 WrappingPublicKeyWrappingPublicKey 類型的 pem 欄位是採用隱私強化郵件 (PEM) 格式來編碼的公開金鑰。

如要進一步瞭解 PEM 編碼格式,請參閱 RFC 7468,尤其是一般注意事項主體公開金鑰資訊的文字編碼章節。

設定環境變數

OpenSSL 指令需要多個檔案路徑做為輸入值。請為這些檔案路徑定義環境變數,以便讓您能更輕鬆地執行指令。請確認您有權寫入下方定義的目錄。

  1. PUB_WRAPPING_KEY 變數設為您從匯入工作下載的包裝金鑰完整路徑。包裝金鑰結尾為 .pem

    PUB_WRAPPING_KEY="WRAPPING_KEY_PATH"
    

  2. TARGET_KEY 變數設為未包裝 (目標) 金鑰的完整路徑。

    TARGET_KEY=TARGET_KEY_PATH
    

    TARGET_KEY_PATH 替換為對稱金鑰的 .bin 檔案路徑,或非對稱金鑰的 .der 檔案路徑。

  3. 如果使用 RSA-AES 包裝,請將 TEMP_AES_KEY 變數設為臨時 AES 金鑰的完整路徑。

    TEMP_AES_KEY=TEMP_AES_KEY_PATH
    

  4. WRAPPED_KEY 變數設為完整路徑,您要將準備匯入的包裝目標金鑰儲存至該路徑。

    WRAPPED_KEY=WRAPPED_KEY_PATH
    

  5. 使用下列指令,確認所有環境變數都已正確設定:

    echo "PUB_WRAPPING_KEY: " ${PUB_WRAPPING_KEY}; \
    echo "TARGET_KEY: " ${TARGET_KEY}; \
    echo "TEMP_AES_KEY: " ${TEMP_AES_KEY}; \
    echo "WRAPPED_KEY: " ${WRAPPED_KEY}
    

變數設定正確後,即可包裝金鑰。如以下說明,有兩種方法:僅使用 RSA 或使用 RSA-AES

包裝金鑰

使用 RSA 包裝金鑰

採用這種方法時,目標金鑰會包裝在 RSA 區塊中。因此目標金鑰大小會受到限制。舉例來說,您無法使用這個方法包裝另一個 RSA 金鑰。支援的匯入方法為 rsa-oaep-3072-sha256rsa-oaep-4096-sha256

  • 使用 CKM_RSA_PKCS_OAEP 演算法,將目標金鑰與包裝公開金鑰包裝在一起:

    openssl pkeyutl \
      -encrypt \
      -pubin \
      -inkey ${PUB_WRAPPING_KEY} \
      -in ${TARGET_KEY} \
      -out ${WRAPPED_KEY} \
      -pkeyopt rsa_padding_mode:oaep \
      -pkeyopt rsa_oaep_md:sha256 \
      -pkeyopt rsa_mgf1_md:sha256
    

使用 RSA-AES 包裝金鑰

在這個方法中,目標金鑰會以臨時 AES 金鑰包裝。然後,臨時 AES 金鑰會由 RSA 金鑰包裝。這兩個已包裝金鑰會串連並匯入。由於目標金鑰是使用 AES 而非 RSA 包裝,因此這種方法可用於包裝大型金鑰。支援的匯入方法為 rsa-oaep-3072-sha1-aes-256rsa-oaep-4096-sha1-aes-256rsa-oaep-3072-sha256-aes-256rsa-oaep-4096-sha256-aes-256

  1. 產生長度為 32 個位元組的臨時隨機 AES 金鑰,並儲存至 ${TEMP_AES_KEY} 所識別的位置:

    openssl rand -out "${TEMP_AES_KEY}" 32
    

  2. 使用 CKM_RSA_PKCS_OAEP 演算法,將臨時 AES 金鑰與包裝公開金鑰包裝在一起。如果匯入方法是 rsa-oaep-3072-sha1-aes-256rsa-oaep-4096-sha1-aes-256,請使用 sha1 做為 rsa_oaep_mdrsa_mgf1_md。使用 sha256 進行 rsa-oaep-3072-sha256-aes-256rsa-oaep-4096-sha256-aes-256

    openssl pkeyutl \
      -encrypt \
      -pubin \
      -inkey ${PUB_WRAPPING_KEY} \
      -in ${TEMP_AES_KEY} \
      -out ${WRAPPED_KEY} \
      -pkeyopt rsa_padding_mode:oaep \
      -pkeyopt rsa_oaep_md:{sha1|sha256} \
      -pkeyopt rsa_mgf1_md:{sha1|sha256}
    

  3. OpenSSL_V110 變數設為 openssl.sh 指令碼的路徑。如果您完全按照修補及重新編譯 OpenSSL 的操作說明進行,即可使用這個指令,不必修改變數的值。

    OPENSSL_V110="${HOME}/local/bin/openssl.sh"
    

  4. 使用 CKM_AES_KEY_WRAP_PAD 演算法搭配臨時 AES 金鑰來包裝目標金鑰,並將其附加至 WRAPPED_KEY

    "${OPENSSL_V110}" enc \
      -id-aes256-wrap-pad \
      -iv A65959A6 \
      -K $( hexdump -v -e '/1 "%02x"' < "${TEMP_AES_KEY}" ) \
      -in "${TARGET_KEY}" >> "${WRAPPED_KEY}"
    

    -iv A65959A6 旗標會將 A65959A6 設為備用初始值。這是 RFC 5649 規格的要求。

後續步驟

  • 儲存在 WRAPPED_KEY 的包裝金鑰現在已可匯入。 如要匯入金鑰,請按照「匯入手動包裝的金鑰」一文中的操作說明進行。