デジタル署名の作成と検証

このトピックでは、非対称鍵に基づくデジタル署名の作成と検証について説明します。

デジタル署名は、非対称鍵の秘密鍵部分を使用して作成します。署名の検証は、同じ非対称鍵の公開鍵部分を使用して行います。

始める前に

  • デジタル署名を作成するときは、ASYMMETRIC_SIGN鍵の目的とする鍵を使用する必要があります。鍵の作成には、ASYMMETRIC_SIGN を使用します。

  • 署名を検証するには、鍵の作成時に使用された完全なアルゴリズムを知る必要があります。openssl コマンドを使用する以下のコマンドラインの手順については、これらのコマンドにこの情報を渡す必要があります。

  • 署名を行うユーザーまたはサービスに、非対称鍵に対する cloudkms.cryptoKeyVersions.useToSign 権限を付与します。Cloud Key Management Service の権限については、権限とロールをご覧ください。

  • 署名を検証する場合は、検証に使用する公開鍵をダウンロードするユーザーまたはサービスに、非対称鍵に対する cloudkms.cryptoKeyVersions.viewPublicKey 権限を付与します。

  • コマンドラインを使用する場合、OpenSSL をまだインストールしていなければ、ここでインストールしてください。Cloud Shell を使用する場合、OpenSSL はすでにインストールされています。

データとダイジェスト

AsymmetricSign リクエストに指定された入力は、data フィールドや digest フィールドを介して渡すことができます。これらのフィールドは、同時に指定できません。未加工アルゴリズムCloud External Key Manager 鍵を使用した署名など、データ フィールドを必要とするアルゴリズムもあります。

未加工アルゴリズム

「未加工」アルゴリズム(RSA_SIGN_RAW_ 接頭辞で識別)は、DigestInfo へのエンコードを省略した PKCS #1 署名のバリアントです。バリアントでは、次のことが行われます。

  • ダイジェストは、署名されるメッセージに対して計算されます。
  • ダイジェストには、直接 PKCS #1 パディングが適用されます。
  • パディングされたダイジェストの署名は、RSA 秘密鍵を使用して計算されます。

こうしたアルゴリズムを使用するには、次のようにします。

  • 未加工データは、(ダイジェストの代わりに)data フィールドの一部として提供する必要があります。
  • データの長さの上限は、RSA 鍵のサイズよりも 11 バイト少なくします。たとえば、2,048 ビットの RSA 鍵がある PKCS #1 では、最大 245 バイトに署名できます。
  • cloudkms.expertRawPKCS1 ロールを適切なユーザーまたはサービスに付与します。Cloud Key Management Service の権限については、権限とロールをご覧ください。

未加工のアルゴリズムを使用すると、事前定義されたアルゴリズムが使用できないダイジェスト タイプに署名することもできます。たとえば、RSA_SIGN_RAW_2048 鍵を使用して、外部で計算済みの SHA-512 PKCS #1 DigestInfo 構造に署名できます。このプロセスでは、標準の RSA_SIGN_PKCS1_2048_SHA512 アルゴリズムと同じ結果が生成されます。

他のハッシュ アルゴリズムの ECDSA サポート

ECDSA 署名アルゴリズムの一般的な形式は次のとおりです。

EC_SIGN_ELLIPTIC_CURVE_[DIGEST_ALGORITHM]

DIGEST_ALGORITHM の値は SHA256SHA384、または SHA512 です。ハッシュは署名を作成する前に行われるため、これらの署名アルゴリズムは、Keccak などの SHA 以外のダイジェストでも使用できます。Keccak ダイジェストを使用するには、Keccak ハッシュ値を指定し、同じ長さの SHA ダイジェスト アルゴリズムを使用します。たとえば、EC_SIGN_P256_SHA256 アルゴリズムを使用するリクエストで KECCAK256 ダイジェストを使用できます。

署名の作成

gcloud

