package main
import (
"bytes"
"encoding/base64"
"crypto/sha256"
"encoding/binary"
"fmt"
"log"
"github.com/miekg/pkcs11"
)
const (
pin = "87654321"
)
var ()
func main() {
// Init PKCS11
p := pkcs11.New("/opt/utimaco/lib/libcs_pkcs11_R3.so")
err := p.Initialize()
if err != nil {
panic(err)
}
defer p.Destroy()
defer p.Finalize()
slots, err := p.GetSlotList(true)
if err != nil {
panic(err)
}
session, err := p.OpenSession(slots[0],
pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
if err != nil {
panic(err)
}
defer p.CloseSession(session)
err = p.Login(session, pkcs11.CKU_USER, pin)
if err != nil {
panic(err)
}
defer p.Logout(session)
info, err := p.GetInfo()
if err != nil {
panic(err)
}
fmt.Printf("CryptokiVersion.Major %v", info.CryptokiVersion.Major)
fmt.Println()
buf := new(bytes.Buffer)
buf = new(bytes.Buffer)
var num uint16 = 1
num = 1
err = binary.Write(buf, binary.LittleEndian, num)
if err != nil {
log.Fatalf("binary.Write failed: %v", err)
}
pubID := buf.Bytes()
buf = new(bytes.Buffer)
num = 2
err = binary.Write(buf, binary.LittleEndian, num)
if err != nil {
log.Fatalf("binary.Write failed: %v", err)
}
privID := buf.Bytes()
publicKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_RSA),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_WRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, 2048),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "pub1"),
pkcs11.NewAttribute(pkcs11.CKA_ID, pubID),
}
privateKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_RSA),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "priv1"),
pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
pkcs11.NewAttribute(pkcs11.CKA_WRAP_WITH_TRUSTED, false),
pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true),
pkcs11.NewAttribute(pkcs11.CKA_ID, privID),
}
pbk, pvk, err := p.GenerateKeyPair(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_KEY_PAIR_GEN,
nil)},
publicKeyTemplate, privateKeyTemplate)
var (
// OAEPLabel defines the label we use for OAEP encryption; this cannot
be changed
OAEPLabel = []byte("")
// OAEPSha256Params describes the OAEP parameters with sha256 hash
algorithm
OAEPSha256Params = &pkcs11.OAEPParams{
HashAlg: pkcs11.CKM_SHA256,
MGF: pkcs11.CKG_MGF1_SHA256,
SourceType: pkcs11.CKZ_DATA_SPECIFIED,
SourceData: OAEPLabel,
}
)
// Encryption
err = p.EncryptInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP,
OAEPSha256Params)}, pbk )
if err != nil {
panic(fmt.Sprintf("EncryptInit() failed %s\n", err))
}
ct, err := p.Encrypt(session, []byte("fooooooo"))
if err != nil {
panic(fmt.Sprintf("Encrypt() failed %s\n", err))
}
// Decryption
err = p.DecryptInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP,
OAEPSha256Params)}, pvk)
plaintext, err := p.Decrypt(session, ct)
_ = plaintext
_ = err
// Signing
msg := []byte("foo")
fmt.Printf("Signing %d bytes with %s\n", len(msg), msg)
err = p.SignInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA256_RSA_PKCS, nil)},
pvk)
if err != nil {
log.Fatalf("Signing Initiation failed (%s)\n", err.Error())
}
sig, err := p.Sign(session, msg)
if err != nil {
err = fmt.Errorf("Signing failed (%s)\n", err.Error())
return
}
log.Printf("Signature %s", base64.RawStdEncoding.EncodeToString(sig))
// Verification
digest := sha256.Sum256(msg)
err = p.VerifyInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA256_RSA_PKCS, nil)},
pbk)
err = p.Verify(session, digest[:], sig)
log.Printf(">>>>>> Signature Verified")
id := buf.Bytes()
//Create AES key which is enabled for wrapping
aesKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_AES),
pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_WRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_VERIFY, false),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), // we don't
need to extract this..
pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
pkcs11.NewAttribute(pkcs11.CKA_VALUE_LEN, 32),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "WrappingAESKey"), /*
Name of Key */
pkcs11.NewAttribute(pkcs11.CKA_ID, id),
}
importedPrivID := buf.Bytes()
aesKeyTemplate2 := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_AES),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "UnwrappedAESKey"), /*
Name of Key */
pkcs11.NewAttribute(pkcs11.CKA_ID, importedPrivID),
}
aesKey, err := p.GenerateKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_KEY_GEN
, nil)},
aesKeyTemplate)
log.Printf("Created AES Key: %v", aesKey)
{
// Wrapping
wrappedPrivBytes, err := p.WrapKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}, pbk,
aesKey)
// Unwrapping
ik, err := p.UnwrapKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}, pvk,
wrappedPrivBytes, aesKeyTemplate2)
_ = ik
_ = err
}
}