ייבוא מפתחות חסין מפני פיצוח קוונטי

במדריך הזה נסביר איך לייבא מפתח קריפטוגרפי ל-Cloud Key Management Service כגרסה חדשה של מפתח באמצעות שיטת ייבוא חסינה מפני פיצוח קוונטי. הגישה הזו עוזרת להגן על המפתח במהלך ההעברה מפני מתקפות "איסוף מיידי ופענוח בהמשך" (SNDL) של מחשבים קוונטיים עתידיים.

ייבוא מפתחות חסינים מפני פיצוח קוונטי מתבצע באמצעות כלים סטנדרטיים של הצפנה פוסט-קוונטית (PQC), כולל מנגנוני אנקפסולציה של מפתחות (KEM) והצפנה היברידית של מפתחות ציבוריים (HPKE), כדי להגן על המפתח בזמן ההעברה.

אפשר לייבא מפתחות חסינים מפני פיצוח קוונטי למפתחות שמגובים בתוכנה (רמת ההגנה SOFTWARE).

לפני שמתחילים

כדי לייבא מפתח, צריך להכין את הפרויקט, את המערכת המקומית ואת חומר המפתח עצמו.

הכנת הפרויקט

  1. נכנסים לחשבון Google Cloud . אנחנו ממליצים למשתמשים חדשים ב- Google Cloud ליצור חשבון כדי שיוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the required API, if it is not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the API

  5. Install the Google Cloud CLI.

  6. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  7. To initialize the gcloud CLI, run the following command:

    gcloud init
  8. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  9. Verify that billing is enabled for your Google Cloud project.

  10. Enable the required API, if it is not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the API

  11. Install the Google Cloud CLI.

  12. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  13. To initialize the gcloud CLI, run the following command:

    gcloud init

התפקידים הנדרשים

כדי לקבל את ההרשאות שדרושות לייבוא מפתח, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים באוסף המפתחות:

להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

הכנת המערכת המקומית

אתם צריכים ספרייה קריפטוגרפית במערכת המקומית שתומכת בכלים של הצפנה פוסט-קוונטית (PQC), כולל מנגנוני אנקפסולציה של מפתחות (KEM) והצפנה היברידית של מפתחות ציבוריים (HPKE). אפשר להשתמש ב-Tink, ב-OpenSSL או בספרייה קריפטוגרפית אחרת שתומכת באפשרויות הבאות:

  • הצפנה היברידית של מפתח ציבורי (HPKE)
  • אחד מהאלגוריתמים הבאים של KEM:
    • ML-KEM-768
    • ML-KEM-1024
    • ‫X-WING (שילוב של ML-KEM-768 ו-X25519)
  • פונקציית גזירת המפתחות (KDF) של HKDF-SHA256
  • הצפנה מאומתת עם מידע נלווה (AEAD) באמצעות האלגוריתם AES-256-GCM

הכנת המפתח

מוודאים שהאלגוריתם והאורך של המפתח נתמכים. לכל הגרסאות של מפתח חייבת להיות אותה רמת הגנה (SOFTWARE).

יצירת מפתח היעד ואוסף המפתחות

כשמייבאים חומר מפתח, הוא הופך לגרסת מפתח חדשה במפתח קיים. המפתח הזה נקרא מפתח היעד. כדי לייבא חומר מפתח, צריך ליצור קודם את אוסף המפתחות ואת המפתח שאליו רוצים לייבא.

כדי ליצור מפתח ריק שמגובה בתוכנה באוסף מפתחות חדש באמצעות Google Cloud CLI או המסוף Google Cloud :

