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