在 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. 依序按一下「更多」圖示 ,然後點選彈出式選單中的「Download wrapping key」

gcloud CLI

如要確認匯入工作是否處於作用中狀態,請執行 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

API

  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,請為 rsa_oaep_mdrsa_mgf1_md 使用 sha1。請為 rsa-oaep-3072-sha256-aes-256rsa-oaep-4096-sha256-aes-256 使用 sha256

    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 的已包裝金鑰現在可供匯入。如要匯入金鑰,請按照「匯入手動包裝的金鑰」中的操作說明進行。