pkcssigner

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2025 License: Apache-2.0 Imports: 7 Imported by: 0

README

crypto.Signer for PKCS11

where private keys as embedded inside PKCS-11 device

Basically, you will get a crypto.Signer interface for the private key. Use the signer to create a TLS session, sign CA/CSRs, or just sign anything.

Note, pkcs11 crypto.signers are a dime a dozen (eg. at ThalesGroup/crypto11, and many more)

the difference with this library is that it also surfaces a way to directly establish TLS using PKCS11 based keys

  func (t PKCS) TLSCertificate() (tls.Certificate, error) {

NOTE: this repo is NOT supported by Google


For pure TPM signer, review

crypto.Signer, implementations for Trusted Platform Modules


Usage Signer

Initialize a signer and directly use .sign() as shown in this below and in the samples

require (
	github.com/salrashid123/tpmsigner v0.0.1
)

then

import (
	"github.com/salrashid123/pkcsigner"
	"github.com/ThalesGroup/crypto11"  
)

	config := &crypto11.Config{
		Path:       "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so",
		TokenLabel: "token1",
		Pin:        "mynewpin",
	}

	stringToSign := []byte("foo")

	h := sha256.New()
	h.Write(b)
	digest := h.Sum(nil)

	ctx, err := crypto11.Configure(config)
	if err != nil {
		log.Fatal(err)
	}

	defer ctx.Close()

	r, err := pkcssigner.NewPKCSCrypto(&pkcssigner.PKCS{
		Context:   ctx,
		PkcsId:    nil, 
		PkcsLabel: []byte("keylabel1"),
	})

	s, err := r.Sign(rand.Reader, digest, crypto.SHA256)

	fmt.Printf("RSA Signed String: %s\n", base64.StdEncoding.EncodeToString(s))

Install PKCS11 support and Verify with OpenSSL

The following will install and test softHSM using openssl. Once this is done, we will use the golang mTLS clients to establish client-server communication.

First install openssl with its PKCS11 engine.

On debian

apt-get update && apt-get install libtpm2-pkcs11-1 \
     tpm2-tools pkcs11-provider opensc softhsm2 libsofthsm2 libengine-pkcs11-openssl -y


$ openssl engine -t -c pkcs11
(pkcs11) pkcs11 engine
     [ available ]

$ openssl engine dynamic \
 -pre SO_PATH:/usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so \
 -pre ID:pkcs11 -pre LIST_ADD:1 \
 -pre LOAD \
 -pre MODULE_PATH:/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \
 -t -c

  (dynamic) Dynamic engine loading support
  [Success]: SO_PATH:/usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so
  [Success]: ID:pkcs11
  [Success]: LIST_ADD:1
  [Success]: LOAD
  [Success]: MODULE_PATH:/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so
  Loaded: (pkcs11) pkcs11 engine
  [RSA, rsaEncryption, id-ecPublicKey]
      [ available ]

## TODO: use providers
# $ openssl list  -provider pkcs11  -provider default  --providers
# Providers:
#   default
#     name: OpenSSL Default Provider
#     version: 3.5.0
#     status: active
#   pkcs11
#     name: PKCS#11 Provider
#     version: 3.5.0
#     status: active
SOFTHSM

SoftHSM is as the name suggests, a sofware "HSM" module used for testing. It is ofcourse not hardware backed but the module does allow for a PKCS11 interface which we will also use for testing.

First make sure the softhsm library is installed

Setup a config file where the directories.tokendir points to a existing folder where softHSM will save all its data (in this case its misc/tokens/)

This repo already contains a sample configuration/certs to use with the softhsm token directory...just delete the folder and start from scratch if you want..

Use pkcs11-too which comes with the installation of opensc

# export OPENSSL_CONF=`pwd`/example/openssl.cnf
export PKCS11_PROVIDER_MODULE=/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so
export SOFTHSM2_CONF=`pwd`/example/softhsm.conf
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/ 

rm -rf /tmp/tokens
mkdir /tmp/tokens

pkcs11-tool --module $PKCS11_PROVIDER_MODULE  --slot-index=0 --init-token --label="token1" --so-pin="123456"
pkcs11-tool --module $PKCS11_PROVIDER_MODULE  --label="token1" --init-pin --so-pin "123456" --pin mynewpin

pkcs11-tool --module $PKCS11_PROVIDER_MODULE --list-token-slots
pkcs11-tool --module $PKCS11_PROVIDER_MODULE -l -k --key-type rsa:2048 --id=1 --label keylabel1 --pin mynewpin 
pkcs11-tool --module $PKCS11_PROVIDER_MODULE -l -k --key-type ec:prime256v1 --id 2 --label keylabel2 --pin mynewpin

pkcs11-tool --module $PKCS11_PROVIDER_MODULE  --list-objects

## important: set the serial_num you get after you ran --list-token-slots above
export serial_number="3cb32116793a2272"

export PKCS11_RSA_PRIVATE_KEY="pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;id=%01;serial=$serial_number;token=token1;type=private;object=keylabel1?pin-value=mynewpin"
export PKCS11_RSA_PUBLIC_KEY="pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;id=%01;serial=$serial_number;token=token1;type=public;object=keylabel1?pin-value=mynewpin"

### TODO: using provider https://github.com/latchset/pkcs11-provider/issues/634
# export PKCS11_PROVIDER_DEBUG=file:/tmp/p11prov-debug.log,level=5
# openssl pkey -provider pkcs11 -provider default -in "$PKCS11_RSA_PUBLIC_KEY" -pubout
# openssl pkey -provider pkcs11 -provider default  -in "$PKCS11_RSA_PRIVATE_KEY" -pubout

### using engine, create a key 
openssl pkey -engine pkcs11  -inform engine -in "$PKCS11_RSA_PUBLIC_KEY" -pubout  -out /tmp/pub.pem

## optionally create a csr and load it to the device
openssl req  -engine pkcs11 --keyform engine -new -key "$PKCS11_RSA_PRIVATE_KEY" -subj "/CN=my_key" -out /tmp/server.csr
openssl x509  -engine pkcs11 --keyform engine -req -days 365 -in /tmp/server.csr -signkey "$PKCS11_RSA_PRIVATE_KEY" -out /tmp/server.crt
openssl x509 -outform DER -in  /tmp/server.crt -out  /tmp/server.der
pkcs11-tool  --module $PKCS11_PROVIDER_MODULE --pin mynewpin --write-object /tmp/server.der --type cert --id 1 --label keylabel1 

## you can now see the public items:
pkcs11-tool --module $PKCS11_PROVIDER_MODULE  --list-objects

## now sign some data
echo "sig data" > /tmp/data.txt
openssl rsa -engine pkcs11  -inform engine -in "$PKCS11_RSA_PUBLIC_KEY" -pubout -out /tmp/pub.pem
openssl pkeyutl -engine pkcs11 -keyform engine  -inkey $PKCS11_RSA_PRIVATE_KEY -sign -in /tmp/data.txt -out /tmp/data.sig
openssl pkeyutl -pubin -inkey /tmp/pub.pem -verify -in /tmp/data.txt -sigfile /tmp/data.sig

then run the examples:

cd example/

go run rsa/main.go

## for ecc
go run ecc/main.go

References

  • OpenSSL Provider

    • /usr/lib/x86_64-linux-gnu/engines-1.1/libpkcs11.so: OpenSSL Engine that allows dynamic PKCS11 providers
  • PKCS11 Modules

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type PKCS

type PKCS struct {
	X509Certificate *x509.Certificate // public x509 certificate for the signer

	PkcsId    []byte
	PkcsLabel []byte
	Context   *crypto11.Context

	ECCRawOutput bool // for ECC keys, output raw signatures. If false, signature is ans1 formatted
	// contains filtered or unexported fields
}

func NewPKCSCrypto

func NewPKCSCrypto(conf *PKCS) (PKCS, error)

func (PKCS) Public

func (t PKCS) Public() crypto.PublicKey

func (PKCS) Sign

func (t PKCS) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)

func (PKCS) TLSCertificate

func (t PKCS) TLSCertificate() (tls.Certificate, error)

Jump to

Keyboard shortcuts

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