examples

package
v0.0.0-...-9b092e4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2021 License: Apache-2.0 Imports: 0 Imported by: 0

Documentation

Overview

Package examples provide GREP11 function call examples. Regular function calls have four steps. The following is one example to generate a key:

1 cryptoClient := pb.NewCryptoClient(conn) // create a crypto client 2 Template := util.NewAttributeMap // create a template 3 keygenmsg, err := &pb.GenerateKeyRequest() // create RPC request parameters 4 if err != nill {...} // check for an error

Example (DeriveKey)

Example_deriveKey generates ECDHE key pairs for Bob and Alice and then generates AES keys for both of them. The names Alice and Bob are described in https://en.wikipedia.org/wiki/Diffie–Hellman_key_exchange. Flow: connect, generate key pairs, derive AES key for Bob, derive AES key for Alice, encrypt with Alice's AES key and decrypt with Bob's AES key

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)

// Generate ECDH key pairs for Alice and Bob
ecParameters, err := asn1.Marshal(util.OIDNamedCurveP256)
if err != nil {
	panic(fmt.Errorf("Unable to encode parameter OID: %s", err))
}

publicKeyECTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_EC_PARAMS, ecParameters),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
privateKeyECTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_DERIVE, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
generateECKeypairRequest := &pb.GenerateKeyPairRequest{
	Mech:            &pb.Mechanism{Mechanism: ep11.CKM_EC_KEY_PAIR_GEN},
	PubKeyTemplate:  publicKeyECTemplate,
	PrivKeyTemplate: privateKeyECTemplate,
}
aliceECKeypairResponse, err := cryptoClient.GenerateKeyPair(context.Background(), generateECKeypairRequest)
if err != nil {
	panic(fmt.Errorf("Generate Alice EC key pair error: %s", err))
}
fmt.Println("Generated Alice EC key pair")

bobECKeypairResponse, err := cryptoClient.GenerateKeyPair(context.Background(), generateECKeypairRequest)
if err != nil {
	panic(fmt.Errorf("Generate Bob EC key pair error: %s", err))
}
fmt.Println("Generated Bob EC key pair")

// Derive AES key for Alice
deriveKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_CLASS, uint64(ep11.CKO_SECRET_KEY)),
	util.NewAttribute(ep11.CKA_KEY_TYPE, uint64(ep11.CKK_AES)),
	util.NewAttribute(ep11.CKA_VALUE_LEN, (uint64)(128/8)),
	util.NewAttribute(ep11.CKA_ENCRYPT, true),
	util.NewAttribute(ep11.CKA_DECRYPT, true),
)
combinedCoordinates, err := util.GetPubkeyBytesFromSPKI(bobECKeypairResponse.PubKey)
if err != nil {
	panic(fmt.Errorf("Bob's EC key cannot obtain coordinates: %s", err))
}
aliceDerivekeyRequest := &pb.DeriveKeyRequest{
	Mech:     &pb.Mechanism{Mechanism: ep11.CKM_ECDH1_DERIVE, Parameter: combinedCoordinates},
	Template: deriveKeyTemplate,
	BaseKey:  aliceECKeypairResponse.PrivKey,
}
aliceDerivekeyResponse, err := cryptoClient.DeriveKey(context.Background(), aliceDerivekeyRequest)
if err != nil {
	panic(fmt.Errorf("Alice EC key derive error: %s", err))
}

// Derive AES key for Bob
combinedCoordinates, err = util.GetPubkeyBytesFromSPKI(aliceECKeypairResponse.PubKey)
if err != nil {
	panic(fmt.Errorf("Alice's EC key cannot obtain coordinates: %s", err))
}
bobDerivekeyRequest := &pb.DeriveKeyRequest{
	Mech:     &pb.Mechanism{Mechanism: ep11.CKM_ECDH1_DERIVE, Parameter: combinedCoordinates},
	Template: deriveKeyTemplate,
	BaseKey:  bobECKeypairResponse.PrivKey,
}
bobDerivekeyResponse, err := cryptoClient.DeriveKey(context.Background(), bobDerivekeyRequest)
if err != nil {
	panic(fmt.Errorf("Bob EC Key Derive Error: %s", err))
}

