Recupera una firma asimétrica

Obtén una firma asimétrica del hash SHA-256 de un mensaje de entrada con la API de KMS.

Páginas de documentación que incluyen esta muestra de código

Para ver la muestra de código usada en contexto, consulta la siguiente documentación:

Muestra de código

C#

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.


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

Comienza a usarlo

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.

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

	kms "cloud.google.com/go/kms/apiv1"
	kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
	"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: %v", 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: %v", 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.AsymmetricSignRequest{
		Name: name,
		Digest: &kmspb.Digest{
			Digest: &kmspb.Digest_Sha256{
				Sha256: digest.Sum(nil),
			},
		},
		DigestCrc32C: wrapperspb.Int64(int64(digestCRC32C)),
	}

	// Call the API.
	result, err := client.AsymmetricSign(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to sign digest: %v", err)
	}

	// Optional, but recommended: perform integrity verification on result.
	// For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
	// https://cloud.google.com/kms/docs/data-integrity-guidelines
	if result.VerifiedDigestCrc32C == false {
		return fmt.Errorf("AsymmetricSign: request corrupted in-transit")
	}
	// TODO(iamtamjam) Uncomment when this field is populated by the server
	// if result.Name != req.Name {
	//	return fmt.Errorf("AsymmetricSign: request corrupted in-transit")
	// }
	if int64(crc32c(result.Signature)) != result.SignatureCrc32C.Value {
		return fmt.Errorf("AsymmetricSign: response corrupted in-transit")
	}

	fmt.Fprintf(w, "Signed digest: %s", result.Signature)
	return nil
}

Java

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.

import com.google.cloud.kms.v1.AsymmetricSignResponse;
import com.google.cloud.kms.v1.CryptoKeyVersionName;
import com.google.cloud.kms.v1.Digest;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;

public class SignAsymmetric {

  public void signAsymmetric() throws IOException, GeneralSecurityException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String locationId = "us-east1";
    String keyRingId = "my-key-ring";
    String keyId = "my-key";
    String keyVersionId = "123";
    String message = "my message";
    signAsymmetric(projectId, locationId, keyRingId, keyId, keyVersionId, message);
  }

  // Get the public key associated with an asymmetric key.
  public void signAsymmetric(
      String projectId,
      String locationId,
      String keyRingId,
      String keyId,
      String keyVersionId,
      String message)
      throws IOException, GeneralSecurityException {
    // 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 key version name from the project, location, key ring, key,
      // and key version.
      CryptoKeyVersionName keyVersionName =
          CryptoKeyVersionName.of(projectId, locationId, keyRingId, keyId, keyVersionId);

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

      // Calculate the digest.
      MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
      byte[] hash = sha256.digest(plaintext);

      // Build the digest object.
      Digest digest = Digest.newBuilder().setSha256(ByteString.copyFrom(hash)).build();

      // Sign the digest.
      AsymmetricSignResponse result = client.asymmetricSign(keyVersionName, digest);

      // Get the signature.
      byte[] signature = result.getSignature().toByteArray();

      System.out.printf("Signature %s%n", signature);
    }
  }
}

Node.js

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.

//
// TODO(developer): Uncomment these variables before running the sample.
//
// const projectId = 'your-project-id';
// const locationId = 'us-east1';
// const keyRingId = 'my-key-ring';
// const keyId = 'my-key';
// const versionId = '123';
// const message = Buffer.from('...');

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

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

// Build the version name
const versionName = client.cryptoKeyVersionPath(
  projectId,
  locationId,
  keyRingId,
  keyId,
  versionId
);

async function signAsymmetric() {
  // Create a digest of the message. The digest needs to match the digest
  // configured for the Cloud KMS key.
  const crypto = require('crypto');
  const hash = crypto.createHash('sha256');
  hash.update(message);
  const digest = hash.digest();

  // Optional but recommended: Compute digest's CRC32C.
  const crc32c = require('fast-crc32c');
  const digestCrc32c = crc32c.calculate(digest);

  // Sign the message with Cloud KMS
  const [signResponse] = await client.asymmetricSign({
    name: versionName,
    digest: {
      sha256: digest,
    },
    digestCrc32c: {
      value: digestCrc32c,
    },
  });

  // Optional, but recommended: perform integrity verification on signResponse.
  // For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
  // https://cloud.google.com/kms/docs/data-integrity-guidelines
  if (signResponse.name !== versionName) {
    throw new Error('AsymmetricSign: request corrupted in-transit');
  }
  if (!signResponse.verifiedDigestCrc32c) {
    throw new Error('AsymmetricSign: request corrupted in-transit');
  }
  if (
    crc32c.calculate(signResponse.signature) !==
    Number(signResponse.signatureCrc32c.value)
  ) {
    throw new Error('AsymmetricSign: response corrupted in-transit');
  }

  // Example of how to display signature. Because the signature is in a binary
  // format, you need to encode the output before printing it to a console or
  // displaying it on a screen.
  const encoded = signResponse.signature.toString('base64');
  console.log(`Signature: ${encoded}`);

  return signResponse.signature;
}