המסוף

  1. נכנסים לדף Key Management במסוף Google Cloud .

    כניסה אל Key Management

  2. לוחצים על Create key ring.

  3. בשדה שם אוסף המפתחות, מזינים את השם של אוסף המפתחות.

  4. בקטע Location type, בוחרים סוג מיקום ומיקום.

  5. לוחצים על יצירה. ייפתח הדף Create key.

  6. בשדה Key name, מזינים את שם המפתח.

  7. בקטע Protection level, בוחרים באפשרות Software.

  8. בקטע Key material, בוחרים באפשרות Imported key ולוחצים על Continue. כך לא נוצרת גרסת מפתח ראשונית.

  9. מגדירים את המטרה ואת האלגוריתם של המפתח ולוחצים על המשך.

  10. אופציונלי: אם רוצים שהמפתח הזה יכיל רק גרסאות מפתח מיובאות, בוחרים באפשרות Restrict key versions to import only. כך לא תיצרו בטעות גרסאות מפתח חדשות ב-Cloud KMS.

  11. אופציונלי: במפתחות מיובאים, הרוטציה האוטומטית מושבתת כברירת מחדל. כדי להפעיל רוטציית מפתחות אוטומטית, בוחרים ערך בשדה Key rotation period.

    אם מפעילים רוטציה אוטומטית, גרסאות מפתח חדשות ייווצרו ב-Cloud KMS, וגרסת המפתח המיובאת לא תהיה יותר גרסת המפתח שמוגדרת כברירת מחדל אחרי הרוטציה.

  12. לוחצים על יצירה.

gcloud

כדי להשתמש ב-Cloud KMS בשורת הפקודה, קודם צריך להתקין את הגרסה העדכנית של Google Cloud CLI או לשדרג אליה.

  1. יוצרים את אוסף המפתחות לטירגוט. בוחרים מיקום שתואם לרמת ההגנה שבה רוצים להשתמש. מידע נוסף על המיקומים הנתמכים מופיע במאמר מיקומים ב-Cloud KMS.

    gcloud kms keyrings create KEY_RING \
      --location LOCATION
    

    מידע נוסף על יצירת מחזיקי מפתחות

  2. יוצרים את מפתח היעד באמצעות הפקודה kms keys create עם הדגל --skip-initial-version-creation. כך נוצר מפתח ללא גרסת מפתח ראשונית, וחומר המפתח המיובא הוא גרסה 1. משתמשים בדגל --import-only כדי למנוע מ-Cloud KMS ליצור חומר מפתח לגרסאות חדשות של מפתחות. אם הדגל הזה מוגדר, צריך לייבא גרסאות חדשות של המפתח הזה. צריך להחליף ידנית מפתחות שנוצרו בתור --import-only.

    gcloud kms keys create KEY_NAME \
      --location LOCATION \
      --keyring KEY_RING \
      --purpose PURPOSE \
      --protection-level SOFTWARE \
      --skip-initial-version-creation \
      --import-only
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫KEY_NAME: השם שרוצים להשתמש בו עבור המפתח.
    • ‫LOCATION: המיקום של אוסף המפתחות.
    • ‫KEY_RING: אוסף המפתחות שבו רוצים ליצור את המפתח.
    • ‫PURPOSE: המטרה שלשמה רוצים להשתמש במפתח.

API

בדוגמאות האלה משתמשים ב-curl כצד הלקוח ב-HTTP כדי להדגים את השימוש ב-API. מידע נוסף על בקרת גישה זמין במאמר גישה ל-Cloud KMS API.

  1. יוצרים אוסף מפתחות חדש:

    curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings?keyRingId=KEY_RING" \
        --request "POST" \
        --header "authorization: Bearer TOKEN" \
        --header "content-type: application/json" \
        --header "x-goog-user-project: PROJECT_ID" \
        --data "{}"
    

    מידע נוסף זמין במאמרי העזרה של ה-API של KeyRing.create.

  2. יוצרים מפתח ריק לייבוא בלבד:

    curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys?cryptoKeyId=KEY_NAME&skipInitialVersionCreation=true" \
        --request "POST" \
        --header "authorization: Bearer TOKEN" \
        --header "content-type: application/json" \
        --header "x-goog-user-project: PROJECT_ID" \
        --data "{"purpose":"PURPOSE", "importOnly": "true", "versionTemplate":{"protectionLevel":"PROTECTION_LEVEL","algorithm":"ALGORITHM"}}"
    

    מידע נוסף זמין במאמרי העזרה של ה-API של CryptoKey.create.