// Encrypt with Alice's key and decrypt with Bob's key
var msg = []byte("hello world!")
rngTemplate := &pb.GenerateRandomRequest{
	Len: (uint64)(ep11.AES_BLOCK_SIZE),
}
rng, err := cryptoClient.GenerateRandom(context.Background(), rngTemplate)
if err != nil {
	panic(fmt.Errorf("GenerateRandom error: %s", err))
}
iv := rng.Rnd[:ep11.AES_BLOCK_SIZE]
encryptRequest := &pb.EncryptSingleRequest{
	Key:   aliceDerivekeyResponse.NewKey,
	Mech:  &pb.Mechanism{Mechanism: ep11.CKM_AES_CBC_PAD, Parameter: iv},
	Plain: msg,
}
encryptResponse, err := cryptoClient.EncryptSingle(context.Background(), encryptRequest)
if err != nil {
	panic(fmt.Errorf("Encrypt error: %s", err))
}

decryptRequest := &pb.DecryptSingleRequest{
	Key:      bobDerivekeyResponse.NewKey,
	Mech:     &pb.Mechanism{Mechanism: ep11.CKM_AES_CBC_PAD, Parameter: iv},
	Ciphered: encryptResponse.Ciphered,
}
decryptResponse, err := cryptoClient.DecryptSingle(context.Background(), decryptRequest)
if err != nil {
	panic(fmt.Errorf("Decrypt error: %s", err))
}

if !bytes.Equal(decryptResponse.Plain, msg) {
	panic(fmt.Errorf("Decrypted message[%v] is different from the original message: [%v]", decryptResponse.Plain, msg))
} else {
	fmt.Println("Alice and Bob get the same derived key")
}

return
Output:

Generated Alice EC key pair
Generated Bob EC key pair
Alice and Bob get the same derived key
Example (Digest)

Example_digest calculates the digest of some plain text Flow: connect, digest single-part data, digest multi-part data

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)

digestData := []byte("This is the data longer than 64 bytes This is the data longer than 64 bytes")
digestInitRequest := &pb.DigestInitRequest{
	Mech: &pb.Mechanism{Mechanism: ep11.CKM_SHA256},
}
digestInitResponse, err := cryptoClient.DigestInit(context.Background(), digestInitRequest)
if err != nil {
	panic(fmt.Errorf("Digest init error: %s", err))
}
digestRequest := &pb.DigestRequest{
	State: digestInitResponse.State,
	Data:  digestData,
}
digestResponse, err := cryptoClient.Digest(context.Background(), digestRequest)
if err != nil {
	panic(fmt.Errorf("Digest error: %s", err))
} else {
	fmt.Printf("Digest data using a single digest operation: %x\n", digestResponse.Digest)
}

// Digest using mutiple operations
digestInitResponse, err = cryptoClient.DigestInit(context.Background(), digestInitRequest)
if err != nil {
	panic(fmt.Errorf("Digest init error: %s", err))
}
digestUpdateRequest := &pb.DigestUpdateRequest{
	State: digestInitResponse.State,
	Data:  digestData[:64],
}
digestUpdateResponse, err := cryptoClient.DigestUpdate(context.Background(), digestUpdateRequest)
if err != nil {
	panic(fmt.Errorf("Digest update error: %s", err))
}
digestUpdateRequest = &pb.DigestUpdateRequest{
	State: digestUpdateResponse.State,
	Data:  digestData[64:],
}
digestUpdateResponse, err = cryptoClient.DigestUpdate(context.Background(), digestUpdateRequest)
if err != nil {
	panic(fmt.Errorf("Digest update error: %s", err))
}
digestFinalRequestInfo := &pb.DigestFinalRequest{
	State: digestUpdateResponse.State,
}
digestFinalResponse, err := cryptoClient.DigestFinal(context.Background(), digestFinalRequestInfo)
if err != nil {
	panic(fmt.Errorf("Digest final error: %s", err))
} else {
	fmt.Printf("Digest data using multiple operations: %x\n", digestFinalResponse.Digest)
}
Output:

Digest data using a single digest operation: ad4e0b6e309d192862ec6db692d17072ddd3a98ccd37afe642a04f7ca554c94c
Digest data using multiple operations: ad4e0b6e309d192862ec6db692d17072ddd3a98ccd37afe642a04f7ca554c94c
Example (EncryptAndDecrypt)

