Executando operações criptográficas com a API GREP11

O IBM Cloud® Hyper Protect Crypto Services fornece uma API do Enterprise PKCS nº 11 (EP11) por gRPC (também chamada de API de GREP11) para acessar remotamente a instância de serviço do Hyper Protect Crypto Services para criptografia e gerenciamento de dados.

Recuperando as suas credenciais do IBM Cloud

Para trabalhar com a API, é necessário gerar suas credenciais de serviço e autenticação. Para reunir suas credenciais:

  1. Gere um token de acesso do IBM Cloud IAM.
  2. Recupere o ID da instância que identifica exclusivamente a sua Hyper Protect Crypto Services instância de serviço.

Gerando uma solicitação de API GREP11

Para acessar remotamente o HSM em nuvem no Hyper Protect Crypto Services para executar operações criptográficas, é necessário gerar uma solicitação de API do GREP11 e transmitir a URL do terminal de API do GREP11, a chave de API do ID de serviço e o terminal do IAM por meio da chamada de API.

Para o plano padrão Hyper Protect Crypto Services, também é possível ativar o TLS mútuo para a API GREP11 para incluir outra camada de autenticação. Para obter mais informações, consulte Ativando a segunda camada de autenticação para conexões do EP11.

Exemplo: gerando dados aleatórios usando a função GenerateRandomRequest()

A API GREP11 suporta linguagens de programação com bibliotecas gRPC. Dois repositórios de amostra do GitHub são fornecidos para você testar a API do GREP11:

É possível usar o exemplo de código de Golang a seguir para gerar dados aleatórios chamando a função GenerateRandom.

Este exemplo assume que pacotes Golang extra necessários são incluídos por meio de instruções de importação, como os pacotes gRPC e http. A declaração import pb "github.com/IBM-Cloud/hpcs-grep11-go/grpc" é usada pelo GREP11 para executar chamadas de função 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")

No exemplo, atualize as variáveis a seguir:

  • Substitua <grep11_server_address> pelo valor do terminal de API GREP11. Para localizar a URL do terminal em serviço, por meio de sua IU da instância de serviço provisionada, clique na Visão geral >> Conectar > URL do terminal do Enterprise PKCS #11 Como alternativa, é possível recuperar dinamicamente a URL do terminal de API O valor retornado inclui o seguinte. Dependendo se você está usando a rede pública ou privada, use o valor do terminal de serviço público ou privado que é retornado na seção 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"
      }
    }
    

    Se você criar suas instâncias após 12 de abril de 2024 em determinadas regiões, poderá ser necessário usar os novos terminais de API com o novo formato como <instance_ID>.ep11.<REGION>.hs-crypto.appdomain.cloud A data de disponibilidade varia por região. Para obter mais informações sobre as regiões suportadas, as datas de disponibilidade e as novas URLs de terminal, consulte Novos terminais

  • Substitua <ibm_cloud_apikey> pela chave de API de ID de serviço que você criou. A chave API do ID de serviço pode ser criada seguindo a instrução em Gerenciando a chave API do ID de serviço.

Se a solicitação de amostra for processada com sucesso, serão retornados dados aleatórios com comprimento de 16 bytes, conforme especificado em ep11.AES_BLOCKSIZE.

O exemplo de autenticação anterior, bem como mais exemplos de código Golang, podem ser localizados em:

O que vem a seguir

Você está pronto para iniciar o gerenciamento de suas chaves de criptografia e dados. Para descobrir mais sobre o gerenciamento de seus dados usando a função HSM em nuvem do Hyper Protect Crypto Services, confira o doc de referência da API do GREP11.