Realización de operaciones criptográficas con la API de GREP11

IBM Cloud® Hyper Protect Crypto Services proporciona una API de Enterprise PKCS #11 (EP11) a través de gRPC (también recibe el nombre de API de GREP11) para acceder de forma remota a la instancia del servicio Hyper Protect Crypto Services para el cifrado y la gestión de datos.

Recuperación de sus credenciales de IBM Cloud

Para trabajar con la API, debe generar credenciales de servicio y autenticación. Para recopilar sus credenciales:

  1. Genere una señal de acceso de IBM Cloud IAM.
  2. Recupere el ID de instancia que identifica de forma exclusiva la instancia de servicio de Hyper Protect Crypto Services.

Generación de una solicitud de API de GREP11

Para acceder de forma remota al HSM de nube en Hyper Protect Crypto Services para realizar operaciones criptográficas, debe generar una solicitud de API GREP11 y pasar el URL de punto final de API GREP11, la clave de API de ID de servicio y el punto final de IAM a través de la llamada de API.

Para el plan estándar Hyper Protect Crypto Services, también puede habilitar TLS mutuo para la API GREP11 para añadir otra capa de autenticación. Para obtener más información, consulte Habilitación de la segunda capa de autenticación para las conexiones EP11.

Ejemplo: Generación de datos aleatorios utilizando la función GenerateRandomRequest()

La API GREP11 soporta lenguajes de programación con bibliotecas gRPC. Se proporcionan dos repositorios GitHub de ejemplo para probar la API de GREP11:

Puede utilizar el siguiente ejemplo de código Golang para generar datos aleatorios llamando a la función GenerateRandom.

En este ejemplo se presupone que se incluyen paquetes Golang necesarios adicionales a través de sentencias de importación, como por ejemplo los paquetes gRPC y http. GREP11 utiliza la sentencia import pb "github.com/IBM-Cloud/hpcs-grep11-go/grpc" para realizar llamadas a funciones de API.

import pb "github.com/IBM-Cloud/hpcs-grep11-go/grpc"

// Data structure and supporting methods used for GREP11 authentication
// IAMPerRPCCredentials type defines the fields required for IBM Cloud IAM authentication
// This type implements the gRPC PerRPCCredentials interface

type IAMPerRPCCredentials struct {
	expiration  time.Time
	updateLock  sync.Mutex
	AccessToken string // Required if APIKey nor Endpoint are specified - IBM Cloud IAM access token
	APIKey      string // Required if AccessToken is not specified - IBM Cloud API key
	Endpoint    string // Required if AccessToken is not specified - IBM Cloud IAM endpoint
}

// GetRequestMetadata is used by GRPC for authentication
func (cr *IAMPerRPCCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	// Set token if empty or Set token if expired
	if len(cr.APIKey) != 0 && len(cr.Endpoint) != 0 && time.Now().After(cr.expiration) {
		if err := cr.getToken(ctx); err != nil {
			return nil, err
		}
	}

	return map[string]string{
		"authorization":    cr.AccessToken,
	}, nil
}

// RequireTransportSecurity is used by gRPC for authentication
func (cr *IAMPerRPCCredentials) RequireTransportSecurity() bool {
	return true
}

// getToken obtains a bearer token and the expiration
func (cr *IAMPerRPCCredentials) getToken(ctx context.Context) (err error) {
	cr.updateLock.Lock()
	defer cr.updateLock.Unlock()

	// Check if another thread has updated the token
	if time.Now().Before(cr.expiration) {
		return nil
	}

	var req *http.Request
	client := http.Client{}
	requestBody := []byte("grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=" + cr.APIKey)

	req, err = http.NewRequest("POST", cr.Endpoint+"/identity/token", bytes.NewBuffer(requestBody))
	if err != nil {
		return err
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req = req.WithContext(ctx)
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response body: %s", err)
	}
	defer resp.Body.Close()

	iamToken := struct {
		AccessToken string `json:"access_token"`
		ExpiresIn   int32  `json:"expires_in"`
	}{}

	err = json.Unmarshal(respBody, &iamToken)
	if err != nil {
		return fmt.Errorf("error unmarshaling response body: %s", err)
	}

	cr.AccessToken = fmt.Sprintf("Bearer %s", iamToken.AccessToken)
	cr.expiration = time.Now().Add((time.Duration(iamToken.ExpiresIn - 60)) * time.Second)

	return nil
}

