{"id":21354912,"url":"https://github.com/salrashid123/signer","last_synced_at":"2025-07-12T22:32:24.120Z","repository":{"id":57633893,"uuid":"222620457","full_name":"salrashid123/signer","owner":"salrashid123","description":"golang crypto.Signer for Trusted Platform Module (TPM) and Google Cloud KMS","archived":false,"fork":false,"pushed_at":"2024-06-17T11:19:03.000Z","size":348,"stargazers_count":26,"open_issues_count":2,"forks_count":10,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-06-19T12:12:35.487Z","etag":null,"topics":["golang","hardware-security-module","hashicorp-vault","key-management-service","kms","trusted-platform-module"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-19T06:03:01.000Z","updated_at":"2024-06-17T14:31:06.000Z","dependencies_parsed_at":"2024-06-14T13:38:27.032Z","dependency_job_id":"5a470215-9c75-4686-8b33-34a150d5c092","html_url":"https://github.com/salrashid123/signer","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsigner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsigner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsigner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsigner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/signer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225839601,"owners_count":17532308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","hardware-security-module","hashicorp-vault","key-management-service","kms","trusted-platform-module"],"created_at":"2024-11-22T04:15:19.085Z","updated_at":"2025-07-12T22:32:24.109Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"#### crypto.Signer, implementations for Trusted Platform Modules\n\nwhere private keys as embedded inside `Trusted Platform Module (TPM)`\n\nBasically, you will get a [crypto.Signer](https://pkg.go.dev/crypto#Signer) interface for the private key. \n\nUse the signer to create a TLS session, sign CA/CSRs, or just sign anything.\n\nFor example, you can use this to sign data or to generate certificates/csr or for mTLS.\n\n- `util/certgen/`:  Library that generates a self-signed x509 certificate for the KMS and TPM based signers above\n- `util/csrgen/`:  Library that generates a CSR using the key in KMS or TPM \n\nsee the [example/](example/) folder for more information.\n\n---\n\n\u003e\u003e this library is not supported by google\n\n---\n\n### Usage Signer\n\nInitialize a signer and directly use `.sign()` as shown in this below and in the samples\n\n```golang\nimport (\n\tsaltpm \"github.com/salrashid123/signer/tpm\"\n\t\"github.com/google/go-tpm/tpmutil\"\n)\n\n\trwc, err := tpmutil.OpenTPM(path)\n\n\tstringToSign := []byte(\"foo\")\n\n\th := sha256.New()\n\th.Write(b)\n\tdigest := h.Sum(nil)\n\n\t// assume the handle to the rsassa key is persistentHandle 0x81008001\n\tr, err := saltpm.NewTPMCrypto(\u0026saltpm.TPM{\n\t\tTpmDevice: rwc,\n\t\tHandle:    tpm2.TPMHandle(handle),\n\t})\n\n\ts, err := r.Sign(rand.Reader, digest, crypto.SHA256)\n\n\tfmt.Printf(\"RSA Signed String: %s\\n\", base64.StdEncoding.EncodeToString(s))\n```\n\n* [https://pkg.go.dev/github.com/salrashid123/signer/tpm](https://pkg.go.dev/github.com/salrashid123/signer/tpm)\n\n---\n\n### Sign/Verify\n\nsee `example/sign_verify_tpm` folder.\n\nTo use this, the key must be first created on the TPM and accessed as a PersistentHandle or TPM PEM file\n\nYou can create these keys using `go-tpm` or using  `tpm2_tools`.  The example below uses tpm2_tools but for others languages and standalone applicatoins, see [openssl tpm2 provider](https://github.com/salrashid123/tpm2?tab=readme-ov-file#tpm-based-private-key) or [tpm2genkey](https://github.com/salrashid123/tpm2genkey)\n\nFor this, install latest [tpm2_tools](https://tpm2-tools.readthedocs.io/en/latest/INSTALL/) \n\n```bash\ncd example/\n\n## if you want to use a software TPM, \n# rm -rf /tmp/myvtpm \u0026\u0026 mkdir /tmp/myvtpm\n# swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear\n\n## then specify \"127.0.0.1:2321\"  as the TPM device path in the examples\n## and for tpm2_tools, export the following var\n# export TPM2TOOLS_TCTI=\"swtpm:port=2321\"\n\n## if you are using a real tpm set --tpm-path=/dev/tpmrm0\n\n## note the primary can be the \"H2\" profile from https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html#name-parent\n# printf '\\x00\\x00' \u003e unique.dat\n# tpm2_createprimary -C o -G ecc  -g sha256  -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\n## RSA - no password\n\n\ttpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'\n\ttpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx\n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n\ttpm2_evictcontrol -C o -c key.ctx 0x81008001\n\ngo run sign_verify_tpm/rsassa/main.go --tpm-path=\"127.0.0.1:2321\" --handle 0x81008001\n\n\n### RSA - no password with PEM key file\n\n\tprintf '\\x00\\x00' \u003e unique.dat\n\ttpm2_createprimary -C o -G ecc  -g sha256  -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\n\ttpm2_create -G rsa2048:rsapss:null -g sha256 -u key.pub -r key.priv -C primary.ctx  --format=pem --output=rsapss_public.pem\n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n\ttpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o key.pem\n\ngo run sign_verify_tpm/keyfile/main.go --tpm-path=\"127.0.0.1:2321\" -pemFile /tmp/key.pem\n\n## rsa-pss\n\n\ttpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'\n\ttpm2_create -G rsa2048:rsapss:null -g sha256 -u key.pub -r key.priv -C primary.ctx\n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n\ttpm2_evictcontrol -C o -c key.ctx 0x81008004\n\ngo run sign_verify_tpm/rsapss/main.go --tpm-path=\"127.0.0.1:2321\" --handle 0x81008004\n\n## ecc\n\n\ttpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'\n\ttpm2_create -G ecc:ecdsa  -g sha256  -u key.pub -r key.priv -C primary.ctx  --format=pem --output=ecc_public.pem\n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n\ttpm2_evictcontrol -C o -c key.ctx 0x81008005    \n\ngo run sign_verify_tpm/ecc/main.go --tpm-path=\"127.0.0.1:2321\" --handle 0x81008005\n\n## for policyPCR\n\n\ttpm2_pcrread sha256:23\n\ttpm2_startauthsession -S session.dat\n\ttpm2_policypcr -S session.dat -l sha256:23  -L policy.dat\n\ttpm2_flushcontext session.dat\n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256  -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'\n\ttpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx  -L policy.dat\n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n\ttpm2_evictcontrol -C o -c key.ctx 0x81008006\n\ngo run sign_verify_tpm/policy_pcr/main.go --handle=0x81008006 --tpm-path=\"127.0.0.1:2321\"\n\n## for policyPassword\n\n\ttpm2_createprimary -C o  -G rsa2048:aes128cfb -g sha256  -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'\n\ttpm2_create -G rsa2048:rsassa:null -p testpwd -g sha256 -u key.pub -r key.priv -C primary.ctx \n\ttpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ttpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx \n\ttpm2_evictcontrol -C o -c key.ctx 0x81008007\n\ngo run sign_verify_tpm/policy_password/main.go --handle=0x81008007 --tpm-path=\"127.0.0.1:2321\"\n\n```\n\n\n### Usage TLS\n\n* for tpm see [mTLS with TPM bound private key](https://github.com/salrashid123/go_tpm_https_embed)\n\n### Sign/Verify ECC\n\nThe default output signature format for ECC based keys is ASN1 format as described in [ecdsa.SignASN1](https://pkg.go.dev/crypto/ecdsa#Sign)\n\nIf you need the raw output format, set `ECCRawOutput:  true` in the config.\n\nSee the examples folder for usage\n\n### Usage: Generate CSR\n\nThe following will generate a TPM based key and then issue a CSR against it.\n\n```bash\n### create key, rsassa\n # using H2 template ( https://gist.github.com/salrashid123/9822b151ebb66f4083c5f71fd4cdbe40 )\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n   -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n   \n tpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx\n tpm2_flushcontext -t\n tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n tpm2_evictcontrol -C o -c key.ctx 0x81008001\n tpm2_flushcontext -t\n tpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o private.pem\n\ncd util/csrgen/\ngo run csrgen/csrgen.go -cn server.domain.com  --persistentHandle 0x81008001\n```\n\n### Usage: Generate self-signed certificate\n\nThe following will generate a key on the tpm, then use that RSA key to issue a CSR and then sign that CSR with by itself to get an x509.\n\nYou can ofcourse modify it to just sign any csr with a TPM backed key\n\n\n```bash\n # using H2 template ( https://gist.github.com/salrashid123/9822b151ebb66f4083c5f71fd4cdbe40 )\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n   -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\n tpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx\n tpm2_flushcontext -t\n tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx\n tpm2_evictcontrol -C o -c key.ctx 0x81008002\n tpm2_flushcontext -t\n tpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o private.pem\n\ngo run certgen/certgen.go -cn server.domain.com --persistentHandle 0x81008002\n```\n\n---\n\nIf you just want to issue JWT's, see\n\n* [https://github.com/salrashid123/golang-jwt-tpm](https://github.com/salrashid123/golang-jwt-tpm)\n* [https://github.com/salrashid123/golang-jwt-pkcs11](https://github.com/salrashid123/golang-jwt-pkcs11)\n\nor real random:\n\n* [TPM backed crypto/rand Reader](https://github.com/salrashid123/tpmrand)\n\n---\n\n#### Keys with Auth Policy\n\nIf the key is setup with an AuthPolicy (eg, a policy that requires a passphrase or a predefined PCR values to exist), you can specify those in code or define your own\n\n\n##### PasswordPolicy\n\nIf the key requires a password, initialize a `NewPasswordSession`\n\n```golang\n\tse, err := saltpm.NewPasswordSession(rwr, []byte(*keyPass))\n\n\trr, err := saltpm.NewTPMCrypto(\u0026saltpm.TPM{\n\t\tTpmDevice:   rwc,\n\t\tHandle:      tpm2.TPMHandle(*handle),\n\t\tAuthSession: se,\n\t})\n```\n\n##### PCRPolicy\n\nIf the key requires a password, initialize a `NewPCRSession`\n\n```golang\n\tse, err := saltpm.NewPCRSession(rwr, []tpm2.TPMSPCRSelection{\n\t\t{\n\t\t\tHash:      tpm2.TPMAlgSHA256,\n\t\t\tPCRSelect: tpm2.PCClientCompatible.PCRs(uint(*pcr)),\n\t\t},\n\t})\n\n\trr, err := saltpm.NewTPMCrypto(\u0026saltpm.TPM{\n\t\tTpmDevice:   rwc,\n\t\tHandle:      tpm2.TPMHandle(*handle),\n\t\tAuthSession: se,\n\t})\n\n```\n\n##### CustomPolicy\n\nNote, you can define your own policy for import too...just implement the \"session\" interface from the signer:\n\n```golang\ntype Session interface {\n\tGetSession() (auth tpm2.Session, closer func() error, err error) // this supplies the session handle to the library\n}\n```\n\nfor example, for a PCR and [AuthPolicy](https://github.com/google/go-tpm/pull/359) enforcement (eg, a PCR and password), you can define a custom session callback.\n\n```golang\ntype MyPCRAndPolicyAuthValueSession struct {\n\trwr      transport.TPM\n\tsel      []tpm2.TPMSPCRSelection\n\tpassword []byte\n}\n\nfunc NewPCRAndPolicyAuthValueSession(rwr transport.TPM, sel []tpm2.TPMSPCRSelection, password []byte) (MyPCRAndPolicyAuthValueSession, error) {\n\treturn MyPCRAndPolicyAuthValueSession{rwr, sel, password}, nil\n}\n\nfunc (p MyPCRAndPolicyAuthValueSession) GetSession() (auth tpm2.Session, closer func() error, err error) {\n\n\tvar options []tpm2.AuthOption\n\toptions = append(options, tpm2.Auth(p.password))\n\n\tsess, closer, err := tpm2.PolicySession(p.rwr, tpm2.TPMAlgSHA256, 16, options...)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t_, err = tpm2.PolicyPCR{\n\t\tPolicySession: sess.Handle(),\n\t\tPcrs: tpm2.TPMLPCRSelection{\n\t\t\tPCRSelections: p.sel,\n\t\t},\n\t}.Execute(p.rwr)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t_, err = tpm2.PolicyAuthValue{\n\t\tPolicySession: sess.Handle(),\n\t}.Execute(p.rwr)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn sess, closer, nil\n}\n\n```\n\nwhich you can call as:\n\n```golang\n\tse, err := NewPCRAndPolicyAuthValueSession(rwr, []tpm2.TPMSPCRSelection{\n\t\t{\n\t\t\tHash:      tpm2.TPMAlgSHA256,\n\t\t\tPCRSelect: tpm2.PCClientCompatible.PCRs(uint(*pcr)),\n\t\t},\n\t}, []byte(\"testpswd\"))\n\n\trr, err := saltpm.NewTPMCrypto(\u0026saltpm.TPM{\n\t\tTpmDevice: rwc,\n\t\tHandle:    tpm2.TPMHandle(*handle*),\n\t\tAuthSession: se,\n\t})\n```\n\n---\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fsigner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fsigner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fsigner/lists"}