コマンドラインで Cloud KMS を使用するには、まず Google Cloud CLI の最新バージョンをインストールまたはアップグレードします

gcloud kms asymmetric-sign \
    --version key-version \
    --key key \
    --keyring key-ring \
    --location location \
    --digest-algorithm digest-algorithm \
    --input-file input-file \
    --signature-file signature-file

key-version は、署名に使用する鍵のバージョンに置き換えます。key は、鍵名で置き換えます。key-ring は、鍵が配置されている鍵リングの名前に置き換えます。location を鍵リングの Cloud KMS の場所に置き換えます。digest-algorithm は、使用するアルゴリズムに置き換えます。input-file を Cloud KMS に送信して署名する場合は、digest-algorithm を省略します。input-filesignature-file は、署名するファイルのローカルパスと署名ファイルに置き換えます。

すべてのフラグと有効な値については、--help フラグを指定してコマンドを実行してください。

C#

このコードを実行するには、まず C# 開発環境を設定し、Cloud KMS C# SDK をインストールします。


using Google.Cloud.Kms.V1;
using Google.Protobuf;
using System.Security.Cryptography;
using System.Text;

public class SignAsymmetricSample
{
    public byte[] SignAsymmetric(
      string projectId = "my-project", string locationId = "us-east1", string keyRingId = "my-key-ring", string keyId = "my-key", string keyVersionId = "123",
      string message = "Sample message")
    {
        // Create the client.
        KeyManagementServiceClient client = KeyManagementServiceClient.Create();

        // Build the key version name.
        CryptoKeyVersionName keyVersionName = new CryptoKeyVersionName(projectId, locationId, keyRingId, keyId, keyVersionId);

        // Convert the message into bytes. Cryptographic plaintexts and
        // ciphertexts are always byte arrays.
        byte[] plaintext = Encoding.UTF8.GetBytes(message);

        // Calculate the digest.
        SHA256 sha256 = SHA256.Create();
        byte[] hash = sha256.ComputeHash(plaintext);

        // Build the digest.
        //
        // Note: Key algorithms will require a varying hash function. For
        // example, EC_SIGN_P384_SHA384 requires SHA-384.
        Digest digest = new Digest
        {
            Sha256 = ByteString.CopyFrom(hash),
        };

        // Call the API.
        AsymmetricSignResponse result = client.AsymmetricSign(keyVersionName, digest);

        // Get the signature.
        byte[] signature = result.Signature.ToByteArray();

        // Return the result.
        return signature;
    }
}

Go

このコードを実行するには、まず Go 開発環境を設定し、Cloud KMS Go SDK をインストールします。

import (
	"context"
	"crypto/sha256"
	"fmt"
	"hash/crc32"
	"io"

	kms "cloud.google.com/go/kms/apiv1"
	"cloud.google.com/go/kms/apiv1/kmspb"
	"google.golang.org/protobuf/types/known/wrapperspb"
)

// signAsymmetric will sign a plaintext message using a saved asymmetric private
// key stored in Cloud KMS.
func signAsymmetric(w io.Writer, name string, message string) error {
	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key/cryptoKeyVersions/123"
	// message := "my message"

	// 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()

	// Convert the message into bytes. Cryptographic plaintexts and
	// ciphertexts are always byte arrays.
	plaintext := []byte(message)

	// Calculate the digest of the message.
	digest := sha256.New()
	if _, err := digest.Write(plaintext); err != nil {
		return fmt.Errorf("failed to create digest: %w", err)
	}

	// Optional but recommended: Compute digest's CRC32C.
	crc32c := func(data []byte) uint32 {
		t := crc32.MakeTable(crc32.Castagnoli)
		return crc32.Checksum(data, t)

	}
	digestCRC32C := crc32c(digest.Sum(nil))

	// Build the signing request.
	//
	// Note: Key algorithms will require a varying hash function. For example,
	// EC_SIGN_P384_SHA384 requires SHA-384.
	req := &kmspb