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