Example_encryptAndDecrypt encrypts and decrypts plain text Flow: connect, generate AES key, generate IV, encrypt multi-part data, decrypt multi-part data

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)
keyLen := 128
keyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_VALUE_LEN, (uint64)(keyLen/8)),
	util.NewAttribute(ep11.CKA_WRAP, false),
	util.NewAttribute(ep11.CKA_UNWRAP, false),
	util.NewAttribute(ep11.CKA_ENCRYPT, true),
	util.NewAttribute(ep11.CKA_DECRYPT, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false), // set to false!
	util.NewAttribute(ep11.CKA_TOKEN, true),        // ignored by EP11
)

keygenmsg := &pb.GenerateKeyRequest{
	Mech:     &pb.Mechanism{Mechanism: ep11.CKM_AES_KEY_GEN},
	Template: keyTemplate,
	KeyId:    uuid.NewV4().String(), // optional
}

generateKeyStatus, err := cryptoClient.GenerateKey(context.Background(), keygenmsg)
if err != nil {
	panic(fmt.Errorf("GenerateKey Error: %s", err))
}
fmt.Println("Generated AES Key")

rngTemplate := &pb.GenerateRandomRequest{
	Len: (uint64)(ep11.AES_BLOCK_SIZE),
}
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")

encipherInitInfo := &pb.EncryptInitRequest{
	Mech: &pb.Mechanism{Mechanism: ep11.CKM_AES_CBC_PAD, Parameter: iv},
	Key:  generateKeyStatus.Key, // you may want to store this
}
cipherStateInit, err := cryptoClient.EncryptInit(context.Background(), encipherInitInfo)
if err != nil {
	panic(fmt.Errorf("Failed EncryptInit [%s]", err))
}

plain := []byte("Hello, this is a very long and creative message without any imagination")

encipherDataUpdate := &pb.EncryptUpdateRequest{
	State: cipherStateInit.State,
	Plain: plain[:20],
}
encipherStateUpdate, err := cryptoClient.EncryptUpdate(context.Background(), encipherDataUpdate)
if err != nil {
	panic(fmt.Errorf("Failed Encrypt [%s]", err))
}

ciphertext := encipherStateUpdate.Ciphered[:]
encipherDataUpdate = &pb.EncryptUpdateRequest{
	State: encipherStateUpdate.State,
	Plain: plain[20:],
}
encipherStateUpdate, err = cryptoClient.EncryptUpdate(context.Background(), encipherDataUpdate)
if err != nil {
	panic(fmt.Errorf("Failed Encrypt [%s]", err))
}

ciphertext = append(ciphertext, encipherStateUpdate.Ciphered...)
encipherDataFinal := &pb.EncryptFinalRequest{
	State: encipherStateUpdate.State,
}
encipherStateFinal, err := cryptoClient.EncryptFinal(context.Background(), encipherDataFinal)
if err != nil {
	panic(fmt.Errorf("Failed EncryptFinal [%s]", err))
}

ciphertext = append(ciphertext, encipherStateFinal.Ciphered...)
fmt.Println("Encrypted message")

decipherInitInfo := &pb.DecryptInitRequest{
	Mech: &pb.Mechanism{Mechanism: ep11.CKM_AES_CBC_PAD, Parameter: iv},
	Key:  generateKeyStatus.Key, // you may want to store this
}
decipherStateInit, err := cryptoClient.DecryptInit(context.Background(), decipherInitInfo)
if err != nil {
	panic(fmt.Errorf("Failed DecryptInit [%s]", err))
}

decipherDataUpdate := &pb.DecryptUpdateRequest{
	State:    decipherStateInit.State,
	Ciphered: ciphertext[:16],
}
decipherStateUpdate, err := cryptoClient.DecryptUpdate(context.Background(), decipherDataUpdate)
if err != nil {
	panic(fmt.Errorf("Failed DecryptUpdate [%s]", err))
}

plaintext := decipherStateUpdate.Plain[:]
decipherDataUpdate = &pb.DecryptUpdateRequest{
	State:    decipherStateUpdate.State,
	Ciphered: ciphertext[16:],
}
decipherStateUpdate, err = cryptoClient.DecryptUpdate(context.Background(), decipherDataUpdate)
if err != nil {
	panic(fmt.Errorf("Failed DecryptUpdate [%s]", err))
}
plaintext = append(plaintext, decipherStateUpdate.Plain...)

