diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f108f6d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,35 @@ +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: {} + +permissions: + contents: write + +jobs: + goreleaser: + name: GoReleaser + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + cache: true + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index a0ebed5..8b37517 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cmd/cert-bundler/testdata/pkg/* # Added by goreleaser init: dist/ +cmd/cert-bundler/testdata/bundle/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..f435ec8 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,447 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com + +# The lines below are called `modelines`. See `:help modeline` +# Feel free to remove those if you don't want/need to use them. +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +# vim: set ts=2 sw=2 tw=0 fo=cnqoj + +version: 2 + +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy + # you may remove this if you don't need go generate + - go generate ./... + +builds: + - id: atping + main: ./cmd/atping/main.go + binary: atping + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: ca-signed + main: ./cmd/ca-signed/main.go + binary: ca-signed + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: cert-bundler + main: ./cmd/cert-bundler/main.go + binary: cert-bundler + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: cert-revcheck + main: ./cmd/cert-revcheck/main.go + binary: cert-revcheck + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: certchain + main: ./cmd/certchain/main.go + binary: certchain + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: certdump + main: ./cmd/certdump/main.go + binary: certdump + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: certexpiry + main: ./cmd/certexpiry/main.go + binary: certexpiry + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: certser + main: ./cmd/certser/main.go + binary: certser + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: certverify + main: ./cmd/certverify/main.go + binary: certverify + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: clustersh + main: ./cmd/clustersh/main.go + binary: clustersh + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: cruntar + main: ./cmd/cruntar/main.go + binary: cruntar + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: csrpubdump + main: ./cmd/csrpubdump/main.go + binary: csrpubdump + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: data_sync + main: ./cmd/data_sync/main.go + binary: data_sync + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: diskimg + main: ./cmd/diskimg/main.go + binary: diskimg + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: dumpbytes + main: ./cmd/dumpbytes/main.go + binary: dumpbytes + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: eig + main: ./cmd/eig/main.go + binary: eig + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: fragment + main: ./cmd/fragment/main.go + binary: fragment + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: host + main: ./cmd/host/main.go + binary: host + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: jlp + main: ./cmd/jlp/main.go + binary: jlp + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: kgz + main: ./cmd/kgz/main.go + binary: kgz + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: minmax + main: ./cmd/minmax/main.go + binary: minmax + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: parts + main: ./cmd/parts/main.go + binary: parts + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: pem2bin + main: ./cmd/pem2bin/main.go + binary: pem2bin + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: pembody + main: ./cmd/pembody/main.go + binary: pembody + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: pemit + main: ./cmd/pemit/main.go + binary: pemit + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: readchain + main: ./cmd/readchain/main.go + binary: readchain + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: renfnv + main: ./cmd/renfnv/main.go + binary: renfnv + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: rhash + main: ./cmd/rhash/main.go + binary: rhash + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: rolldie + main: ./cmd/rolldie/main.go + binary: rolldie + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: showimp + main: ./cmd/showimp/main.go + binary: showimp + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: ski + main: ./cmd/ski/main.go + binary: ski + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: sprox + main: ./cmd/sprox/main.go + binary: sprox + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: stealchain + main: ./cmd/stealchain/main.go + binary: stealchain + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: stealchain-server + main: ./cmd/stealchain-server/main.go + binary: stealchain-server + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: subjhash + main: ./cmd/subjhash/main.go + binary: subjhash + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: tlsinfo + main: ./cmd/tlsinfo/main.go + binary: tlsinfo + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: tlskeypair + main: ./cmd/tlskeypair/main.go + binary: tlskeypair + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: utc + main: ./cmd/utc/main.go + binary: utc + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: yamll + main: ./cmd/yamll/main.go + binary: yamll + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + - id: zsearch + main: ./cmd/zsearch/main.go + binary: zsearch + env: + - CGO_ENABLED=0 + goos: [linux, darwin] + goarch: [amd64, arm64] + ignore: + - goos: darwin + goarch: amd64 + +archives: + - formats: [tar.gz] + # this name template makes the OS and Arch compatible with the results of `uname`. + name_template: >- + {{ .ProjectName }}_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + # use zip for windows archives + format_overrides: + - goos: windows + formats: [zip] + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" + +release: + footer: >- + + --- + + Released by [GoReleaser](https://github.com/goreleaser/goreleaser). diff --git a/backoff/backoff_test.go b/backoff/backoff_test.go index 9c093bf..5395fe1 100644 --- a/backoff/backoff_test.go +++ b/backoff/backoff_test.go @@ -91,7 +91,7 @@ func TestReset(t *testing.T) { } } -const decay = 25 * time.Millisecond +const decay = time.Second const maxDuration = 10 * time.Millisecond const interval = time.Millisecond diff --git a/cmd/certdump/main.go b/cmd/certdump/main.go index b2913da..c24c5e0 100644 --- a/cmd/certdump/main.go +++ b/cmd/certdump/main.go @@ -15,10 +15,138 @@ import ( "sort" "strings" + "github.com/kr/text" + "git.wntrmute.dev/kyle/goutils/certlib" "git.wntrmute.dev/kyle/goutils/lib" ) +// following two lifted from CFSSL, (replace-regexp "\(.+\): \(.+\)," +// "\2: \1,") + +const ( + sSHA256 = "SHA256" + sSHA512 = "SHA512" +) + +var keyUsage = map[x509.KeyUsage]string{ + x509.KeyUsageDigitalSignature: "digital signature", + x509.KeyUsageContentCommitment: "content committment", + x509.KeyUsageKeyEncipherment: "key encipherment", + x509.KeyUsageKeyAgreement: "key agreement", + x509.KeyUsageDataEncipherment: "data encipherment", + x509.KeyUsageCertSign: "cert sign", + x509.KeyUsageCRLSign: "crl sign", + x509.KeyUsageEncipherOnly: "encipher only", + x509.KeyUsageDecipherOnly: "decipher only", +} + +var extKeyUsages = map[x509.ExtKeyUsage]string{ + x509.ExtKeyUsageAny: "any", + x509.ExtKeyUsageServerAuth: "server auth", + x509.ExtKeyUsageClientAuth: "client auth", + x509.ExtKeyUsageCodeSigning: "code signing", + x509.ExtKeyUsageEmailProtection: "s/mime", + x509.ExtKeyUsageIPSECEndSystem: "ipsec end system", + x509.ExtKeyUsageIPSECTunnel: "ipsec tunnel", + x509.ExtKeyUsageIPSECUser: "ipsec user", + x509.ExtKeyUsageTimeStamping: "timestamping", + x509.ExtKeyUsageOCSPSigning: "ocsp signing", + x509.ExtKeyUsageMicrosoftServerGatedCrypto: "microsoft sgc", + x509.ExtKeyUsageNetscapeServerGatedCrypto: "netscape sgc", + x509.ExtKeyUsageMicrosoftCommercialCodeSigning: "microsoft commercial code signing", + x509.ExtKeyUsageMicrosoftKernelCodeSigning: "microsoft kernel code signing", +} + +func sigAlgoPK(a x509.SignatureAlgorithm) string { + switch a { + case x509.MD2WithRSA, x509.MD5WithRSA, x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: + return "RSA" + case x509.SHA256WithRSAPSS, x509.SHA384WithRSAPSS, x509.SHA512WithRSAPSS: + return "RSA-PSS" + case x509.ECDSAWithSHA1, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512: + return "ECDSA" + case x509.DSAWithSHA1, x509.DSAWithSHA256: + return "DSA" + case x509.PureEd25519: + return "Ed25519" + case x509.UnknownSignatureAlgorithm: + return "unknown public key algorithm" + default: + return "unknown public key algorithm" + } +} + +func sigAlgoHash(a x509.SignatureAlgorithm) string { + switch a { + case x509.MD2WithRSA: + return "MD2" + case x509.MD5WithRSA: + return "MD5" + case x509.SHA1WithRSA, x509.ECDSAWithSHA1, x509.DSAWithSHA1: + return "SHA1" + case x509.SHA256WithRSA, x509.ECDSAWithSHA256, x509.DSAWithSHA256: + return sSHA256 + case x509.SHA256WithRSAPSS: + return sSHA256 + case x509.SHA384WithRSA, x509.ECDSAWithSHA384: + return "SHA384" + case x509.SHA384WithRSAPSS: + return "SHA384" + case x509.SHA512WithRSA, x509.ECDSAWithSHA512: + return sSHA512 + case x509.SHA512WithRSAPSS: + return sSHA512 + case x509.PureEd25519: + return sSHA512 + case x509.UnknownSignatureAlgorithm: + return "unknown hash algorithm" + default: + return "unknown hash algorithm" + } +} + +const maxLine = 78 + +func makeIndent(n int) string { + s := " " + var sSb97 strings.Builder + for range n { + sSb97.WriteString(" ") + } + s += sSb97.String() + return s +} + +func indentLen(n int) int { + return 4 + (8 * n) +} + +// this isn't real efficient, but that's not a problem here. +func wrap(s string, indent int) string { + if indent > 3 { + indent = 3 + } + + wrapped := text.Wrap(s, maxLine) + lines := strings.SplitN(wrapped, "\n", 2) + if len(lines) == 1 { + return lines[0] + } + + if (maxLine - indentLen(indent)) <= 0 { + panic("too much indentation") + } + + rest := strings.Join(lines[1:], " ") + wrapped = text.Wrap(rest, maxLine-indentLen(indent)) + return lines[0] + "\n" + text.Indent(wrapped, makeIndent(indent)) +} + +func dumpHex(in []byte) string { + return lib.HexEncode(in, lib.HexEncodeUpperColon) +} + func certPublic(cert *x509.Certificate) string { switch pub := cert.PublicKey.(type) { case *rsa.PublicKey: diff --git a/cmd/certdump/util.go b/cmd/certdump/util.go deleted file mode 100644 index 66ffd23..0000000 --- a/cmd/certdump/util.go +++ /dev/null @@ -1,142 +0,0 @@ -package main - -import ( - "crypto/x509" - "fmt" - "strings" - - "github.com/kr/text" -) - -// following two lifted from CFSSL, (replace-regexp "\(.+\): \(.+\)," -// "\2: \1,") - -const ( - sSHA256 = "SHA256" - sSHA512 = "SHA512" -) - -var keyUsage = map[x509.KeyUsage]string{ - x509.KeyUsageDigitalSignature: "digital signature", - x509.KeyUsageContentCommitment: "content committment", - x509.KeyUsageKeyEncipherment: "key encipherment", - x509.KeyUsageKeyAgreement: "key agreement", - x509.KeyUsageDataEncipherment: "data encipherment", - x509.KeyUsageCertSign: "cert sign", - x509.KeyUsageCRLSign: "crl sign", - x509.KeyUsageEncipherOnly: "encipher only", - x509.KeyUsageDecipherOnly: "decipher only", -} - -var extKeyUsages = map[x509.ExtKeyUsage]string{ - x509.ExtKeyUsageAny: "any", - x509.ExtKeyUsageServerAuth: "server auth", - x509.ExtKeyUsageClientAuth: "client auth", - x509.ExtKeyUsageCodeSigning: "code signing", - x509.ExtKeyUsageEmailProtection: "s/mime", - x509.ExtKeyUsageIPSECEndSystem: "ipsec end system", - x509.ExtKeyUsageIPSECTunnel: "ipsec tunnel", - x509.ExtKeyUsageIPSECUser: "ipsec user", - x509.ExtKeyUsageTimeStamping: "timestamping", - x509.ExtKeyUsageOCSPSigning: "ocsp signing", - x509.ExtKeyUsageMicrosoftServerGatedCrypto: "microsoft sgc", - x509.ExtKeyUsageNetscapeServerGatedCrypto: "netscape sgc", - x509.ExtKeyUsageMicrosoftCommercialCodeSigning: "microsoft commercial code signing", - x509.ExtKeyUsageMicrosoftKernelCodeSigning: "microsoft kernel code signing", -} - -func sigAlgoPK(a x509.SignatureAlgorithm) string { - switch a { - case x509.MD2WithRSA, x509.MD5WithRSA, x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: - return "RSA" - case x509.SHA256WithRSAPSS, x509.SHA384WithRSAPSS, x509.SHA512WithRSAPSS: - return "RSA-PSS" - case x509.ECDSAWithSHA1, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512: - return "ECDSA" - case x509.DSAWithSHA1, x509.DSAWithSHA256: - return "DSA" - case x509.PureEd25519: - return "Ed25519" - case x509.UnknownSignatureAlgorithm: - return "unknown public key algorithm" - default: - return "unknown public key algorithm" - } -} - -func sigAlgoHash(a x509.SignatureAlgorithm) string { - switch a { - case x509.MD2WithRSA: - return "MD2" - case x509.MD5WithRSA: - return "MD5" - case x509.SHA1WithRSA, x509.ECDSAWithSHA1, x509.DSAWithSHA1: - return "SHA1" - case x509.SHA256WithRSA, x509.ECDSAWithSHA256, x509.DSAWithSHA256: - return sSHA256 - case x509.SHA256WithRSAPSS: - return sSHA256 - case x509.SHA384WithRSA, x509.ECDSAWithSHA384: - return "SHA384" - case x509.SHA384WithRSAPSS: - return "SHA384" - case x509.SHA512WithRSA, x509.ECDSAWithSHA512: - return sSHA512 - case x509.SHA512WithRSAPSS: - return sSHA512 - case x509.PureEd25519: - return sSHA512 - case x509.UnknownSignatureAlgorithm: - return "unknown hash algorithm" - default: - return "unknown hash algorithm" - } -} - -const maxLine = 78 - -func makeIndent(n int) string { - s := " " - var sSb97 strings.Builder - for range n { - sSb97.WriteString(" ") - } - s += sSb97.String() - return s -} - -func indentLen(n int) int { - return 4 + (8 * n) -} - -// this isn't real efficient, but that's not a problem here. -func wrap(s string, indent int) string { - if indent > 3 { - indent = 3 - } - - wrapped := text.Wrap(s, maxLine) - lines := strings.SplitN(wrapped, "\n", 2) - if len(lines) == 1 { - return lines[0] - } - - if (maxLine - indentLen(indent)) <= 0 { - panic("too much indentation") - } - - rest := strings.Join(lines[1:], " ") - wrapped = text.Wrap(rest, maxLine-indentLen(indent)) - return lines[0] + "\n" + text.Indent(wrapped, makeIndent(indent)) -} - -func dumpHex(in []byte) string { - var s string - var sSb130 strings.Builder - for i := range in { - sSb130.WriteString(fmt.Sprintf("%02X:", in[i])) - } - s += sSb130.String() - - return strings.Trim(s, ":") -}