Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ jobs:
with:
only-latest-golang: false
run-codeql: true
golangci-lint-version: "v2.12.1"
golangci-lint-version: "v2.13.2"
secrets: inherit
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,32 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Changed

- Enforce the minimum HMAC key lengths from RFC 7518 §3.2 after migrating to
go-jose v4. `oct` keys must now be at least 32 bytes for HS256, 48 bytes for
HS384, and 64 bytes for HS512. `step crypto jwk create` rejects smaller values
for `--size`, and `--insecure` no longer overrides the minimum. Existing
shorter keys can no longer be used to sign or verify with the
`step crypto jwt` and `step crypto jws` commands and must be replaced
(smallstep/cli#1732, smallstep/crypto#1157).
- Require the `--size` of `oct` keys in `step crypto jwk create` to match the
AES key wrap algorithm exactly: 16 bytes for A128KW and A128GCMKW, 24 bytes for
A192KW and A192GCMKW, and 32 bytes for A256KW and A256GCMKW. Existing keys
whose size does not match their algorithm, including keys created without
`--size` for A128KW, A192KW, A128GCMKW, or A192GCMKW, are now rejected by
`step crypto jwe decrypt` (smallstep/cli#1732, smallstep/crypto#1157).

### Deprecated

### Removed

### Fixed

- Fix `step crypto jwe encrypt` with `oct` keys, which failed with
`unsupported key type '<nil>'` (smallstep/cli#1732).
- Keep the original protected header in `step crypto jose format`, reordering
its fields invalidated the signature or authentication tag of the token
(smallstep/cli#1732).

### Security

---
Expand Down
21 changes: 12 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ GORELEASER_BUILD_ID?=default

# all go files
SRC=$(shell find . -type f -name '*.go' -or -name go.mod -or -name go.sum)
GOSRC=$(shell find . -type f -name '*.go')

# tools run with `go tool`, their versions are defined in go.mod
GOIMPORTS=golang.org/x/tools/cmd/goimports
GOLANGCI_LINT=github.com/golangci/golangci-lint/v2/cmd/golangci-lint
GOTESTSUM=gotest.tools/gotestsum
GOVULNCHECK=golang.org/x/vuln/cmd/govulncheck

all: lint test build

Expand Down Expand Up @@ -104,10 +111,6 @@ GORELEASER_SKIP=$(if $(filter true,$(shell goreleaser --version | grep -q gorele
TMPDIR := $(shell mktemp -d)
bootstra%: GOPATH=$(shell go env GOPATH)
bootstra%:
$Q curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin latest
$Q go install golang.org/x/vuln/cmd/govulncheck@latest
$Q go install gotest.tools/gotestsum@latest
$Q go install golang.org/x/tools/cmd/goimports@latest
@echo "Installing GoReleaser Pro into $(GOPATH)/bin"
$Q curl -o $(TMPDIR)/goreleaser.tar.gz -L $(GORELEASER_PRO_URL)
$Q ls $(TMPDIR)
Expand Down Expand Up @@ -149,10 +152,10 @@ goreleaser:
#########################################

test:
$Q $(CGO_OVERRIDE) $(GOFLAGS) gotestsum -- -coverprofile=coverage.out -short -covermode=atomic ./...
$Q $(CGO_OVERRIDE) $(GOFLAGS) go tool $(GOTESTSUM) -- -coverprofile=coverage.out -short -covermode=atomic ./...

race:
$Q $(CGO_OVERRIDE) $(GOFLAGS) gotestsum -- -race ./...
$Q $(CGO_OVERRIDE) $(GOFLAGS) go tool $(GOTESTSUM) -- -race ./...

.PHONY: test race

Expand All @@ -161,16 +164,16 @@ race:
#########################################

fmt:
$Q goimports -local github.com/golangci/golangci-lint -l -w $(SRC)
$Q go tool $(GOIMPORTS) -local github.com/smallstep/cli/ -l -w $(GOSRC)

lint: golint govulncheck

golint: SHELL:=/bin/bash
golint:
$Q LOG_LEVEL=error golangci-lint run --config <(curl -s https://raw.githubusercontent.com/smallstep/workflows/master/.golangci.yml) --timeout=30m
$Q LOG_LEVEL=error go tool $(GOLANGCI_LINT) run --config <(curl -s https://raw.githubusercontent.com/smallstep/workflows/master/.golangci.yml) --timeout=30m

govulncheck:
$Q govulncheck ./...
$Q go tool $(GOVULNCHECK) ./...

.PHONY: fmt lint golint govulncheck

Expand Down
2 changes: 1 addition & 1 deletion command/ca/acme/eab/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func addAction(ctx *cli.Context) (err error) {
// TODO(hs): JSON output, so that executing this command can be more easily automated?

out := os.Stdout
format := "%-36s%-28s%-48s%s\n"
format := "%-40s%-28s%-48s%s\n"
fmt.Fprintf(out, format, "Key ID", "Provisioner", "Key (base64, raw url encoded)", "Reference")
fmt.Fprintf(out, format, cliEAK.id, cliEAK.provisioner, cliEAK.key, cliEAK.reference)

Expand Down
3 changes: 1 addition & 2 deletions command/ca/acme/eab/eab.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ import (
"github.com/pkg/errors"
"github.com/urfave/cli"

"github.com/smallstep/linkedca"

"github.com/smallstep/certificates/authority/admin"
"github.com/smallstep/certificates/ca"
"github.com/smallstep/linkedca"
)

type cliEAK struct {
Expand Down
2 changes: 1 addition & 1 deletion command/ca/acme/eab/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func listAction(ctx *cli.Context) (err error) {
}

cursor := ""
format := "%-36s%-28s%-16s%-30s%-30s%-40s%s\n"
format := "%-40s%-28s%-16s%-30s%-30s%-40s%s\n"
firstIteration := true
startedPager := false

Expand Down
5 changes: 2 additions & 3 deletions command/ca/health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import (
"github.com/stretchr/testify/require"
"github.com/urfave/cli"

"go.step.sm/crypto/minica"
"go.step.sm/crypto/pemutil"

"github.com/smallstep/certificates/authority/config"
stepca "github.com/smallstep/certificates/ca"
"go.step.sm/crypto/minica"
"go.step.sm/crypto/pemutil"
)

// reservePort "reserves" a TCP port by opening a listener on a random
Expand Down
3 changes: 2 additions & 1 deletion command/ca/policy/x509/wildcards.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package x509
import (
"context"

"github.com/urfave/cli"

"github.com/smallstep/cli/command/ca/policy/actions"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/internal/command"
"github.com/urfave/cli"
)

var provisionerFilterFlag = cli.StringFlag{
Expand Down
1 change: 1 addition & 0 deletions command/ca/provisioner/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/smallstep/certificates/ca"
"github.com/smallstep/cli-utils/errs"

"github.com/smallstep/cli/flags"
)

Expand Down
1 change: 0 additions & 1 deletion command/ca/provisioner/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/smallstep/certificates/ca"
"github.com/smallstep/cli-utils/errs"
"github.com/smallstep/cli-utils/ui"

"github.com/smallstep/linkedca"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/mldsa"
Expand Down
2 changes: 1 addition & 1 deletion command/ca/revoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/pkg/errors"
"github.com/urfave/cli"
"golang.org/x/crypto/ocsp"

"github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/authority/provisioner"
Expand All @@ -25,7 +26,6 @@ import (
"go.step.sm/crypto/jose"
"go.step.sm/crypto/pemutil"
"go.step.sm/crypto/x509util"
"golang.org/x/crypto/ocsp"

"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils/cautils"
Expand Down
3 changes: 2 additions & 1 deletion command/ca/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (
"github.com/pkg/errors"
"github.com/urfave/cli"

"golang.org/x/crypto/ssh"

"github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/pki"
"github.com/smallstep/cli-utils/command"
"github.com/smallstep/cli-utils/errs"
"github.com/smallstep/cli-utils/fileutil"
"go.step.sm/crypto/pemutil"
"golang.org/x/crypto/ssh"

"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils"
Expand Down
6 changes: 3 additions & 3 deletions command/certificate/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import (
"crypto/x509"
"fmt"

//nolint:gosec // support for sha1 fingerprints
_ "crypto/sha1"

"github.com/pkg/errors"
"github.com/urfave/cli"

Expand All @@ -17,6 +14,9 @@ import (

"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils"

//nolint:gosec // support for sha1 fingerprints
_ "crypto/sha1"
)

func fingerprintCommand() cli.Command {
Expand Down
3 changes: 2 additions & 1 deletion command/certificate/inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"flag"
"testing"

"github.com/smallstep/assert"
"github.com/urfave/cli"

"github.com/smallstep/assert"
"go.step.sm/crypto/pemutil"
)

Expand Down
1 change: 1 addition & 0 deletions command/certificate/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/pkg/errors"

"go.step.sm/crypto/x509util"
)

Expand Down
3 changes: 2 additions & 1 deletion command/certificate/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import (
"time"

"github.com/pkg/errors"
"github.com/urfave/cli"

"github.com/smallstep/cli-utils/errs"
"github.com/smallstep/cli-utils/ui"
"github.com/urfave/cli"
"go.step.sm/crypto/mldsa"
"go.step.sm/crypto/pemutil"
"go.step.sm/crypto/x509util"
Expand Down
14 changes: 7 additions & 7 deletions command/crypto/hash/hash.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package hash

import (
"github.com/pkg/errors"
"github.com/urfave/cli"

"github.com/smallstep/cli-utils/errs"

"github.com/smallstep/cli/flags"

//nolint:gosec // md5 can only be used with --insecure flag
"crypto/md5"
//nolint:gosec // sha1 is being used to calculate a hash, not a key
Expand All @@ -16,13 +23,6 @@ import (
"os"
"path"
"strings"

"github.com/pkg/errors"
"github.com/urfave/cli"

"github.com/smallstep/cli-utils/errs"

"github.com/smallstep/cli/flags"
)

type hashConstructor func() hash.Hash
Expand Down
54 changes: 50 additions & 4 deletions command/crypto/jose/jose.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jose

import (
"encoding/json"
"fmt"
"io"
"os"
Expand All @@ -9,7 +10,10 @@ import (

"github.com/pkg/errors"
"github.com/urfave/cli"

"go.step.sm/crypto/jose"

"github.com/smallstep/cli/internal/joseutil"
)

// Command returns the cli.Command for jose related subcommands.
Expand Down Expand Up @@ -75,10 +79,10 @@ func formatAction(*cli.Context) error {
// Attempt to parse an encrypted
// If it fails parse a regular JWS
var srz serializer
if enc, err := jose.ParseEncrypted(token); err == nil {
if enc, err := joseutil.ParseEncryptedInsecure(token); err == nil {
srz = enc
} else {
tok, err := jose.ParseJWS(token)
tok, err := joseutil.ParseSignedInsecure(token)
if err != nil {
return errors.Wrap(jose.TrimPrefix(err), "error parsing data")
}
Expand All @@ -90,14 +94,56 @@ func formatAction(*cli.Context) error {
if err != nil {
return errors.Wrap(jose.TrimPrefix(err), "error serializing data")
}
fmt.Println(str)
fmt.Println(withCompactProtected(str, token))
} else {
fmt.Println(srz.FullSerialize())
fmt.Println(withJSONProtected(srz.FullSerialize(), token))
}

return nil
}

// withCompactProtected returns the given compact serialization with the protected
// header of the original token in JSON format. go-jose marshals the header again
// when it serializes a token, which changes the bytes that the signature or the
// authentication tag cover if the fields are in a different order.
func withCompactProtected(compact, token string) string {
var jws struct {
Protected string `json:"protected"`
Signatures []struct {
Protected string `json:"protected"`
} `json:"signatures"`
}
if err := json.Unmarshal([]byte(token), &jws); err != nil {
return compact
}

protected := jws.Protected
if protected == "" && len(jws.Signatures) == 1 {
protected = jws.Signatures[0].Protected
}
_, rest, ok := strings.Cut(compact, ".")
if protected == "" || !ok {
return compact
}
return strings.TrimRight(protected, "=") + "." + rest
}

// withJSONProtected returns the given JSON serialization with the protected header
// of the original token in compact format, see withCompactProtected.
func withJSONProtected(full, token string) string {
var serialized struct {
Protected string `json:"protected"`
}
if err := json.Unmarshal([]byte(full), &serialized); err != nil {
return full
}

protected, _, _ := strings.Cut(token, ".")
return strings.Replace(full,
`"protected":"`+serialized.Protected+`"`,
`"protected":"`+protected+`"`, 1)
}

var stripWhitespaceRegex = regexp.MustCompile(`\s`)

// stripWhitespace strip all newlines and whitespace
Expand Down
9 changes: 6 additions & 3 deletions command/crypto/jwe/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,12 @@ func encryptAction(ctx *cli.Context) error {
KeyID: kid,
}
} else {
// Public keys are used for encryption
jwkPub := jwk.Public()
jwk = &jwkPub
// Public keys are used for encryption. go-jose JSONWebKey.Public() returns
// an empty key for oct, which are symmetric and are used as they are.
if !jose.IsSymmetric(jwk) {
jwkPub := jwk.Public()
jwk = &jwkPub
}

if jwk.Use == "sig" {
return errors.New("invalid jwk use: found 'sig' (signature), expecting 'enc' (encryption)")
Expand Down
Loading
Loading