// Generating a GREP11 API function call

// The following IBM Cloud items need to be changed prior to running the sample program
const address = "<grep11_server_address>"

var callOpts = []grpc.DialOption{
  grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
  grpc.WithPerRPCCredentials(&util.IAMPerRPCCredentials{
    APIKey:   "<ibm_cloud_apikey>",
    Endpoint: "https://iam.cloud.ibm.com",
  }),
}

conn, err := grpc.Dial(address, callOpts...)
if err != nil {
		panic(fmt.Errorf("Could not connect to server: %s", err))
}
defer conn.Close()

cryptoClient := pb.NewCryptoClient(conn)

rngTemplate := &pb.GenerateRandomRequest{
		Len: (uint64)(ep11.AES_BLOCK_SIZE),
}

// Generate 16 bytes of random data for the initialization vector
rng, err := cryptoClient.GenerateRandom(context.Background(), rngTemplate)
if err != nil {
		panic(fmt.Errorf("GenerateRandom Error: %s", err))
}
iv := rng.Rnd[:ep11.AES_BLOCK_SIZE]
fmt.Println("Generated IV")

En el ejemplo, actualice las variables siguientes:

  • Sustituya <grep11_server_address> por el valor del punto final de API GREP11. Para encontrar el URL de punto final de servicio, en la interfaz de usuario de la instancia de servicio suministrada, pulse Visión general > Conectar > URL de punto final Enterprise PKCS #11. De forma alternativa, puede recuperar dinámicamente el URL de punto final de API. El valor devuelto incluye lo siguiente. En función de si va a utilizar una red privada o pública, utilice el valor de punto final de servicio público o privado que se devuelve en la sección ep11.

    {
      "instance_id": "<instance_ID>",
      "kms": {
        "public": "<instance_ID>.api.<region>.hs-crypto.appdomain.cloud",
        "private":"<instance_ID>.api.private.<region>.hs-crypto.appdomain.cloud"
      },
      "ep11": {
        "public": "<instance_ID>.ep11.<region>.hs-crypto.appdomain.cloud",
        "private":"<instance_ID>.ep11.private.<region>.hs-crypto.appdomain.cloud"
      }
    }
    

    Si crea las instancias después del 12 de abril de 2024 en determinadas regiones, es posible que tenga que utilizar los nuevos puntos finales de API con el nuevo formato como <instance_ID>.ep11.<REGION>.hs-crypto.appdomain.cloud. La fecha de disponibilidad varía según la región. Para obtener más información sobre las regiones soportadas, las fechas de disponibilidad y los nuevos URL de punto final, consulte Nuevos puntos finales.

  • Sustituya <ibm_cloud_apikey> por la clave de API de ID de servicio que ha creado. La clave de API de ID de servicio se puede crear siguiendo la instrucción de Gestión de la clave de API de ID de servicio.

Si la solicitud de ejemplo se procesa satisfactoriamente, se devolverán datos aleatorios con una longitud de 16 bytes, tal como se especifica en ep11.AES_BLOCKSIZE.

El ejemplo de autenticación anterior, así como más ejemplos de código Golang se pueden encontrar en:

Qué hacer a continuación

Ya está todo listo para empezar a gestionar datos y claves de cifrado. Para obtener más información sobre cómo gestionar sus datos utilizando la función de HSM de nube de Hyper Protect Crypto Services, consulte el documento de referencia de la API de GREP11.