package main
import (
"bytes"
"crypto/sha256"
"crypto/rand"
"encoding/base64"
"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()
// Create DES3 key
// first lookup the key
buf := new(bytes.Buffer)
var num uint16 = 1
err = binary.Write(buf, binary.LittleEndian, num)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
id := buf.Bytes()
desKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_DES3),
pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), // we don't
need to extract this..
pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "DESKey"), /*
Name of Key */
}
desKey, err := p.GenerateKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_KEY_GEN , nil)},
desKeyTemplate)
if err != nil {
panic(fmt.Sprintf("GenerateKey() failed %s\n", err))
}
log.Printf("Created DES3 Key: %v", desKey)
ktemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_ID, id),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "DESKey"),
}
if err := p.FindObjectsInit(session, ktemplate); err != nil {
panic(err)
}
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_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_WRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, 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), /* KeyLength */
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "AESKeyToWrap"), /*
Name of Key */
}
aesKey, err := p.GenerateKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_KEY_GEN
, nil)},
aesKeyTemplate)
if err != nil {
panic(fmt.Sprintf("GenerateKey() failed %s\n", err))
}
log.Printf("Created AES Key: %v", aesKey)
// Wrapping
wrappedPrivBytes, err := p.WrapKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC, nil)}, desKey,
aesKey)
buf = new(bytes.Buffer)
num = 6
err = binary.Write(buf, binary.LittleEndian, num)
if err != nil {
log.Fatalf("binary.Write failed: %v", err)
}
importedPrivID := buf.Bytes()
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_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "UnwrappedDES3Key"), /*
Name of Key */
pkcs11.NewAttribute(pkcs11.CKA_ID, importedPrivID),
}
// Unwrapping
ik, err := p.UnwrapKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC, nil)}, desKey,
wrappedPrivBytes, aesKeyTemplate)
_ = ik
if err != nil {
log.Fatalf("Unwrap Failed: %v", err)
}
if err != nil {
log.Fatalf("failed to wrap privatekey : %s\n", err)
}
if err != nil {
panic(err)
}
if err = p.FindObjectsFinal(session); err != nil {
panic(err)
}
iv := make([]byte, 8)
_, err = rand.Read(iv)
if err != nil {
panic(err)
}
// Encryption
err = p.EncryptInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC, iv)}, desKey )
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))
}
// append the IV to the ciphertext
cdWithIV := append(iv, ct...)
log.Printf("Encrypted IV+Ciphertext %s",
base64.RawStdEncoding.EncodeToString(cdWithIV))
// Decryption
err = p.DecryptInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC, cdWithIV[0:8])},
desKey)
if err != nil {
panic(fmt.Sprintf("EncryptInit() failed %s\n", err))
}
pt, err := p.Decrypt(session, ct[:8])
if err != nil {
panic(fmt.Sprintf("Encrypt() failed %s\n", err))
}
log.Printf("Decrypt %s", string(pt))
// Signing
msg := []byte("foo")
digest := sha256.Sum256(msg)
log.Printf("Decrypt %s", string(pt))
err = p.SignInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC, nil)}, desKey)
sig, err := p.Sign(session, msg)
// Verification
err = p.VerifyInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC, nil)}, desKey)
err = p.Verify(session, digest[:], sig)
}