return signAsymmetric();

PHP

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.

use Google\Cloud\Kms\V1\KeyManagementServiceClient;
use Google\Cloud\Kms\V1\Digest;

function sign_asymmetric_sample(
    string $projectId = 'my-project',
    string $locationId = 'us-east1',
    string $keyRingId = 'my-key-ring',
    string $keyId = 'my-key',
    string $versionId = '123',
    string $message = '...'
) {
    // Create the Cloud KMS client.
    $client = new KeyManagementServiceClient();

    // Build the key version name.
    $keyVersionName = $client->cryptoKeyVersionName($projectId, $locationId, $keyRingId, $keyId, $versionId);

    // Calculate the hash.
    $hash = hash('sha256', $message, true);

    // Build the digest.
    //
    // Note: Key algorithms will require a varying hash function. For
    // example, EC_SIGN_P384_SHA384 requires SHA-384.
    $digest = (new Digest())
        ->setSha256($hash);

    // Call the API.
    $signResponse = $client->asymmetricSign($keyVersionName, $digest);
    printf('Signature: %s' . PHP_EOL, $signResponse->getSignature());
    return $signResponse;
}

Python

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.

def sign_asymmetric(project_id, location_id, key_ring_id, key_id, version_id, message):
    """
    Sign a message using the public key part of an asymmetric key.

    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').
        key_id (string): ID of the key to use (e.g. 'my-key').
        version_id (string): Version to use (e.g. '1').
        message (string): Message to sign.

    Returns:
        AsymmetricSignResponse: Signature.
    """

    # Import the client library.
    from google.cloud import kms

    # Import base64 for printing the ciphertext.
    import base64

    # Import hashlib for calculating hashes.
    import hashlib

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

    # Build the key version name.
    key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, version_id)

    # Convert the message to bytes.
    message_bytes = message.encode('utf-8')

    # Calculate the hash.
    hash_ = hashlib.sha256(message_bytes).digest()

    # Build the digest.
    #
    # Note: Key algorithms will require a varying hash function. For
    # example, EC_SIGN_P384_SHA384 requires SHA-384.
    digest = {'sha256': hash_}

    # Optional, but recommended: compute digest's CRC32C.
    # See crc32c() function defined below.
    digest_crc32c = crc32c(hash_)

    # Call the API
    sign_response = client.asymmetric_sign(
        request={'name': key_version_name, 'digest': digest, 'digest_crc32c': digest_crc32c})

    # Optional, but recommended: perform integrity verification on sign_response.
    # For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
    # https://cloud.google.com/kms/docs/data-integrity-guidelines
    if not sign_response.verified_digest_crc32c:
        raise Exception('The request sent to the server was corrupted in-transit.')
    if not sign_response.name == key_version_name:
        raise Exception('The request sent to the server was corrupted in-transit.')
    if not sign_response.signature_crc32c == crc32c(sign_response.signature):
        raise Exception('The response received from the server was corrupted in-transit.')
    # End integrity verification

    print('Signature: {}'.format(base64.b64encode(sign_response.signature)))
    return sign_response

def crc32c(data):
    """
    Calculates the CRC32C checksum of the provided data.
    Args:
        data: the bytes over which the checksum should be calculated.
    Returns:
        An int representing the CRC32C checksum of the provided bytes.
    """
    import crcmod
    import six
    crc32c_fun = crcmod.predefined.mkPredefinedCrcFun('crc-32c')
    return crc32c_fun(six.ensure_binary(data))

Ruby

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Cloud KMS, consulta Bibliotecas cliente de Cloud KMS.

# TODO(developer): uncomment these values before running the sample.
# project_id  = "my-project"
# location_id = "us-east1"
# key_ring_id = "my-key-ring"
# key_id      = "my-key"
# version_id  = "123"
# message     = "my message"

# Require the library.
require "google/cloud/kms"

# Require digest.
require "digest"

# Create the client.
client = Google::Cloud::Kms.key_management_service

# Build the key version name.
key_version_name = client.crypto_key_version_path project:            project_id,
                                                  location:           location_id,
                                                  key_ring:           key_ring_id,
                                                  crypto_key:         key_id,
                                                  crypto_key_version: version_id

# Calculate the hash.
#
# Note: Key algorithms will require a varying hash function. For
# example, EC_SIGN_P384_SHA384 requires SHA-384.
digest = { sha256: Digest::SHA256.digest(message) }

# Call the API.
sign_response = client.asymmetric_sign name: key_version_name, digest: digest
puts "Signature: #{Base64.strict_encode64 sign_response.signature}"

¿Qué sigue?

Para buscar y filtrar muestras de código para otros productos de Google Cloud, consulta el navegador de muestra de Google Cloud.