decipherDataFinal := &pb.DecryptFinalRequest{
	State: decipherStateUpdate.State,
}
decipherStateFinal, err := cryptoClient.DecryptFinal(context.Background(), decipherDataFinal)
if err != nil {
	panic(fmt.Errorf("Failed DecryptFinal [%s]", err))
}
plaintext = append(plaintext, decipherStateFinal.Plain...)

if !reflect.DeepEqual(plain, plaintext) {
	panic(fmt.Errorf("Failed comparing plain text of cipher single"))
}

fmt.Printf("Decrypted message\n%s\n", plaintext)
Output:

Generated AES Key
Generated IV
Encrypted message
Decrypted message
Hello, this is a very long and creative message without any imagination
Example (GetMechanismInfo)

Example_getMechanismInfo retrieves a mechanism list and retrieves detailed information for the CKM_RSA_PKCS mechanism Flow: connect, get mechanism list, get mechanism info

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)

mechanismListRequest := &pb.GetMechanismListRequest{}
mechanismListResponse, err := cryptoClient.GetMechanismList(context.Background(), mechanismListRequest)
if err != nil {
	panic(fmt.Errorf("Get mechanism list error: %s", err))
}
fmt.Printf("Got mechanism list:\n%v ...\n", mechanismListResponse.Mechs[:1])

mechanismInfoRequest := &pb.GetMechanismInfoRequest{
	Mech: ep11.CKM_RSA_PKCS,
}
_, err = cryptoClient.GetMechanismInfo(context.Background(), mechanismInfoRequest)
if err != nil {
	panic(fmt.Errorf("Get mechanism info error: %s", err))
}
Output:

Got mechanism list:
[CKM_RSA_PKCS] ...
Example (SignAndVerifyToTestErrorHandling)

Example_signAndVerifyToTestErrorHandling signs some data, modifies the signature and verifies the expected returned error code Flow: connect, generate ECDSA key pair, sign single-part data, modify signature to force verify error,

verify single-part data, ensure proper error is returned
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)

ecParameters, err := asn1.Marshal(util.OIDNamedCurveP256)
if err != nil {
	panic(fmt.Errorf("Unable to encode parameter OID: %s", err))
}

publicKeyECTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_EC_PARAMS, ecParameters),
	util.NewAttribute(ep11.CKA_VERIFY, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
privateKeyECTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_SIGN, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
generateECKeypairRequest := &pb.GenerateKeyPairRequest{
	Mech:            &pb.Mechanism{Mechanism: ep11.CKM_EC_KEY_PAIR_GEN},
	PubKeyTemplate:  publicKeyECTemplate,
	PrivKeyTemplate: privateKeyECTemplate,
}
generateKeyPairStatus, err := cryptoClient.GenerateKeyPair(context.Background(), generateECKeypairRequest)
if err != nil {
	panic(fmt.Errorf("GenerateKeyPair error: %s", err))
}

fmt.Println("Generated ECDSA PKCS key pair")

// Sign data
signInitRequest := &pb.SignInitRequest{
	Mech:    &pb.Mechanism{Mechanism: ep11.CKM_ECDSA},
	PrivKey: generateKeyPairStatus.PrivKey,
}
signInitResponse, err := cryptoClient.SignInit(context.Background(), signInitRequest)
if err != nil {
	panic(fmt.Errorf("SignInit error: %s", err))
}
signData := sha256.New().Sum([]byte("This data needs to be signed"))
signRequest := &pb.SignRequest{
	State: signInitResponse.State,
	Data:  signData,
}
SignResponse, err := cryptoClient.Sign(context.Background(), signRequest)
if err != nil {
	panic(fmt.Errorf("Sign error: %s", err))
}
fmt.Println("Data signed")

// Modify signature to force returned error code
SignResponse.Signature[0] = 255

verifyInitRequest := &pb.VerifyInitRequest{
	Mech:   &pb.Mechanism{Mechanism: ep11.CKM_ECDSA},
	PubKey: generateKeyPairStatus.PubKey,
}
verifyInitResponse, err := cryptoClient.VerifyInit(context.Background(), verifyInitRequest)
if err != nil {
	panic(fmt.Errorf("VerifyInit error: %s", err))
}
verifyRequest := &pb.VerifyRequest{
	State:     verifyInitResponse.State,
	Data:      signData,
	Signature: SignResponse.Signature,
}
_, err = cryptoClient.Verify(context.Background(), verifyRequest)

if ok, ep11Status := util.Convert(err); !ok {
	if ep11Status.Code == ep11.CKR_SIGNATURE_INVALID {
		fmt.Printf("Invalid signature\n")
		return
	}
	panic(fmt.Errorf("Verify error: [%d]: %s", ep11Status.Code, ep11Status.Detail))
}
Output:

Generated ECDSA PKCS key pair
Data signed
Invalid signature
Example (SignAndVerifyUsingECDSAKeyPair)

Example_signAndVerifyUsingECDSAKeyPair generates an ECDSA key pair and uses the key pair to sign and verify data Flow: connect, generate ECDSA key pair, sign single-part data, verify single-part data

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)

