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

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

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

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

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

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

הכנת הפרויקט

  1. 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

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

  3. Enable the required API.

    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

  4. התקינו את ה-CLI של Google Cloud.

  5. הגדירו שה-CLI של gcloud ישתמש בזהות המאוחדת שלכם.

    איך נכנסים ל-CLI של gcloud באמצעות הזהות המאוחדת?

  6. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    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. בשדה Key ring name (שם אוסף המפתחות), מזינים את השם של אוסף המפתחות.

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

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

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

  7. בקטע רמת הגנה, בוחרים באפשרות תוכנה.

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

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

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

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

    אם מפעילים רוטציה אוטומטית, גרסאות מפתח חדשות ייווצרו ב-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 \
      --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 "{}"
    

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

  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"}}"
    

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

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

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

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

ייבוא מפתחות חסינים מפני פיצוח קוונטי נתמך רק ברמת ההגנה 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. לוחצים על הכרטיסייה Import Jobs (פעולות ייבוא) בחלק העליון של הדף.

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

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 ולהתקין את Cloud KMS Java SDK.

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 .

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

  3. לוחצים על הכרטיסייה Import Jobs (פעולות ייבוא) בחלק העליון של הדף.

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

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).