אוסף המפתחות והמפתח קיימים עכשיו, אבל המפתח לא מכיל חומר מפתח, אין לו גרסה והוא לא פעיל. בשלב הבא יוצרים משימת ייבוא.

יצירת משימת הייבוא

משימת ייבוא מגדירה את המאפיינים של המפתחות שהיא מייבאת, כולל רמת ההגנה ושיטת הייבוא.

אפשר לייבא מפתחות חסינים מפני פיצוח קוונטי רק ברמת ההגנה SOFTWARE. בוחרים אחת מהשיטות הבאות לייבוא חסין מפני פיצוח קוונטי:

  • HPKE_KEM_XWING_HKDF_SHA256_AES_256_GCM
  • HPKE_KEM_ML_KEM_768_HKDF_SHA256_AES_256_GCM
  • HPKE_KEM_ML_KEM_1024_HKDF_SHA256_AES_256_GCM

gcloud

מריצים את הפקודה הבאה כדי ליצור משימת ייבוא עם שיטת ייבוא חסינה מפני פיצוח קוונטי:

gcloud kms import-jobs create IMPORT_JOB \
    --location LOCATION \
    --keyring KEY_RING \
    --import-method IMPORT_METHOD \
    --protection-level software

מחליפים את מה שכתוב בשדות הבאים:

  • ‫IMPORT_JOB: שם ייחודי למשימת הייבוא.
  • ‫LOCATION: המיקום של אוסף המפתחות שבו יצרתם את מפתח היעד.
  • ‫KEY_RING: השם של אוסף המפתחות שבו יצרתם את מפתח היעד.
  • IMPORT_METHOD: שיטת הייבוא חסין מפני פיצוח קוונטי שרוצים להשתמש בה, לדוגמה hpke-kem-xwing-hkdf-sha256-aes-256-gcm.

REST

מבצעים קריאה ל-keyRings.importJobs.create:

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/importJobs?import_job_id=IMPORT_JOB" \
    --request "POST" \
    --header "authorization: Bearer TOKEN" \
    --header "content-type: application/json" \
    --data '{"import_method": "IMPORT_METHOD", "protection_level": "SOFTWARE"}'

מחליפים את מה שכתוב בשדות הבאים:

  • ‫PROJECT_ID: המזהה של פרויקט Cloud KMS.
  • ‫LOCATION: המיקום של אוסף המפתחות שבו יצרתם את מפתח היעד.
  • ‫KEY_RING: השם של אוסף המפתחות שבו יצרתם את מפתח היעד.
  • ‫IMPORT_JOB: שם ייחודי לשימוש בעבודת הייבוא.
  • ‫TOKEN: האסימון לאימות הבקשה.
  • IMPORT_METHOD: שיטת הייבוא חסין מפני פיצוח קוונטי שרוצים להשתמש בה, לדוגמה HPKE_KEM_XWING_HKDF_SHA256_AES_256_GCM.

בדיקת המצב של משימת הייבוא

המצב הראשוני של משימת ייבוא הוא PENDING_GENERATION. כשהמצב הוא ACTIVE, אפשר להשתמש בו כדי לייבא מפתחות.

התוקף של משימת ייבוא פג אחרי שלושה ימים. אם פג התוקף של משימת הייבוא, צריך ליצור משימה חדשה.

אתם יכולים לבדוק את הסטטוס של משימת הייבוא באמצעות Google Cloud CLI, מסוףGoogle Cloud או Cloud Key Management Service API.

המסוף

  1. נכנסים לדף Key Management במסוף Google Cloud .

    כניסה לדף Key Management

  2. לוחצים על השם של אוסף המפתחות שמכיל את עבודת הייבוא.

  3. לוחצים על הכרטיסייה משימות ייבוא בחלק העליון של הדף.

  4. הסטטוס יופיע בקטע Status לצד שם משימת הייבוא.

gcloud

כדי להשתמש ב-Cloud KMS בשורת הפקודה, קודם צריך להתקין את הגרסה העדכנית של Google Cloud CLI או לשדרג אליה.