ecParameters, err := asn1.Marshal(util.OIDNamedCurveP256)
if err != nil {
	panic(fmt.Errorf("Unable to encode parameter OID: %s", err))
}

publicKeyECTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_EC_PARAMS, ecParameters),
	util.NewAttribute(ep11.CKA_VERIFY, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
privateKeyECTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_SIGN, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
generateECKeypairRequest := &pb.GenerateKeyPairRequest{
	Mech:            &pb.Mechanism{Mechanism: ep11.CKM_EC_KEY_PAIR_GEN},
	PubKeyTemplate:  publicKeyECTemplate,
	PrivKeyTemplate: privateKeyECTemplate,
}
generateKeyPairStatus, err := cryptoClient.GenerateKeyPair(context.Background(), generateECKeypairRequest)
if err != nil {
	panic(fmt.Errorf("GenerateKeyPair error: %s", err))
}

fmt.Println("Generated ECDSA PKCS key pair")

// Sign data
signInitRequest := &pb.SignInitRequest{
	Mech:    &pb.Mechanism{Mechanism: ep11.CKM_ECDSA},
	PrivKey: generateKeyPairStatus.PrivKey,
}
signInitResponse, err := cryptoClient.SignInit(context.Background(), signInitRequest)
if err != nil {
	panic(fmt.Errorf("SignInit error: %s", err))
}
signData := sha256.New().Sum([]byte("This data needs to be signed"))
signRequest := &pb.SignRequest{
	State: signInitResponse.State,
	Data:  signData,
}
SignResponse, err := cryptoClient.Sign(context.Background(), signRequest)
if err != nil {
	panic(fmt.Errorf("Sign error: %s", err))
}
fmt.Println("Data signed")

verifyInitRequest := &pb.VerifyInitRequest{
	Mech:   &pb.Mechanism{Mechanism: ep11.CKM_ECDSA},
	PubKey: generateKeyPairStatus.PubKey,
}
verifyInitResponse, err := cryptoClient.VerifyInit(context.Background(), verifyInitRequest)
if err != nil {
	panic(fmt.Errorf("VerifyInit error: %s", err))
}
verifyRequest := &pb.VerifyRequest{
	State:     verifyInitResponse.State,
	Data:      signData,
	Signature: SignResponse.Signature,
}
_, err = cryptoClient.Verify(context.Background(), verifyRequest)
if ok, ep11Status := util.Convert(err); !ok {
	if ep11Status.Code == ep11.CKR_SIGNATURE_INVALID {
		panic(fmt.Errorf("Invalid signature"))
	} else {
		panic(fmt.Errorf("Verify error: [%d]: %s", ep11Status.Code, ep11Status.Detail))
	}
}
fmt.Println("Verified")
Output:

Generated ECDSA PKCS key pair
Data signed
Verified
Example (SignAndVerifyUsingRSAKeyPair)

Example_signAndVerifyUsingRSAKeyPair signs some data and verifies it Flow: connect, generate RSA key pair, sign single-part data, verify single-part data

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

cryptoClient := pb.NewCryptoClient(conn)

// Generate RSA key pairs
publicExponent := []byte{0x11}
publicKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_ENCRYPT, true),
	util.NewAttribute(ep11.CKA_VERIFY, true), // to verify a signature
	util.NewAttribute(ep11.CKA_MODULUS_BITS, uint64(2048)),
	util.NewAttribute(ep11.CKA_PUBLIC_EXPONENT, publicExponent),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
privateKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_PRIVATE, true),
	util.NewAttribute(ep11.CKA_SENSITIVE, true),
	util.NewAttribute(ep11.CKA_DECRYPT, true),
	util.NewAttribute(ep11.CKA_SIGN, true), // to generate a signature
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
generateKeypairRequest := &pb.GenerateKeyPairRequest{
	Mech:            &pb.Mechanism{Mechanism: ep11.CKM_RSA_PKCS_KEY_PAIR_GEN},
	PubKeyTemplate:  publicKeyTemplate,
	PrivKeyTemplate: privateKeyTemplate,
	PrivKeyId:       uuid.NewV4().String(),
	PubKeyId:        uuid.NewV4().String(),
}
generateKeyPairStatus, err := cryptoClient.GenerateKeyPair(context.Background(), generateKeypairRequest)
if err != nil {
	panic(fmt.Errorf("GenerateKeyPair error: %s", err))
}
fmt.Println("Generated RSA PKCS key pair")

// Sign data
signInitRequest := &pb.SignInitRequest{
	Mech:    &pb.Mechanism{Mechanism: ep11.CKM_SHA1_RSA_PKCS},
	PrivKey: generateKeyPairStatus.PrivKey,
}
signInitResponse, err := cryptoClient.SignInit(context.Background(), signInitRequest)
if err != nil {
	panic(fmt.Errorf("SignInit error: %s", err))
}

signData := sha256.New().Sum([]byte("This data needs to be signed"))
signRequest := &pb.SignRequest{
	State: signInitResponse.State,
	Data:  signData,
}
SignResponse, err := cryptoClient.Sign(context.Background(), signRequest)
if err != nil {
	panic(fmt.Errorf("Sign error: %s", err))
}
fmt.Println("Data signed")

verifyInitRequest := &pb.VerifyInitRequest{
	Mech:   &pb.Mechanism{Mechanism: ep11.CKM_SHA1_RSA_PKCS},
	PubKey: generateKeyPairStatus.PubKey,
}
verifyInitResponse, err := cryptoClient.VerifyInit(context.Background(), verifyInitRequest)
if err != nil {
	panic(fmt.Errorf("VerifyInit error: %s", err))
}
verifyRequest := &pb.VerifyRequest{
	State:     verifyInitResponse.State,
	Data:      signData,
	Signature: SignResponse.Signature,
}
_, err = cryptoClient.Verify(context.Background(), verifyRequest)
if ok, ep11Status := util.Convert(err); !ok {
	if ep11Status.Code == ep11.CKR_SIGNATURE_INVALID {
		panic(fmt.Errorf("Invalid signature"))
	} else {
		panic(fmt.Errorf("Verify error: [%d]: %s", ep11Status.Code, ep11Status.Detail))
	}
}
fmt.Println("Verified")
Output:

Generated RSA PKCS key pair
Data signed
Verified
Example (Tls)

Example_tls tests TLS communication between a client and server using a certificate and private key that are dynamically generated

package main

import (
	"context"
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"fmt"
	"io/ioutil"
	"math/big"
	"net/http"
	"strings"
	"time"

	"github.com/ibm-developer/ibm-cloud-hyperprotectcrypto/golang/ep11"
	pb "github.com/ibm-developer/ibm-cloud-hyperprotectcrypto/golang/grpc"
	"github.com/ibm-developer/ibm-cloud-hyperprotectcrypto/golang/util"
	grpc "google.golang.org/grpc"
)

// generateECDSAKeyPair generates a 256 bit ECDSA key pair
func generateECDSAKeyPair(cryptoClient pb.CryptoClient) ([]byte, []byte, error) {
	ecParameters, err := asn1.Marshal(util.OIDNamedCurveP256)
	if err != nil {
		return nil, nil, fmt.Errorf("Unable to encode parameter OID: %s", err)
	}
	publicKeyECTemplate := util.NewAttributeMap(
		util.NewAttribute(ep11.CKA_EC_PARAMS, ecParameters),
		util.NewAttribute(ep11.CKA_VERIFY, true),
		util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
	)
	privateKeyECTemplate := util.NewAttributeMap(
		util.NewAttribute(ep11.CKA_SIGN, true),
		util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
	)
	generateECKeypairRequest := &pb.GenerateKeyPairRequest{
		Mech:            &pb.Mechanism{Mechanism: ep11.CKM_EC_KEY_PAIR_GEN},
		PubKeyTemplate:  publicKeyECTemplate,
		PrivKeyTemplate: privateKeyECTemplate,
	}
	var ecKeypairResponse *pb.GenerateKeyPairResponse
	ecKeypairResponse, err = cryptoClient.GenerateKeyPair(context.Background(), generateECKeypairRequest)
	if err != nil {
		return nil, nil, fmt.Errorf("Generate ECDSA key pair error: %s", err)
	}
	return ecKeypairResponse.PrivKey, ecKeypairResponse.PubKey, nil
}

