在 Linux 中使用 OpenSSL 包裝金鑰

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

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

事前準備

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

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

擷取包裝金鑰

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

控制台

  1. 前往 Google Cloud 控制台的「Key Management」頁面。

    前往「金鑰管理」頁面

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

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

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

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