כשיש משימת ייבוא פעילה, אפשר להשתמש בה כדי לייבא מפתחות. התהליך יכול להימשך כמה דקות. משתמשים בפקודה הזו כדי לוודא שמשימת הייבוא פעילה. משתמשים במיקום ובמחזיק המפתחות שבהם יצרתם את עבודת הייבוא.

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

הפלט אמור להיראות כך:

state: ACTIVE

Go

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח של Go ולהתקין את Cloud KMS Go SDK.

import (
	"context"
	"fmt"
	"io"

	kms "cloud.google.com/go/kms/apiv1"
	"cloud.google.com/go/kms/apiv1/kmspb"
)

// checkStateImportJob checks the state of an ImportJob in KMS.
func checkStateImportJob(w io.Writer, name string) error {
	// name := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring/importJobs/my-import-job"

	// Create the client.
	ctx := context.Background()
	client, err := kms.NewKeyManagementClient(ctx)
	if err != nil {
		return fmt.Errorf("failed to create kms client: %w", err)
	}
	defer client.Close()

	// Call the API.
	result, err := client.GetImportJob(ctx, &kmspb.GetImportJobRequest{
		Name: name,
	})
	if err != nil {
		return fmt.Errorf("failed to get import job: %w", err)
	}
	fmt.Fprintf(w, "Current state of import job %q: %s\n", result.Name, result.State)
	return nil
}

Java

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח של Java ולהתקין את Java SDK של Cloud KMS.

import com.google.cloud.kms.v1.ImportJob;
import com.google.cloud.kms.v1.ImportJobName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import java.io.IOException;

public class CheckStateImportJob {

  public void checkStateImportJob() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String locationId = "us-east1";
    String keyRingId = "my-key-ring";
    String importJobId = "my-import-job";
    checkStateImportJob(projectId, locationId, keyRingId, importJobId);
  }

  // Check the state of an import job in Cloud KMS.
  public void checkStateImportJob(
      String projectId, String locationId, String keyRingId, String importJobId)
      throws IOException {
    // Initialize client that will be used to send requests. This client only
    // needs to be created once, and can be reused for multiple requests. After
    // completing all of your requests, call the "close" method on the client to
    // safely clean up any remaining background resources.
    try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
      // Build the parent name from the project, location, and key ring.
      ImportJobName importJobName = ImportJobName.of(projectId, locationId, keyRingId, importJobId);

      // Retrieve the state of an existing import job.
      ImportJob importJob = client.getImportJob(importJobName);
      System.out.printf(
          "Current state of import job %s: %s%n", importJob.getName(), importJob.getState());
    }
  }
}

Node.js

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח של Node.js ולהתקין את Cloud KMS Node.js SDK.

//
// TODO(developer): Uncomment these variables before running the sample.
//
// const projectId = 'my-project';
// const locationId = 'us-east1';
// const keyRingId = 'my-key-ring';
// const importJobId = 'my-import-job';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the import job name
const importJobName = client.importJobPath(
  projectId,
  locationId,
  keyRingId,
  importJobId
);

async function checkStateImportJob() {
  const [importJob] = await client.getImportJob({
    name: importJobName,
  });

  console.log(
    `Current state of import job ${importJob.name}: ${importJob.state}`
  );
  return importJob;
}

return checkStateImportJob();

Python

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח ב-Python ולהתקין את Cloud KMS Python SDK.

from google.cloud import kms


def check_state_import_job(
    project_id: str, location_id: str, key_ring_id: str, import_job_id: str
) -> None:
    """
    Check the state of an import job in Cloud KMS.

    Args:
        project_id (string): Google Cloud project ID (e.g. 'my-project').
        location_id (string): Cloud KMS location (e.g. 'us-east1').
        key_ring_id (string): ID of the Cloud KMS key ring (e.g. 'my-key-ring').
        import_job_id (string): ID of the import job (e.g. 'my-import-job').
    """

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Retrieve the fully-qualified import_job string.
    import_job_name = client.import_job_path(
        project_id, location_id, key_ring_id, import_job_id
    )

    # Retrieve the state from an existing import job.
    import_job = client.get_import_job(name=import_job_name)

    print(f"Current state of import job {import_job.name}: {import_job.state}")

API

בדוגמאות האלה משתמשים ב-curl כצד הלקוח ב-HTTP כדי להדגים את השימוש ב-API. מידע נוסף על בקרת גישה זמין במאמר גישה ל-Cloud KMS API.

כדי לבדוק את הסטטוס של משימת ייבוא, משתמשים בשיטה ImportJobs.get:

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/importJobs/IMPORT_JOB_ID" \
    --request "GET" \
    --header "authorization: Bearer TOKEN"

ברגע שמשימת הייבוא פעילה, אפשר לייבא מפתח.

אחזור מפתח האריזה הציבורי

אחרי שמשימת הייבוא נמצאת במצב ACTIVE, מאחזרים את המפתח הציבורי שמשויך אליה. אתם תשתמשו במפתח הציבורי הזה במערכת המקומית כדי לעטוף את חומר המפתח שאתם רוצים לייבא.

gcloud

מריצים את הפקודה הבאה כדי להוריד את המפתח הציבורי:

gcloud kms import-jobs describe IMPORT_JOB \
    --location LOCATION \
    --keyring KEY_RING \
    --format="value(publicKey.data)"

מחליפים את מה שכתוב בשדות הבאים:

  • ‫IMPORT_JOB: השם של משימת הייבוא.
  • ‫LOCATION: המיקום של אוסף המפתחות שבו יצרתם את משימת הייבוא.
  • ‫KEY_RING: השם של אוסף המפתחות שבו יצרתם את משימת הייבוא.

המפתח הציבורי מקודד ב-Base64.

REST

  1. מפעילים את ה-method‏ keyRings.importJobs.get.
  2. מאחזרים את המפתח הציבורי מהשדה publicKey.data של התשובה ושומרים אותו באופן מקומי בתור public_key.data.

הכנה ואריזה של חומר המפתח

משתמשים בספרייה קריפטוגרפית חיצונית שנתמכת במערכת המקומית כדי לעטוף את חומר המפתח באמצעות מפתח האריזה הציבורי שאוחזר.

תהליך העטיפה חייב לבצע HPKE.Seal() (RFC 9180) כדי ליצור מפתח עטוף. הפעולה הזו משלימה את השלבים הבאים:

  1. מבצעים אנקפסולציה של המפתח הציבורי שאוחזר כדי ליצור סוד משותף ומפתח אנקפסולציה.
  2. הפקת מפתח סימטרי זמני מהסוד המשותף באמצעות HKDF-SHA256.
  3. מצפינים את חומר המפתח באמצעות המפתח האפמרי ב-AES-256-GCM.
  4. משרשרים את מפתח האריזה ואת חומר המפתח המוצפן כמידע מוצפן (ciphertext). זהו המפתח העטוף שנוצר, שבו תשתמשו כדי לייבא את המפתח. שומרים את הקובץ בשם wrapped_key.bin.

דוגמת הקוד הבאה ב-Go ממחישה איך לעטוף חומר מפתחות באמצעות הספרייה tink-go:

package main

import (
    "bytes"
    "encoding/base64"
    "flag"
    "fmt"
    "log"

    "google.golang.org/protobuf/proto"
    "github.com/tink-crypto/tink-go/v2/hybrid"
    "github.com/tink-crypto/tink-go/v2/keyset"

    hpkepb "github.com/tink-crypto/tink-go/v2/proto/hpke_go_proto"
    tinkpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto"
)

var (
    publicKeyB64Flag = flag.String("public_key", "", "Base64 encoded public key for wrapping.")
    targetKeyB64Flag = flag.String("target_key", "", "Base64 encoded 32-byte target key to be wrapped.")
)

func main() {
    flag.Parse()

    if *publicKeyB64Flag == "" {
        log.Fatal("-public_key is required")
    }
    if *targetKeyB64Flag == "" {
        log.Fatal("-target_key is required")
    }

    pkBytes, err := base64.StdEncoding.DecodeString(*publicKeyB64Flag)
    if err != nil {
        log.Fatalf("failed to decode public key: %v", err)
    }

    targetKey, err := base64.StdEncoding.DecodeString(*targetKeyB64Flag)
    if err != nil {
        log.Fatalf("failed to decode target key: %v", err)
    }

    hpkePubKey := &hpkepb.HpkePublicKey{
        Version: 0,
        Params: &hpkepb.HpkeParams{
            Kem:  hpkepb.HpkeKem_ML_KEM768,
            Kdf:  hpkepb.HpkeKdf_HKDF_SHA256,
            Aead: hpkepb.HpkeAead_AES_256_GCM,
        },
        PublicKey: pkBytes,
    }
    serializedPubKey, err := proto.Marshal(hpkePubKey)
    if err != nil {
        log.Fatalf("failed to marshal HPKE public key: %v", err)
    }

    ks := &tinkpb.Keyset{
        PrimaryKeyId: 1,
        Key: []*tinkpb.Keyset_Key{
            {
                KeyData: &tinkpb.KeyData{
                    TypeUrl:         "type.googleapis.com/google.crypto.tink.HpkePublicKey",
                    Value:           serializedPubKey,
                    KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
                },
                Status:           tinkpb.KeyStatusType_ENABLED,
                KeyId:            1,
                OutputPrefixType: tinkpb.OutputPrefixType_RAW,
            },
        },
    }
    serializedKeyset, err := proto.Marshal(ks)
    if err != nil {
        log.Fatalf("failed to marshal keyset: %v", err)
    }

    // Create a KeysetHandle and retrieve the HybridEncrypt primitive.
    reader := keyset.NewBinaryReader(bytes.NewReader(serializedKeyset))
    handle, err := keyset.ReadWithNoSecrets(reader)
    if err != nil {
        log.Fatalf("failed to create keyset handle: %v", err)
    }

    enc, err := hybrid.NewHybridEncrypt(handle)
    if err != nil {
        log.Fatalf("failed to create hybrid encrypt primitive: %v", err)
    }

    // Perform the wrapping operation. Tink's HPKE implementation handles the
  // 'enc || ciphertext' concatenation automatically.
    wrappedKey, err := enc.Encrypt(targetKey, nil)
    if err != nil {
        log.Fatalf("failed to wrap key: %v", err)
    }

    fmt.Printf("Final wrappedKey (base64):\n%s\n", base64.StdEncoding.EncodeToString(wrappedKey))
}

שומרים את מחרוזת הפלט ב-base64 או מפענחים אותה לקובץ בינארי: bash echo "BASE64_WRAPPED_KEY" | base64 --decode > wrapped_key.bin

ייבוא המפתח שעטוף

מייבאים את המפתח הארוז שהכנתם כגרסת מפתח חדשה של מפתח היעד.

gcloud

מריצים את הפקודה kms keys versions import:

gcloud kms keys versions import \
    --location LOCATION \
    --keyring KEY_RING \
    --key KEY_NAME \
    --import-job IMPORT_JOB \
    --algorithm ALGORITHM \
    --wrapped-key-file wrapped_key.bin

מחליפים את מה שכתוב בשדות הבאים:

  • ‫LOCATION: המיקום של אוסף המפתחות שמכיל את מפתח היעד.
  • ‫KEY_RING: השם של אוסף המפתחות שמכיל את מפתח היעד.
  • ‫KEY_NAME: השם של מפתח היעד.
  • ‫IMPORT_JOB: השם של עבודת הייבוא.
  • ‫ALGORITHM: האלגוריתם של חומר המפתחות לייבוא.

REST

מבצעים קריאה ל-cryptoKeyVersions.import:

curl "https://cloudkms.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions:import" \
    --request "POST" \
    --header "authorization: Bearer TOKEN" \
    --header "content-type: application/json" \
    --data '{"importJob": "IMPORT_JOB", "algorithm": "ALGORITHM", "wrappedKey": "PATH_TO_WRAPPED_KEY"}'