func createECDSASelfSignedCert(privKey *util.EP11PrivateKey, commonName string, sigAlg x509.SignatureAlgorithm) ([]byte, error) {
	template := x509.Certificate{
		SerialNumber: big.NewInt(123456789),
		Subject: pkix.Name{
			CommonName: commonName,
		},
		NotBefore: time.Now(),
		NotAfter:  time.Now().Add(time.Hour * 24 * 180),
	}

	certDERBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, privKey.Public(), privKey)
	if err != nil {
		return nil, fmt.Errorf("Failed to create certificate: %s", err)
	}
	return certDERBytes, nil
}

// StartServer starts https server
func CreateServer(listenAddr string) *http.Server {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		w.Write([]byte("Hello"))
	})
	httpServer := &http.Server{
		Addr:    listenAddr,
		Handler: mux,
	}
	return httpServer
}

func newHTTPTestClient(caCertDER []byte) *http.Client {
	x509Cert, err := x509.ParseCertificate(caCertDER)
	if err != nil {
		fmt.Printf("x509.ParseCertificate failed: %s\n", err)
		return nil
	}
	clientCertPool := x509.NewCertPool()
	// Append the client certificates from the CA
	clientCertPool.AddCert(x509Cert)

	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				ServerName: "localhost",
				RootCAs:    clientCertPool,
			},
		},
	}

	return httpClient
}

func ping(client *http.Client, serverAddr string) (string, error) {
	// serverAddr in format of a.b.c.d:port in ipv4 or [::]:port in ipv6
	var serverPort string
	id := strings.LastIndex(serverAddr, ":")
	if id != -1 {
		serverPort = serverAddr[id:]
	} else {
		serverPort = serverAddr
	}
	fullAddr := "https://localhost" + serverPort

	resp, err := client.Get(fullAddr)
	if err != nil {
		return "", fmt.Errorf("Http client get failed: %s", err)
	}
	data, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return "", fmt.Errorf("ioutil.ReadAll failed: %s", err)
	}
	return string(data), nil
}

// Example_tls tests TLS communication between a client and server using a certificate and private key that are dynamically generated
func main() {
	conn, err := grpc.Dial(address, callOpts...)
	if err != nil {
		fmt.Printf("Could not connect to server: %s", err)
		return
	}
	defer conn.Close()
	cryptoClient := pb.NewCryptoClient(conn)
	privKeyBlob, spki, err := generateECDSAKeyPair(cryptoClient)
	if err != nil {
		fmt.Printf("Failed to generate ECDSA key pair: %s", err)
		return
	}

	// Create signer and raw certificate to build up TLS certificate
	priv, err := util.NewEP11Signer(cryptoClient, privKeyBlob, spki)
	if err != nil {
		fmt.Printf("NewEP11Signer error: %s\n", err)
		return
	}
	certDER, err := createECDSASelfSignedCert(priv, "localhost", x509.ECDSAWithSHA256)
	if err != nil {
		fmt.Printf("createECDSASelfSignedCert error: %s\n", err)
		return
	}
	tlsCert := tls.Certificate{
		Certificate: [][]byte{certDER},
		PrivateKey:  priv,
	}

	// Create and start server thread
	tlsCfg := &tls.Config{
		Certificates: []tls.Certificate{tlsCert},
		ClientAuth:   tls.NoClientCert,
	}
	lis, err := tls.Listen("tcp", ":0", tlsCfg)
	if err != nil {
		fmt.Printf("Failed to listen: %s\n", err)
		return
	}
	httpServer := CreateServer(lis.Addr().String())

	defer httpServer.Close()
	go func() {
		httpServer.Serve(lis)
	}()

	// Create TLS client
	client := newHTTPTestClient(certDER)
	strResp, err := ping(client, lis.Addr().String())
	if err != nil {
		fmt.Printf("Ping failed: %s\n", err)
	} else {
		fmt.Printf("Response data from https server: [%s]\n", strResp)
	}

	return

}
Output:

Response data from https server: [Hello]
Example (WrapAndUnwrapKey)

Example_wrapAndUnWrapKey wraps an AES key with a RSA public key and then unwraps it with the private key Flow: connect, generate AES key, generate RSA key pair, wrap/unwrap AES key with RSA key pair

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)

