{"id":37146873,"url":"https://github.com/jtaylorcpp/piv-go","last_synced_at":"2026-01-14T17:05:36.846Z","repository":{"id":57524551,"uuid":"254936307","full_name":"jtaylorcpp/piv-go","owner":"jtaylorcpp","description":"Keys and certificates for YubiKeys","archived":false,"fork":true,"pushed_at":"2020-04-11T20:59:21.000Z","size":136,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2023-08-09T01:14:13.351Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"go-piv/piv-go","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jtaylorcpp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-11T19:05:41.000Z","updated_at":"2020-04-16T03:36:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jtaylorcpp/piv-go","commit_stats":null,"previous_names":[],"tags_count":5,"template":null,"template_full_name":null,"purl":"pkg:github/jtaylorcpp/piv-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtaylorcpp%2Fpiv-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtaylorcpp%2Fpiv-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtaylorcpp%2Fpiv-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtaylorcpp%2Fpiv-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jtaylorcpp","download_url":"https://codeload.github.com/jtaylorcpp/piv-go/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtaylorcpp%2Fpiv-go/sbom","scorecard":{"id":539880,"data":{"date":"2025-08-11","repo":{"name":"github.com/jtaylorcpp/piv-go","commit":"797173c6683a5e72d0d40d44e7dd8abfe4db1eff"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/jtaylorcpp/piv-go/test.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/jtaylorcpp/piv-go/test.yaml/master?enable=pin","Warn: goCommand not pinned by hash: .github/workflows/test.yaml:21","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T07:57:06.300Z","repository_id":57524551,"created_at":"2025-08-20T07:57:06.300Z","updated_at":"2025-08-20T07:57:06.300Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28427192,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T16:38:47.836Z","status":"ssl_error","status_checked_at":"2026-01-14T16:34:59.695Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-01-14T17:05:36.118Z","updated_at":"2026-01-14T17:05:36.839Z","avatar_url":"https://github.com/jtaylorcpp.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"This is not an officially supported Google product\n\n# A pure Go YubiKey PIV implementation\n\n[![GoDoc](https://godoc.org/github.com/ericchiang/piv-go/piv?status.svg)](https://godoc.org/github.com/ericchiang/piv-go/piv)\n\nYubiKeys implement the PIV specification for managing smart card certificates.\nThis applet is a simpler alternative to GPG for managing asymmetric keys on a\nYubiKey.\n\nThis package is an alternative to Paul Tagliamonte's [go-ykpiv](https://github.com/paultag/go-ykpiv),\na wrapper for YubiKey's ykpiv.h C library. This package aims to provide:\n\n* Better error messages\n* Idiomatic Go APIs\n* Modern features such as PIN protected management keys\n\n## Examples\n\n* [Signing](#signing)\n* [PINs](#pins)\n* [Certificates](#certificates)\n* [Attestation](#attestation)\n\n### Signing\n\nThe piv-go package can be used to generate keys and store certificates on a\nYubiKey. This uses a management key to generate new keys on the applet, and a\nPIN for signing operations. The package provides default PIN values. If the PIV\ncredentials on the YubiKey haven't been modified, the follow code generates a\nnew EC key on the smartcard, and provides a signing interface:\n\n```go\n// List all smartcards connected to the system.\ncards, err := piv.Cards()\nif err != nil {\n\t// ...\n}\n\n// Find a YubiKey and open the reader.\nvar yk *piv.YubiKey\nfor _, card := range cards {\n\tif strings.Contains(strings.ToLower(card), \"yubikey\") {\n\t\tif yk, err = piv.Open(card); err != nil {\n\t\t\t// ...\n\t\t}\n\t\tbreak\n\t}\n}\nif yk == nil {\n\t// ...\n}\n\n// Generate a private key on the YubiKey.\nkey := piv.Key{\n\tAlgorithm:   piv.AlgorithmEC256,\n\tPINPolicy:   piv.PINPolicyAlways,\n\tTouchPolicy: piv.TouchPolicyAlways,\n}\npub, err := yk.GenerateKey(piv.DefaultManagementKey, piv.SlotAuthentication, key)\nif err != nil {\n\t// ...\n}\n\nauth := piv.KeyAuth{PIN: piv.DefaultPIN}\npriv, err := yk.PrivateKey(piv.SlotAuthentication, pub, auth)\nif err != nil {\n\t// ...\n}\n// Use private key to sign or decrypt.\n```\n\n### PINs\n\nThe PIV applet has three unique credentials:\n\n* Management key (3DES key) used to generate new keys on the YubiKey.\n* PIN (up to 8 digits, usually 6) used to access signing operations.\n* PUK (up to 8 digits) used to unblock the PIN. Usually set once and thrown\n  away or managed by an administrator.\n\npiv-go implements PIN protected management keys to store the management key on\nthe YubiKey. This allows users to only provide a PIN and still access management\ncapabilities.\n\nThe following code generates new, random credentials for a YubiKey:\n\n```go\nnewPINInt, err := rand.Int(rand.Reader, bit.NewInt(1_000_000))\nif err != nil {\n\t// ...\n}\nnewPUKInt, err := rand.Int(rand.Reader, bit.NewInt(100_000_000))\nif err != nil {\n\t// ...\n}\nvar newKey [24]byte\nif _, err := io.ReadFull(rand.Reader, newKey[:]); err != nil {\n\t// ...\n}\n// Format with leading zeros.\nnewPIN := fmt.Sprintf(\"%06d\", newPINInt)\nnewPUK := fmt.Sprintf(\"%08d\", newPUKInt)\n\n// Set all values to a new value.\nif err := yk.SetManagementKey(piv.DefaultManagementKey, newKey); err != nil {\n\t// ...\n}\nif err := yk.SetPIN(piv.DefaultPUK, newPUK); err != nil {\n\t// ...\n}\nif err := yk.SetPIN(piv.DefaultPIN, newPIN); err != nil {\n\t// ...\n}\n// Store management key on the YubiKey.\nm := piv.Metadata{ManagementKey: \u0026newKey}\nif err := yk.SetMetadata(newKey, m); err != nil {\n\t// ...\n}\n\nfmt.Println(\"Credentials set. Your PIN is: %s\", newPIN)\n```\n\nThe user can user the PIN later to fetch the management key:\n\n```go\nm, err := yk.Metadata(pin)\nif err != nil {\n\t// ...\n}\nif m.ManagementKey == nil {\n\t// ...\n}\nkey := *m.ManagementKey\n```\n\n### Certificates\n\nThe PIV applet can also store X.509 certificates on the YubiKey:\n\n```go\ncert, err := x509.ParseCertificate(certDER)\nif err != nil {\n\t// ...\n}\nif err := yk.SetCertificate(managementKey, piv.SlotAuthentication, cert); err != nil {\n\t// ...\n}\n```\n\nThe certificate can later be used in combination with the private key. For\nexample, to serve TLS traffic: \n\n```go\ncert, err := yk.Certificate(piv.SlotAuthentication)\nif err != nil {\n\t// ...\n}\npriv, err := yk.PrivateKey(piv.SlotAuthentication, cert.PublicKey, auth)\nif err != nil {\n\t// ...\n}\ns := \u0026http.Server{\n\tTLSConfig: \u0026tls.Config{\n\t\tCertificates: []tls.Certificate{\n\t\t\t{\n\t\t\t\tCertificate: [][]byte{cert.Raw},\n\t\t\t\tPrivateKey:  priv,\n\t\t\t},\n\t\t},\n\t},\n\tHandler: myHandler,\n}\n```\n\n### Attestation\n\nYubiKeys can attest that a particular key was generated on the smartcard, and\nthat it was set with specific PIN and touch policies. The client generates a\nkey, then asks the YubiKey to sign an attestation certificate:\n\n```go\n// Get the YubiKey's attestation certificate, which is signed by Yubico.\nyubiKeyAttestationCert, err := yk.AttestationCertificate()\nif err != nil {\n\t// ...\n}\n\n// Generate a key on the YubiKey and generate an attestation certificate for\n// that key. This will be signed by the YubiKey's attestation certificate.\nkey := piv.Key{\n\tAlgorithm:   piv.AlgorithmEC256,\n\tPINPolicy:   piv.PINPolicyAlways,\n\tTouchPolicy: piv.TouchPolicyAlways,\n}\nif _, err := yk.GenerateKey(managementKey, piv.SlotAuthentication, key); err != nil {\n\t// ...\n}\nslotAttestationCertificate, err := yk.Attest(piv.SlotAuthentication)\nif err != nil {\n\t// ...\n}\n\n// Send certificates to server.\n```\n\nA CA can then verify the attestation, proving a key was generated on the card\nand enforce policy:\n\n```go\n// Server receives both certificates, then proves a key was generated on the\n// YubiKey.\na, err := piv.Verify(yubiKeyAttestationCert, slotAttestationCertificate)\nif err != nil {\n\t// ...\n}\nif a.TouchPolicy != piv.TouchPolicyAlways {\n\t// ...\n}\n\n// Record YubiKey's serial number and public key.\npub := slotAttestationCertificate.PublicKey\nserial := a.Serial\n```\n\n## Installation\n\nOn MacOS, piv-go doesn't require any additional packages.\n\nTo build on Linux, piv-go requires PCSC lite. To install on Debian-based\ndistros, run:\n\n```\nsudo apt-get install libpcsclite-dev\n```\n\nOn Fedora:\n\n```\nsudo yum install pcsc-lite-devel\n```\n\nOn CentOS:\n\n```\nsudo yum install 'dnf-command(config-manager)'\nsudo yum config-manager --set-enabled PowerTools\nsudo yum install pcsc-lite-devel\n```\n\n## Testing\n\nTests automatically find connected available YubiKeys, but won't modify the\nsmart card without the `--wipe-yubikey` flag. To let the tests modify your\nYubiKey's PIV applet, run:\n\n```\ngo test -v ./piv --wipe-yubikey\n```\n\nLonger tests can be skipped with the `--test.short` flag.\n\n```\ngo test -v --short ./piv --wipe-yubikey\n```\n\n## Why?\n\nYubiKey's C PIV library, ykpiv, is brittle. The error messages aren't terrific,\nand while it has debug options, plumbing them through isn't idiomatic or\nconvenient.\n\nykpiv wraps PC/SC APIs available on Windows, Mac, and Linux. There's no\nrequirement for it to be written in any particular langauge. As an alternative\nto [pault.ag/go/ykpiv][go-ykpiv] this package re-implements ykpiv in Go instead\nof calling it.\n\n## Alternatives\n\nOpenSSH has experimental support for U2F keys ([announcement][openssh-u2f]) that\ndirectly use browser U2F challenges for smart cards.\n\n[go-ykpiv]: https://github.com/paultag/go-ykpiv\n[openssh-u2f]: https://marc.info/?l=openssh-unix-dev\u0026m=157259802529972\u0026w=2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjtaylorcpp%2Fpiv-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjtaylorcpp%2Fpiv-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjtaylorcpp%2Fpiv-go/lists"}