מחליפים את מה שכתוב בשדות הבאים:

  • ‫PROJECT_ID: המזהה של פרויקט Cloud KMS.
  • ‫LOCATION: המיקום של אוסף המפתחות שמכיל את מפתח היעד.
  • ‫KEY_RING: השם של אוסף המפתחות שמכיל את מפתח היעד.
  • ‫KEY_NAME: השם של מפתח היעד.
  • ‫TOKEN: הטוקן לאימות הבקשה.
  • ‫IMPORT_JOB: המזהה של משימת הייבוא המתאימה.
  • ‫ALGORITHM: האלגוריתם של חומר המפתחות לייבוא.
  • ‫PATH_TO_WRAPPED_KEY: הנתיב למפתח שעטפתם באופן ידני בפורמט base64.

בדיקת המצב של גרסת המפתח המיובאת

המצב הראשוני של גרסת מפתח מיובאת הוא PENDING_IMPORT. כשהסטטוס הוא ENABLED, גרסת המפתח יובאה בהצלחה. אם הייבוא נכשל, הסטטוס הוא IMPORT_FAILED.

אתם יכולים לבדוק את הסטטוס של בקשת הייבוא באמצעות Google Cloud CLI, מסוףGoogle Cloud או Cloud Key Management Service API.

המסוף

  1. נכנסים לדף Key Management במסוף Google Cloud .

    כניסה אל Key Management

  2. לוחצים על השם של אוסף המפתחות שמכיל את משימת הייבוא.

  3. לוחצים על הכרטיסייה משימות ייבוא בחלק העליון של הדף.

  4. הסטטוס יופיע בקטע Status לצד שם משימת הייבוא.

gcloud

כדי להשתמש ב-Cloud KMS בשורת הפקודה, קודם צריך להתקין את הגרסה העדכנית של Google Cloud CLI או לשדרג אליה.

משתמשים בפקודה versions list כדי לבדוק את המצב. משתמשים באותו מיקום, באותו אוסף מפתחות ובאותו מפתח יעד שיצרתם קודם לכן בנושא הזה.

gcloud kms keys versions list \
  --keyring KEY_RING \
  --location LOCATION \
  --key KEY_NAME

Go

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח של Go ולהתקין את Cloud KMS Go SDK.

import (
	"context"
	"fmt"
	"io"

	kms "cloud.google.com/go/kms/apiv1"
	"cloud.google.com/go/kms/apiv1/kmspb"
)

// checkStateImportedKey checks the state of a CryptoKeyVersion in KMS.
func checkStateImportedKey(w io.Writer, name string) error {
	// name := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring/cryptoKeys/my-imported-key/cryptoKeyVersions/1"

	// Create the client.
	ctx := context.Background()
	client, err := kms.NewKeyManagementClient(ctx)
	if err != nil {
		return fmt.Errorf("failed to create kms client: %w", err)
	}
	defer client.Close()

	// Call the API.
	result, err := client.GetCryptoKeyVersion(ctx, &kmspb.GetCryptoKeyVersionRequest{
		Name: name,
	})
	if err != nil {
		return fmt.Errorf("failed to get crypto key version: %w", err)
	}
	fmt.Fprintf(w, "Current state of crypto key version %q: %s\n", result.Name, result.State)
	return nil
}

Java

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח ב-Java ולהתקין את Cloud KMS Java SDK.

import com.google.cloud.kms.v1.CryptoKeyVersion;
import com.google.cloud.kms.v1.CryptoKeyVersionName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import java.io.IOException;

public class CheckStateImportedKey {