// Generate a AES key
desKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_VALUE_LEN, (uint64)(128/8)),
	util.NewAttribute(ep11.CKA_ENCRYPT, true),
	util.NewAttribute(ep11.CKA_DECRYPT, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, true), // must be true to be wrapped
)
generateKeyRequest := &pb.GenerateKeyRequest{
	Mech:     &pb.Mechanism{Mechanism: ep11.CKM_AES_KEY_GEN},
	Template: desKeyTemplate,
	KeyId:    uuid.NewV4().String(), // optional
}
generateNewKeyStatus, err := cryptoClient.GenerateKey(context.Background(), generateKeyRequest)
if err != nil {
	panic(fmt.Errorf("Generate AES key error: %s", err))
} else {
	fmt.Println("Generated AES key")
}

// Generate RSA key pairs
publicExponent := []byte{0x11}
publicKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_ENCRYPT, true),
	util.NewAttribute(ep11.CKA_WRAP, true), // to wrap a key
	util.NewAttribute(ep11.CKA_MODULUS_BITS, uint64(2048)),
	util.NewAttribute(ep11.CKA_PUBLIC_EXPONENT, publicExponent),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
privateKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_PRIVATE, true),
	util.NewAttribute(ep11.CKA_SENSITIVE, true),
	util.NewAttribute(ep11.CKA_DECRYPT, true),
	util.NewAttribute(ep11.CKA_UNWRAP, true), // to unwrap a key
	util.NewAttribute(ep11.CKA_EXTRACTABLE, false),
)
generateKeypairRequest := &pb.GenerateKeyPairRequest{
	Mech:            &pb.Mechanism{Mechanism: ep11.CKM_RSA_PKCS_KEY_PAIR_GEN},
	PubKeyTemplate:  publicKeyTemplate,
	PrivKeyTemplate: privateKeyTemplate,
	PrivKeyId:       uuid.NewV4().String(),
	PubKeyId:        uuid.NewV4().String(),
}
generateKeyPairStatus, err := cryptoClient.GenerateKeyPair(context.Background(), generateKeypairRequest)
if err != nil {
	panic(fmt.Errorf("GenerateKeyPair error: %s", err))
}
fmt.Println("Generated PKCS key pair")

wrapKeyRequest := &pb.WrapKeyRequest{
	Mech: &pb.Mechanism{Mechanism: ep11.CKM_RSA_PKCS},
	KeK:  generateKeyPairStatus.PubKey,
	Key:  generateNewKeyStatus.Key,
}
wrapKeyResponse, err := cryptoClient.WrapKey(context.Background(), wrapKeyRequest)
if err != nil {
	panic(fmt.Errorf("Wrap AES key error: %s", err))
}
fmt.Println("Wraped AES key")

desUnwrapKeyTemplate := util.NewAttributeMap(
	util.NewAttribute(ep11.CKA_CLASS, ep11.CKO_SECRET_KEY),
	util.NewAttribute(ep11.CKA_KEY_TYPE, ep11.CKK_AES),
	util.NewAttribute(ep11.CKA_VALUE_LEN, (uint64)(128/8)),
	util.NewAttribute(ep11.CKA_ENCRYPT, true),
	util.NewAttribute(ep11.CKA_DECRYPT, true),
	util.NewAttribute(ep11.CKA_EXTRACTABLE, true), // must be true to be wrapped
)
unwrapRequest := &pb.UnwrapKeyRequest{
	Mech:     &pb.Mechanism{Mechanism: ep11.CKM_RSA_PKCS},
	KeK:      generateKeyPairStatus.PrivKey,
	Wrapped:  wrapKeyResponse.Wrapped,
	Template: desUnwrapKeyTemplate,
}
unWrapedResponse, err := cryptoClient.UnwrapKey(context.Background(), unwrapRequest)
if err != nil {
	panic(fmt.Errorf("Unwrap AES key error: %s", err))
}
if !bytes.Equal(generateNewKeyStatus.GetCheckSum()[:3], unWrapedResponse.GetCheckSum()[:3]) {
	panic(fmt.Errorf("Unwrap AES key has a different checksum than the original key"))
} else {
	fmt.Println("Unwraped AES key")
}
Output:

Generated AES key
Generated PKCS key pair
Wraped AES key
Unwraped AES key

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL