diff --git a/.gitignore b/.gitignore index bd53762..15c2965 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +external-signer-pkcs11 +vendor/ # ---> Go # If you prefer the allow list template instead of the deny list, see community template: # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8ba444f --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module git.hatter.ink/external-signer-pkcs11 + +go 1.24.1 + +require github.com/ThalesGroup/crypto11 v1.4.1 + +require ( + github.com/miekg/pkcs11 v1.1.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/thales-e-security/pool v0.0.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..586781e --- /dev/null +++ b/go.sum @@ -0,0 +1,14 @@ +github.com/ThalesGroup/crypto11 v1.4.1 h1:6YR6aVL8LI8akReXKTEgxf+k0+b8wlV8Ra7tZnCG9y4= +github.com/ThalesGroup/crypto11 v1.4.1/go.mod h1:vggvBwlVrqePDrooq/B32dMXlfEsdsFY+6YlSD7VOy0= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= +github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= diff --git a/main.go b/main.go new file mode 100644 index 0000000..baa1788 --- /dev/null +++ b/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "crypto" + "crypto/rand" + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/ThalesGroup/crypto11" +) + +const ( + EnvPkcs11Pin = "PKCS11_PIN" +) + +type Pkcs11Key struct { + Library string `json:"library"` + TokenLabel string `json:"token_label"` + Pin string `json:"pin"` + KeyLabel string `json:"key_label"` +} + +func main() { + parameter := "ewogICJsaWJyYXJ5IjogIi91c3IvbG9jYWwvbGliL2xpYnlrY3MxMS5keWxpYiIsCiAgInRva2VuX2xhYmVsIjogIll1YmlLZXkgUElWICM1MDEwMjIwIiwKICAicGluIjogIiIsCiAgImtleV9sYWJlbCI6ICJQcml2YXRlIGtleSBmb3IgUElWIEF1dGhlbnRpY2F0aW9uIgp9Cg==" + message := "message" + + parameterBytes, err := base64.StdEncoding.DecodeString(parameter) + if err != nil { + println("1", err.Error()) + return + } + var pkcs11Key Pkcs11Key + err = json.Unmarshal(parameterBytes, &pkcs11Key) + if err != nil { + println("2", err.Error()) + return + } + + pin, err := getPin(pkcs11Key.Pin) + if err != nil { + println("3", err.Error()) + return + } + config := &crypto11.Config{ + Path: pkcs11Key.Library, + TokenLabel: pkcs11Key.TokenLabel, + Pin: pin, + } + keyLabel := pkcs11Key.KeyLabel + + ctx, err := crypto11.Configure(config) + if err != nil { + println("4", err.Error()) + return + } + defer ctx.Close() + + privateKey, err := ctx.FindKeyPair(nil, []byte(keyLabel)) + if err != nil { + println("5", err.Error()) + return + } + publicKey := privateKey.Public() + publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + println("6", err.Error()) + return + } + println(base64.StdEncoding.EncodeToString(publicKeyBytes)) + + hashed := sha256.Sum256([]byte(message)) + signature, err := privateKey.Sign(rand.Reader, hashed[:], crypto.SHA256) + if err != nil { + println("7", err.Error()) + return + } + fmt.Printf("%x\n", signature) +} + +func getPin(pin string) (string, error) { + if pin != "" { + return pin, nil + } + envPin := os.Getenv(EnvPkcs11Pin) + if envPin != "" { + return envPin, nil + } + return "", errors.New("PIN is not set, set PIN: " + EnvPkcs11Pin) +}