  public void checkStateImportedKey() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String locationId = "us-east1";
    String keyRingId = "my-key-ring";
    String cryptoKeyId = "my-crypto-key";
    String cryptoKeyVersionId = "1";
    checkStateImportedKey(projectId, locationId, keyRingId, cryptoKeyId, cryptoKeyVersionId);
  }

  // Check the state of an imported key in Cloud KMS.
  public void checkStateImportedKey(
      String projectId,
      String locationId,
      String keyRingId,
      String cryptoKeyId,
      String cryptoKeyVersionId)
      throws IOException {
    // Initialize client that will be used to send requests. This client only
    // needs to be created once, and can be reused for multiple requests. After
    // completing all of your requests, call the "close" method on the client to
    // safely clean up any remaining background resources.
    try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
      // Build the version name from its path components.
      CryptoKeyVersionName versionName =
          CryptoKeyVersionName.of(
              projectId, locationId, keyRingId, cryptoKeyId, cryptoKeyVersionId);

      // Retrieve the state of an existing version.
      CryptoKeyVersion version = client.getCryptoKeyVersion(versionName);
      System.out.printf(
          "Current state of crypto key version %s: %s%n", version.getName(), version.getState());
    }
  }
}

Node.js

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח של Node.js ולהתקין את Cloud KMS Node.js SDK.

//
// TODO(developer): Uncomment these variables before running the sample.
//
// const projectId = 'my-project';
// const locationId = 'us-east1';
// const keyRingId = 'my-key-ring';
// const cryptoKeyId = 'my-imported-key';
// const cryptoKeyVersionId = '1';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the key version name
const keyVersionName = client.cryptoKeyVersionPath(
  projectId,
  locationId,
  keyRingId,
  cryptoKeyId,
  cryptoKeyVersionId
);

async function checkStateCryptoKeyVersion() {
  const [keyVersion] = await client.getCryptoKeyVersion({
    name: keyVersionName,
  });

  console.log(
    `Current state of key version ${keyVersion.name}: ${keyVersion.state}`
  );
  return keyVersion;
}

return checkStateCryptoKeyVersion();

Python

כדי להריץ את הקוד הזה, קודם צריך להגדיר סביבת פיתוח של Python ולהתקין את Cloud KMS Python SDK.

from google.cloud import kms


def check_state_imported_key(
    project_id: str, location_id: str, key_ring_id: str, import_job_id: str
) -> None:
    """
    Check the state of an import job in Cloud KMS.

    Args:
        project_id (string): Google Cloud project ID (e.g. 'my-project').
        location_id (string): Cloud KMS location (e.g. 'us-east1').
        key_ring_id (string): ID of the Cloud KMS key ring (e.g. 'my-key-ring').
        import_job_id (string): ID of the import job (e.g. 'my-import-job').
    """

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Retrieve the fully-qualified import_job string.
    import_job_name = client.import_job_path(
        project_id, location_id, key_ring_id, import_job_id
    )

    # Retrieve the state from an existing import job.
    import_job = client.get_import_job(name=import_job_name)

    print(f"Current state of import job {import_job.name}: {import_job.state}")

API

בדוגמאות האלה משתמשים ב-curl כצד הלקוח ב-HTTP כדי להדגים את השימוש ב-API. מידע נוסף על בקרת גישה זמין במאמר גישה ל-Cloud KMS API.

מבצעים קריאה ל-method‏ ImportJob.get ובודקים את השדה [state][api_importjob_fields_state]. אם הערך של state הוא PENDING_GENERATION, משימת הייבוא עדיין בתהליך יצירה. בודקים שוב את המצב מדי פעם עד שהוא משתנה ל-ACTIVE.

אחרי שמייבאים את גרסת המפתח הראשונית, הסטטוס של המפתח משתנה ל-ENABLED. לפני שתוכלו להשתמש במפתחות סימטריים, אתם צריכים להגדיר את גרסת המפתח המיובאת כגרסה הראשית.

ייבוא מחדש של מפתח שהושמד בעבר

אם אתם צריכים לשחזר גרסת מפתח מיובאת קודמת שנמצאת במצב DESTROYED או במצב IMPORT_FAILED למצב ENABLED, אתם יכולים לייבא מחדש את אותו חומר מפתח בדיוק.

כדי לייבא מחדש גרסת מפתח שהושמדה, צריך לבצע את אותו תהליך כמו בייבוא הראשוני, באמצעות משימת הייבוא המקורית או משימת ייבוא חדשה (עם אותה רמת הגנה SOFTWARE).