Repository: smallstep/crypto
Pull request #703 (2025-02-14 21:06:52)

Use  SHA-256 for subject key id on FIPS 140-3 mode
### Description

This commit adds the fips util package, which reports whether the cryptography libraries are operating in FIPS 140-3 mode.

It also uses the 160 leftmost bits of SHA-256 to generate the Subject Key IDs.

Related:
- https://github.com/golang/go/issues/71746



Patch:
diff --git a/README.md b/README.md
index c41a221..f28b8c3 100644
--- a/README.md
+++ b/README.md
@@ -83,9 +83,14 @@ certificate, SSH certificate and SSH key fingerprints.
 
 ### tpm
 
-Package `tpm` provides an abstraction over and utilities for interacting
-with TPMs. It can be used to retrieve TPM information, retrieve its Endorsement
-Keys (EK) and associated certificates, create and operate on Attestation Keys (AK), 
-and create and operate on (attested) application keys. The `storage` subpackage 
-provides an interface and concrete implementations offering a transparent 
-persistence mechanism for Attestation and application keys.
\ No newline at end of file
+Package `tpm` provides an abstraction over and utilities for interacting with
+TPMs. It can be used to retrieve TPM information, retrieve its Endorsement Keys
+(EK) and associated certificates, create and operate on Attestation Keys (AK),
+and create and operate on (attested) application keys. The `storage` subpackage
+provides an interface and concrete implementations offering a transparent
+persistence mechanism for Attestation and application keys.
+
+### fipsutil
+
+Package `fipsutil` reports whether the cryptography libraries are operating in
+FIPS 140-3 mode.
diff --git a/fipsutil/fipsutil.go b/fipsutil/fipsutil.go
new file mode 100644
index 0000000..b37f1a1
--- /dev/null
+++ b/fipsutil/fipsutil.go
@@ -0,0 +1,49 @@
+//go:build go1.24
+
+package fipsutil
+
+import (
+	"crypto/fips140"
+	"os"
+	"strings"
+	"sync"
+)
+
+var (
+	only bool
+	once sync.Once
+)
+
+// Enabled reports whether the cryptography libraries are operating in FIPS
+// 140-3 mode.
+//
+// It can be controlled at runtime using the GODEBUG setting "fips140". If set
+// to "on", FIPS 140-3 mode is enabled. If set to "only", non-approved
+// cryptography functions will additionally return errors or panic.
+//
+// This can't be changed after the program has started.
+func Enabled() bool {
+	return fips140.Enabled()
+}
+
+// Only reports whether the cryptography libraries are operating in FIPS 140-3
+// "only" mode. When in this mode, using non-approved cryptography functions
+// will return errors or panic.
+func Only() bool {
+	once.Do(func() {
+		if !fips140.Enabled() {
+			return
+		}
+
+		// Parse GODEBUG backwards as the last value is the correct one.
+		settings := strings.Split(os.Getenv("GODEBUG"), ",")
+		for i := len(settings) - 1; i >= 0; i-- {
+			if settings[i] == "fips140=only" {
+				only = true
+				return
+			}
+		}
+	})
+
+	return only
+}
diff --git a/fipsutil/fipsutil_other.go b/fipsutil/fipsutil_other.go
new file mode 100644
index 0000000..056b622
--- /dev/null
+++ b/fipsutil/fipsutil_other.go
@@ -0,0 +1,19 @@
+//go:build !go1.24
+
+package fipsutil
+
+// Enabled reports whether the cryptography libraries are operating in FIPS
+// 140-3 mode.
+//
+// On Go < 1.24 it will always return false.
+func Enabled() bool {
+	return false
+}
+
+// Only reports whether the cryptography libraries are operating in FIPS 140-3
+// "only" mode.
+//
+// On Go < 1.24 it will always return false.
+func Only() bool {
+	return false
+}
diff --git a/go.mod b/go.mod
index 1878284..ca63dd8 100644
--- a/go.mod
+++ b/go.mod
@@ -1,17 +1,17 @@
 module go.step.sm/crypto
 
-go 1.22.12
+go 1.22
 
 require (
 	cloud.google.com/go/kms v1.20.5
 	filippo.io/edwards25519 v1.1.0
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0
-	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2
+	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1
 	github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0
 	github.com/Masterminds/sprig/v3 v3.3.0
 	github.com/ThalesIgnite/crypto11 v1.2.5
-	github.com/aws/aws-sdk-go-v2/config v1.29.6
-	github.com/aws/aws-sdk-go-v2/service/kms v1.37.18
+	github.com/aws/aws-sdk-go-v2/config v1.29.4
+	github.com/aws/aws-sdk-go-v2/service/kms v1.37.16
 	github.com/go-jose/go-jose/v3 v3.0.3
 	github.com/go-piv/piv-go/v2 v2.3.0
 	github.com/google/go-tpm v0.9.3
@@ -20,21 +20,21 @@ require (
 	github.com/peterbourgon/diskv/v3 v3.0.1
 	github.com/pkg/errors v0.9.1
 	github.com/schollz/jsonstore v1.1.0
+	github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262
 	github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935
 	github.com/stretchr/testify v1.10.0
 	go.uber.org/mock v0.5.0
-	golang.org/x/crypto v0.33.0
-	golang.org/x/net v0.35.0
-	golang.org/x/sys v0.30.0
-	google.golang.org/api v0.221.0
+	golang.org/x/crypto v0.32.0
+	golang.org/x/net v0.34.0
+	golang.org/x/sys v0.29.0
+	google.golang.org/api v0.219.0
 	google.golang.org/grpc v1.70.0
-	google.golang.org/protobuf v1.36.5
-	modernc.org/sqlite v1.35.0
+	google.golang.org/protobuf v1.36.4
 )
 
 require (
 	cloud.google.com/go v0.116.0 // indirect
-	cloud.google.com/go/auth v0.14.1 // indirect
+	cloud.google.com/go/auth v0.14.0 // indirect
 	cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
 	cloud.google.com/go/compute/metadata v0.6.0 // indirect
 	cloud.google.com/go/iam v1.2.2 // indirect
@@ -42,20 +42,20 @@ require (
 	dario.cat/mergo v1.0.1 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
-	github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect
+	github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/semver/v3 v3.3.0 // indirect
-	github.com/aws/aws-sdk-go-v2 v1.36.1 // indirect
-	github.com/aws/aws-sdk-go-v2/credentials v1.17.59 // indirect
-	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 // indirect
+	github.com/aws/aws-sdk-go-v2 v1.36.0 // indirect
+	github.com/aws/aws-sdk-go-v2/credentials v1.17.57 // indirect
+	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 // indirect
-	github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 // indirect
-	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 // indirect
-	github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 // indirect
+	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 // indirect
+	github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 // indirect
+	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 // indirect
+	github.com/aws/aws-sdk-go-v2/service/sts v1.33.12 // indirect
 	github.com/aws/smithy-go v1.22.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
@@ -83,24 +83,23 @@ require (
 	github.com/shopspring/decimal v1.4.0 // indirect
 	github.com/spf13/cast v1.7.0 // indirect
 	github.com/thales-e-security/pool v0.0.2 // indirect
-	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
-	go.opentelemetry.io/otel v1.34.0 // indirect
-	go.opentelemetry.io/otel/metric v1.34.0 // indirect
-	go.opentelemetry.io/otel/trace v1.34.0 // indirect
-	golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect
-	golang.org/x/mod v0.19.0 // indirect
-	golang.org/x/oauth2 v0.26.0 // indirect
-	golang.org/x/sync v0.11.0 // indirect
-	golang.org/x/text v0.22.0 // indirect
-	golang.org/x/time v0.10.0 // indirect
-	golang.org/x/tools v0.23.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
+	go.opentelemetry.io/otel v1.32.0 // indirect
+	go.opentelemetry.io/otel/metric v1.32.0 // indirect
+	go.opentelemetry.io/otel/trace v1.32.0 // indirect
+	golang.org/x/mod v0.18.0 // indirect
+	golang.org/x/oauth2 v0.25.0 // indirect
+	golang.org/x/sync v0.10.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
+	golang.org/x/time v0.9.0 // indirect
+	golang.org/x/tools v0.22.0 // indirect
 	google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	modernc.org/libc v1.61.13 // indirect
-	modernc.org/mathutil v1.7.1 // indirect
-	modernc.org/memory v1.8.2 // indirect
+	modernc.org/libc v1.55.3 // indirect
+	modernc.org/mathutil v1.6.0 // indirect
+	modernc.org/memory v1.8.0 // indirect
+	modernc.org/sqlite v1.34.5 // indirect
 )
diff --git a/go.sum b/go.sum
index ef9edcd..3f65986 100644
--- a/go.sum
+++ b/go.sum
@@ -32,8 +32,8 @@ cloud.google.com/go v0.92.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+Y
 cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
 cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
 cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
-cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0=
-cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM=
+cloud.google.com/go/auth v0.14.0 h1:A5C4dKV/Spdvxcl0ggWwWEzzP7AZMJSEIgrkngwhGYM=
+cloud.google.com/go/auth v0.14.0/go.mod h1:CYsoRL1PdiDuqeQpZE0bP2pnPrGqFcOkI0nldEQis+A=
 cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
 cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
@@ -87,10 +87,10 @@ github.com/Azure/azure-sdk-for-go v30.1.0+incompatible h1:HyYPft8wXpxMd0kfLtXo6e
 github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
 github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM=
@@ -102,8 +102,8 @@ github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxw
 github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
 github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 h1:H5xDQaE3XowWfhZRUpnfC+rGZMEVoSiji+b+/HFAPU4=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
@@ -162,32 +162,32 @@ github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi
 github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
 github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
-github.com/aws/aws-sdk-go-v2 v1.36.1 h1:iTDl5U6oAhkNPba0e1t1hrwAo02ZMqbrGq4k5JBWM5E=
-github.com/aws/aws-sdk-go-v2 v1.36.1/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
-github.com/aws/aws-sdk-go-v2/config v1.29.6 h1:fqgqEKK5HaZVWLQoLiC9Q+xDlSp+1LYidp6ybGE2OGg=
-github.com/aws/aws-sdk-go-v2/config v1.29.6/go.mod h1:Ft+WLODzDQmCTHDvqAH1JfC2xxbZ0MxpZAcJqmE1LTQ=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.59 h1:9btwmrt//Q6JcSdgJOLI98sdr5p7tssS9yAsGe8aKP4=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.59/go.mod h1:NM8fM6ovI3zak23UISdWidyZuI1ghNe2xjzUZAyT+08=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 h1:KwsodFKVQTlI5EyhRSugALzsV6mG/SGrdjlMXSZSdso=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28/go.mod h1:EY3APf9MzygVhKuPXAc5H+MkGb8k/DOSQjWS0LgkKqI=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 h1:BjUcr3X3K0wZPGFg2bxOWW3VPN8rkE3/61zhP+IHviA=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32/go.mod h1:80+OGC/bgzzFFTUmcuwD0lb4YutwQeKLFpmt6hoWapU=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 h1:m1GeXHVMJsRsUAqG6HjZWx9dj7F5TR+cF1bjyfYyBd4=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32/go.mod h1:IitoQxGfaKdVLNg0hD8/DXmAqNy0H4K2H2Sf91ti8sI=
+github.com/aws/aws-sdk-go-v2 v1.36.0 h1:b1wM5CcE65Ujwn565qcwgtOTT1aT4ADOHHgglKjG7fk=
+github.com/aws/aws-sdk-go-v2 v1.36.0/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
+github.com/aws/aws-sdk-go-v2/config v1.29.4 h1:ObNqKsDYFGr2WxnoXKOhCvTlf3HhwtoGgc+KmZ4H5yg=
+github.com/aws/aws-sdk-go-v2/config v1.29.4/go.mod h1:j2/AF7j/qxVmsNIChw1tWfsVKOayJoGRDjg1Tgq7NPk=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.57 h1:kFQDsbdBAR3GZsB8xA+51ptEnq9TIj3tS4MuP5b+TcQ=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.57/go.mod h1:2kerxPUUbTagAr/kkaHiqvj/bcYHzi2qiJS/ZinllU0=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 h1:7lOW8NUwE9UZekS1DYoiPdVAqZ6A+LheHWb+mHbNOq8=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27/go.mod h1:w1BASFIPOPUae7AgaH4SbjNbfdkxuggLyGfNFTn8ITY=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 h1:lWm9ucLSRFiI4dQQafLrEOmEDGry3Swrz0BIRdiHJqQ=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31/go.mod h1:Huu6GG0YTfbPphQkDSo4dEGmQRTKb9k9G7RdtyQWxuI=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 h1:ACxDklUKKXb48+eg5ROZXi1vDgfMyfIA/WyvqHcHI0o=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31/go.mod h1:yadnfsDwqXeVaohbGc/RaD287PuyRw2wugkh5ZL2J6k=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 h1:SYVGSFQHlchIcy6e7x12bsrxClCXSP5et8cqVhL8cuw=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13/go.mod h1:kizuDaLX37bG5WZaoxGPQR/LNFXpxp0vsUnqfkWXfNE=
-github.com/aws/aws-sdk-go-v2/service/kms v1.37.18 h1:pi9M/9n1PLayBXjia7LfwgXwcpFdFO7Q2cqKOZa1ZmM=
-github.com/aws/aws-sdk-go-v2/service/kms v1.37.18/go.mod h1:vZXvmzfhdsPj/axc8+qk/2fSCP4hGyaZ1MAduWEHAxM=
-github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 h1:/eE3DogBjYlvlbhd2ssWyeuovWunHLxfgw3s/OJa4GQ=
-github.com/aws/aws-sdk-go-v2/service/sso v1.24.15/go.mod h1:2PCJYpi7EKeA5SkStAmZlF6fi0uUABuhtF8ILHjGc3Y=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 h1:M/zwXiL2iXUrHputuXgmO94TVNmcenPHxgLXLutodKE=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14/go.mod h1:RVwIw3y/IqxC2YEXSIkAzRDdEU1iRabDPaYjpGCbCGQ=
-github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 h1:TzeR06UCMUq+KA3bDkujxK1GVGy+G8qQN/QVYzGLkQE=
-github.com/aws/aws-sdk-go-v2/service/sts v1.33.14/go.mod h1:dspXf/oYWGWo6DEvj98wpaTeqt5+DMidZD0A9BYTizc=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 h1:O+8vD2rGjfihBewr5bT+QUfYUHIxCVgG61LHoT59shM=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12/go.mod h1:usVdWJaosa66NMvmCrr08NcWDBRv4E6+YFG2pUdw1Lk=
+github.com/aws/aws-sdk-go-v2/service/kms v1.37.16 h1:DasFbYMIEAOh0QNbGTsJnTeVPualnAc6UR74Fs0Z9ME=
+github.com/aws/aws-sdk-go-v2/service/kms v1.37.16/go.mod h1:rtC85vnVnYbYWQWtm2tPHPnZ/JOPa5+iuUDip9XDa1Q=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 h1:c5WJ3iHz7rLIgArznb3JCSQT3uUMiz9DLZhIX+1G8ok=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.14/go.mod h1:+JJQTxB6N4niArC14YNtxcQtwEqzS3o9Z32n7q33Rfs=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 h1:f1L/JtUkVODD+k1+IiSJUUv8A++2qVr+Xvb3xWXETMU=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13/go.mod h1:tvqlFoja8/s0o+UruA1Nrezo/df0PzdunMDDurUfg6U=
+github.com/aws/aws-sdk-go-v2/service/sts v1.33.12 h1:fqg6c1KVrc3SYWma/egWue5rKI4G2+M4wMQN2JosNAA=
+github.com/aws/aws-sdk-go-v2/service/sts v1.33.12/go.mod h1:7Yn+p66q/jt38qMoVfNvjbm3D89mGBnkwDcijgtih8w=
 github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
 github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
 github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
@@ -438,8 +438,6 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
 github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
-github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
 github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
@@ -730,8 +728,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
 github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
-github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
 github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
 github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@@ -752,6 +750,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY=
+github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc=
 github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935 h1:kjYvkvS/Wdy0PVRDUAA0gGJIVSEZYhiAJtfwYgOYoGA=
 github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935/go.mod h1:vNAduivU014fubg6ewygkAvQC0IQVXqdc8vaGl/0er4=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -866,32 +866,30 @@ go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
-go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
 go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
 go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
-go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
-go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
+go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
+go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
 go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
 go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
-go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
-go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
+go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
+go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
 go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
 go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
-go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
-go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
+go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
+go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
 go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
 go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
 go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
 go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
 go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
-go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
-go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
+go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
+go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -930,8 +928,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
-golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -943,8 +941,6 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
-golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo=
-golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -972,8 +968,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
-golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
+golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1029,8 +1025,8 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
-golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1050,8 +1046,8 @@ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
-golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
+golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1066,8 +1062,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
-golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1148,15 +1144,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
-golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1169,16 +1165,16 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
-golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
+golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1252,8 +1248,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
-golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
+golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
+golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1291,8 +1287,8 @@ google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtuk
 google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
 google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
 google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.221.0 h1:qzaJfLhDsbMeFee8zBRdt/Nc+xmOuafD/dbdgGfutOU=
-google.golang.org/api v0.221.0/go.mod h1:7sOU2+TL4TxUTdbi0gWgAIg7tH5qBXxoyhtL+9x3biQ=
+google.golang.org/api v0.219.0 h1:nnKIvxKs/06jWawp2liznTBnMRQBEPpGo7I+oEypTX0=
+google.golang.org/api v0.219.0/go.mod h1:K6OmjGm+NtLrIkHxv1U3a0qIf/0JOvAHd5O/6AoyKYE=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1370,8 +1366,8 @@ google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD
 google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
 google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
 google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 h1:91mG8dNTpkC0uChJUQ9zCiRqx3GEEFOWaRZ0mI6Oj2I=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
 google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1421,8 +1417,8 @@ google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX7
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
-google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1465,30 +1461,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
-modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
-modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
-modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
-modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
-modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
-modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
-modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
-modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
-modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
-modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
-modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
-modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=
-modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
-modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
-modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
-modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
-modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
-modernc.org/sqlite v1.35.0 h1:yQps4fegMnZFdphtzlfQTCNBWtS0CZv48pRpW3RFHRw=
-modernc.org/sqlite v1.35.0/go.mod h1:9cr2sicr7jIaWTBKQmAxQLfBv9LL0su4ZTEV+utt3ic=
-modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
-modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
-modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
-modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
+modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
+modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
+modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
+modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
+modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
+modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
+modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g=
+modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE=
 pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
diff --git a/internal/utils/convert.go b/internal/utils/convert.go
deleted file mode 100644
index fbbd9d4..0000000
--- a/internal/utils/convert.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package utils
-
-import (
-	"fmt"
-	"math"
-)
-
-type integer interface {
-	~int | ~int64
-}
-
-// SafeUint64 converts an integer value to [uint64]. It returns an error if the value is out of range.
-func SafeUint64[T integer](x T) (uint64, error) {
-	if x < 0 {
-		return 0, fmt.Errorf("value %d out of range for uint64", x)
-	}
-
-	return uint64(x), nil
-}
-
-// MustUint64 converts an integer value to [uint64]. It panics if the value is out of range.
-func MustUint64[T integer](x T) uint64 {
-	u64, err := SafeUint64(x)
-	if err != nil {
-		panic(err)
-	}
-
-	return u64
-}
-
-// SafeUint32 converts an integer value to [uint32]. It returns an error if the value is out of range.
-func SafeUint32[T integer](x T) (uint32, error) {
-	if x < 0 || x > math.MaxUint32 {
-		return 0, fmt.Errorf("value %d out of range for uint32", x)
-	}
-
-	return uint32(x), nil
-}
-
-// MustUint32 converts an integer value to [uint32]. It panics if the value is out of range.
-func MustUint32[T integer](x T) uint32 {
-	u32, err := SafeUint32(x)
-	if err != nil {
-		panic(err)
-	}
-
-	return u32
-}
-
-// MustUint16 converts an integer value to [uint16]. It panics if the value is out of range.
-func MustUint16(x int) uint16 {
-	if x < 0 || x > math.MaxUint16 {
-		panic(fmt.Errorf("value %d out of range for uint16", x))
-	}
-
-	return uint16(x)
-}
-
-// SafeUint8 converts an integer value to [uint8]. It returns an error if the value is out of range.
-func SafeUint8(x int) (uint8, error) {
-	if x < 0 || x > math.MaxUint8 {
-		return 0, fmt.Errorf("value %d out of range for uint8", x)
-	}
-
-	return uint8(x), nil
-}
-
-// MustUint8 converts an integer value to [uint8]. It panics if the value is out of range.
-func MustUint8(x int) uint8 {
-	u8, err := SafeUint8(x)
-	if err != nil {
-		panic(err)
-	}
-
-	return u8
-}
diff --git a/kms/mackms/mackms.go b/kms/mackms/mackms.go
index 996928e..5d0e6ed 100644
--- a/kms/mackms/mackms.go
+++ b/kms/mackms/mackms.go
@@ -527,7 +527,7 @@ func (*MacKMS) DeleteKey(req *apiv1.DeleteKeyRequest) error {
 			if err != nil {
 				return fmt.Errorf("mackms DeleteKey failed: %w", err)
 			}
-			defer cfTag.Release() //nolint:gocritic // only two iterations
+			defer cfTag.Release()
 			dict[security.KSecAttrApplicationTag] = cfTag
 		}
 		// Extract logic to deleteItem to avoid defer on loops
@@ -617,20 +617,11 @@ func (k *MacKMS) SearchKeys(req *apiv1.SearchKeysRequest) (*apiv1.SearchKeysResp
 	results := make([]apiv1.SearchKeyResult, len(keys))
 	for i, key := range keys {
 		d := cf.NewDictionaryRef(cf.TypeRef(key.TypeRef()))
-		var (
-			hash    = security.GetSecAttrApplicationLabel(d)
-			label   = security.GetSecAttrLabel(d)
-			tag     = security.GetSecAttrApplicationTag(d)
-			tokenID = security.GetSecAttrTokenID(d)
-		)
-		d.Release()
+		defer d.Release()
 
 		name := uri.New(Scheme, url.Values{})
-		name.Values.Set("hash", hex.EncodeToString(hash))
-		name.Values.Set("label", label)
-		name.Values.Set("tag", tag)
-
-		keyInSecureEnclave := tokenID == "com.apple.setoken" //nolint:gosec // this is not a credential
+		tokenID := security.GetSecAttrTokenID(d)
+		keyInSecureEnclave := tokenID == "com.apple.setoken"
 		switch {
 		case !u.secureEnclaveSet && keyInSecureEnclave:
 			name.Values.Set("se", "true")
@@ -645,6 +636,10 @@ func (k *MacKMS) SearchKeys(req *apiv1.SearchKeysRequest) (*apiv1.SearchKeysResp
 			continue
 		}
 
+		name.Values.Set("hash", hex.EncodeToString(security.GetSecAttrApplicationLabel(d)))
+		name.Values.Set("label", security.GetSecAttrLabel(d))
+		name.Values.Set("tag", security.GetSecAttrApplicationTag(d))
+
 		// obtain the public key by requesting it, as the current
 		// representation of the key includes just the attributes.
 		pub, err := k.GetPublicKey(&apiv1.GetPublicKeyRequest{
diff --git a/minica/minica.go b/minica/minica.go
index 33728c7..0d12859 100644
--- a/minica/minica.go
+++ b/minica/minica.go
@@ -6,11 +6,9 @@ import (
 	"fmt"
 	"time"
 
-	"golang.org/x/crypto/ssh"
-
-	"go.step.sm/crypto/internal/utils"
 	"go.step.sm/crypto/sshutil"
 	"go.step.sm/crypto/x509util"
+	"golang.org/x/crypto/ssh"
 )
 
 // CA is the implementation of a simple X.509 and SSH CA.
@@ -164,11 +162,7 @@ func (c *CA) SignCSR(csr *x509.CertificateRequest, opts ...SignOption) (*x509.Ce
 func (c *CA) SignSSH(template *ssh.Certificate) (*ssh.Certificate, error) {
 	mut := *template
 	if mut.ValidAfter == 0 && mut.ValidBefore != ssh.CertTimeInfinity {
-		validAfter, err := utils.SafeUint64(time.Now().Unix())
-		if err != nil {
-			return nil, fmt.Errorf("failed converting timestamp to uint64: %w", err)
-		}
-		mut.ValidAfter = validAfter
+		mut.ValidAfter = uint64(time.Now().Unix())
 	}
 	if mut.ValidBefore == 0 {
 		mut.ValidBefore = mut.ValidAfter + 24*60*60
diff --git a/nssdb/certificate.go b/nssdb/certificate.go
index 9286835..bbd9f72 100644
--- a/nssdb/certificate.go
+++ b/nssdb/certificate.go
@@ -71,8 +71,8 @@ func x509CertToObject(cert *x509.Certificate, name string) (*Object, error) {
 }
 
 // AddCertificate returns the id of the certificate and public key objects.
-// Any certificates or public keys with the same subject key id will be replaced.
 // The only supported key type is ECDSA with curve P-256.
+// TODO(areed) what if a cert already has the same label or serial or cka id?
 func (db *NSSDB) AddCertificate(ctx context.Context, cert *x509.Certificate, name string) (uint32, uint32, error) {
 	if cert.PublicKeyAlgorithm != x509.ECDSA {
 		return 0, 0, errors.New("unsupported public key algorithm")
@@ -87,16 +87,6 @@ func (db *NSSDB) AddCertificate(ctx context.Context, cert *x509.Certificate, nam
 		return 0, 0, err
 	}
 
-	matches, err := db.findByAttr(ctx, CKO_CERTIFICATE, "CKA_ID", cert.SubjectKeyId)
-	if err != nil {
-		return 0, 0, fmt.Errorf("failed to find by CKA_ID: %w", err)
-	}
-	for _, id := range matches {
-		if err := db.DeleteCertificate(ctx, id); err != nil {
-			return 0, 0, fmt.Errorf("failed to delete conflicting certificate %d: %w", id, err)
-		}
-	}
-
 	certID, err := db.InsertPublic(ctx, certObj)
 	if err != nil {
 		return 0, 0, err
@@ -113,10 +103,7 @@ func (db *NSSDB) AddCertificate(ctx context.Context, cert *x509.Certificate, nam
 
 // Import returns (cert id, public key id, private key id) on success. The
 // certificates subject key id will be added as CKA_ID to all three objects to
-// bind them together. All certificate and key objects with the same CKA_ID will
-// be replaced. Certificates with the same name and different subject key id
-// will not be replaced. Use DeleteCertificateByName for that.
-// The only supported key type is ECDSA with curve P-256.
+// bind them together. The only supported key type is ECDSA with curve P-256.
 func (db *NSSDB) Import(ctx context.Context, name string, cert *x509.Certificate, privKey crypto.PrivateKey) (uint32, uint32, uint32, error) {
 	var privKeyID uint32
 
@@ -140,57 +127,6 @@ func (db *NSSDB) Import(ctx context.Context, name string, cert *x509.Certificate
 	return certID, pubKeyID, privKeyID, nil
 }
 
-// DeleteCertificatesByName deletes all certificates with the given nickname,
-// along with their keys.
-func (db *NSSDB) DeleteCertificatesByName(ctx context.Context, name string) error {
-	ids, err := db.findByAttr(ctx, CKO_CERTIFICATE, "CKA_LABEL", []byte(name))
-	if err != nil {
-		return fmt.Errorf("find certificates with matching name: %w", err)
-	}
-	for _, id := range ids {
-		if err := db.DeleteCertificate(ctx, id); err != nil {
-			return fmt.Errorf("delete certificate %d: %w", id, err)
-		}
-	}
-	return nil
-}
-
-// DeleteCertificate deletes a certificate and its keys.
-func (db *NSSDB) DeleteCertificate(ctx context.Context, id uint32) error {
-	obj, err := db.GetObjectPublic(ctx, id)
-	if err != nil {
-		return err
-	}
-	if err := obj.ValidateULong("CKA_CLASS", CKO_CERTIFICATE); err != nil {
-		return err
-	}
-	ckaID := obj.Attributes["CKA_ID"]
-	if len(ckaID) > 0 {
-		pubKeyIDs, err := db.findByAttr(ctx, CKO_PUBLIC_KEY, "CKA_ID", ckaID)
-		if err != nil {
-			return fmt.Errorf("find public keys: %w", err)
-		}
-		for _, id := range pubKeyIDs {
-			if err := db.DeleteObjectPublic(ctx, id); err != nil {
-				return fmt.Errorf("delete public key %d: %w", id, err)
-			}
-		}
-		privKeyIDs, err := db.findByAttr(ctx, CKO_PRIVATE_KEY, "CKA_ID", ckaID)
-		if err != nil {
-			return fmt.Errorf("find private keys: %w", err)
-		}
-		for _, id := range privKeyIDs {
-			if err := db.DeleteObjectPrivate(ctx, id); err != nil {
-				return fmt.Errorf("delete private key %d: %w", id, err)
-			}
-		}
-	}
-	if err := db.DeleteObjectPublic(ctx, id); err != nil {
-		return fmt.Errorf("delete certificate object: %w", err)
-	}
-	return nil
-}
-
 // ListCertificateObjects returns all x509 certificate objects from the
 // nssPublic table in the cert db.
 func (db *NSSDB) ListCertificateObjects(ctx context.Context) ([]*Object, error) {
diff --git a/nssdb/encrypt.go b/nssdb/encrypt.go
index aab94e2..aea8f24 100644
--- a/nssdb/encrypt.go
+++ b/nssdb/encrypt.go
@@ -8,12 +8,10 @@ import (
 	"errors"
 	"fmt"
 
+	"go.step.sm/crypto/randutil"
 	"golang.org/x/crypto/cryptobyte"
 	asn1tag "golang.org/x/crypto/cryptobyte/asn1"
 	"golang.org/x/crypto/pbkdf2"
-
-	"go.step.sm/crypto/internal/utils"
-	"go.step.sm/crypto/randutil"
 )
 
 var (
@@ -288,14 +286,6 @@ func newAES256CBC() (*aes256CBCParams, error) {
 	if err != nil {
 		return nil, err
 	}
-	// TODO(areed) Every IV that I found in an NSS db that was generated by NSS
-	// tools started with these bytes. The first byte is the ASN.1 tag for an octet
-	// string and the second is length of 14. The NSS tools fail to decode if the
-	// IV doesn't start with these two bytes. This means only the trailing 14 bytes
-	// of the IV are unique. Need to determine why NSS does this instead of using
-	// an 18 byte ASN.1 encoded octet string with 16 random bytes.
-	iv[0] = 0x04
-	iv[1] = 0x0E
 	return &aes256CBCParams{
 		InitializationVector: iv,
 	}, nil
@@ -304,18 +294,14 @@ func newAES256CBC() (*aes256CBCParams, error) {
 func (p *aes256CBCParams) encrypt(key, plaintext []byte) ([]byte, error) {
 	block, err := aes.NewCipher(key)
 	if err != nil {
-		return nil, fmt.Errorf("failed creating new AES cipher: %w", err)
-	}
-
-	paddedPlaintext, err := cbcPad(plaintext)
-	if err != nil {
-		return nil, fmt.Errorf("failed padding plaintext: %w", err)
+		return nil, err
 	}
 
-	ciphertext := make([]byte, len(paddedPlaintext))
-
 	enc := cipher.NewCBCEncrypter(block, p.InitializationVector)
-	enc.CryptBlocks(ciphertext, paddedPlaintext)
+
+	plaintext = cbcPad(plaintext)
+	ciphertext := make([]byte, len(plaintext))
+	enc.CryptBlocks(ciphertext, plaintext)
 
 	return ciphertext, nil
 }
@@ -349,21 +335,17 @@ func (p *aes256CBCParams) unmarshal(s cryptobyte.String) error {
 }
 
 // https://github.com/nss-dev/nss/blob/NSS_3_107_RTM/lib/softoken/padbuf.c#L17
-func cbcPad(plaintext []byte) ([]byte, error) {
+func cbcPad(plaintext []byte) []byte {
 	inLen := len(plaintext)
 
 	desLen := (inLen + aes.BlockSize) & ^(aes.BlockSize - 1)
-
-	desPadLen, err := utils.SafeUint8(desLen - inLen)
-	if err != nil {
-		return nil, fmt.Errorf("conversion to uint8 failed: %w", err)
-	}
+	desPadLen := uint8(desLen - inLen)
 
 	for i := inLen; i < desLen; i++ {
 		plaintext = append(plaintext, desPadLen)
 	}
 
-	return plaintext, nil
+	return plaintext
 }
 
 func cbcUnpad(plaintext []byte) []byte {
diff --git a/nssdb/keys.go b/nssdb/keys.go
index aece23e..1833cf8 100644
--- a/nssdb/keys.go
+++ b/nssdb/keys.go
@@ -161,27 +161,14 @@ func ecPrivKeyToObject(priv *ecdsa.PrivateKey, name string, id []byte, certCNs .
 }
 
 // AddPrivateKey adds a private key to the nssPrivate database and returns its id.
-// The ckaID argument should come from the SubjectKeyID of the associated certificate.
-// Keys with the same ckaID will be replaced.
 // Only ecdsa keys with curve P-256 are supported.
-func (db *NSSDB) AddPrivateKey(ctx context.Context, privKey *ecdsa.PrivateKey, name string, ckaID []byte, certCNs ...string) (uint32, error) {
+// TODO(areed) what if a key already has the cka id? Update?
+func (db *NSSDB) AddPrivateKey(ctx context.Context, privKey *ecdsa.PrivateKey, name string, id []byte, certCNs ...string) (uint32, error) {
 	if privKey.Curve != elliptic.P256() {
 		return 0, errors.New("unsupported curve")
 	}
 
-	if len(ckaID) > 0 {
-		matches, err := db.findByAttr(ctx, CKO_PRIVATE_KEY, "CKA_ID", ckaID)
-		if err != nil {
-			return 0, fmt.Errorf("find cka id conflicts: %w", err)
-		}
-		for _, id := range matches {
-			if err := db.DeleteObjectPrivate(ctx, id); err != nil {
-				return 0, fmt.Errorf("delete conflicting private key %d: %w", id, err)
-			}
-		}
-	}
-
-	privKeyObj, err := ecPrivKeyToObject(privKey, name, ckaID, certCNs...)
+	privKeyObj, err := ecPrivKeyToObject(privKey, name, id, certCNs...)
 	if err != nil {
 		return 0, err
 	}
@@ -195,27 +182,14 @@ func (db *NSSDB) AddPrivateKey(ctx context.Context, privKey *ecdsa.PrivateKey, n
 }
 
 // AddPublicKey adds a public key to the nssPublic database and returns its id.
-// The ckaID argument should come from the SubjectKeyID of the associated certificate.
-// Keys with the same ckaID will be replaced.
 // Only ecdsa keys with curve P-256 are supported.
-func (db *NSSDB) AddPublicKey(ctx context.Context, pubKey *ecdsa.PublicKey, ckaID []byte) (uint32, error) {
+// TODO(areed) what if a key already has the cka id? Update it?
+func (db *NSSDB) AddPublicKey(ctx context.Context, pubKey *ecdsa.PublicKey, id []byte) (uint32, error) {
 	if pubKey.Curve != elliptic.P256() {
 		return 0, errors.New("unsupported curve")
 	}
 
-	if len(ckaID) > 0 {
-		matches, err := db.findByAttr(ctx, CKO_PUBLIC_KEY, "CKA_ID", ckaID)
-		if err != nil {
-			return 0, fmt.Errorf("find cka id conflicts: %w", err)
-		}
-		for _, id := range matches {
-			if err := db.DeleteObjectPublic(ctx, id); err != nil {
-				return 0, fmt.Errorf("delete conflicting public key %d: %w", id, err)
-			}
-		}
-	}
-
-	pubKeyObj, err := ecPubKeyToObject(pubKey, ckaID)
+	pubKeyObj, err := ecPubKeyToObject(pubKey, id)
 	if err != nil {
 		return 0, err
 	}
diff --git a/nssdb/nssdb.go b/nssdb/nssdb.go
index e23463e..870e8ec 100644
--- a/nssdb/nssdb.go
+++ b/nssdb/nssdb.go
@@ -11,9 +11,8 @@ import (
 	"strings"
 	"time"
 
-	_ "modernc.org/sqlite" // enable sql driver
-
-	"go.step.sm/crypto/internal/utils"
+	// enable sql driver
+	_ "modernc.org/sqlite"
 )
 
 var columnNames = make(map[string]string, len(columns))
@@ -457,13 +456,7 @@ func (db *NSSDB) scan(ctx context.Context, rows *sql.Rows, private bool) (*Objec
 			}
 		}
 	}
-
-	u32ID, err := utils.SafeUint32(id.Int64)
-	if err != nil {
-		return nil, fmt.Errorf("failed converting %d to uint32: %w", id.Int64, err)
-	}
-
-	row.ID = u32ID
+	row.ID = uint32(id.Int64)
 	if _, ok := row.EncryptedAttributes["CKA_VALUE"]; ok {
 		ckaValSignatureID := keySignatureID(row.ID)
 		md, err := db.GetMetadata(ctx, ckaValSignatureID)
@@ -480,10 +473,7 @@ func (db *NSSDB) scan(ctx context.Context, rows *sql.Rows, private bool) (*Objec
 
 // https://github.com/nss-dev/nss/blob/NSS_3_107_RTM/lib/softoken/sdb.c#L1260
 func (db *NSSDB) getObjectID(ctx context.Context) (uint32, error) {
-	id, err := utils.SafeUint32(time.Now().Unix() & 0x3fffffff)
-	if err != nil {
-		return 0, fmt.Errorf("failed converting timestamp to uint32: %w", err)
-	}
+	id := uint32(time.Now().Unix() & 0x3fffffff)
 
 	for i := 0; i < 0x40000000; i++ {
 		id &= 0x3fffffff
@@ -502,48 +492,3 @@ func (db *NSSDB) getObjectID(ctx context.Context) (uint32, error) {
 
 	return 0, errors.New("no id available")
 }
-
-// findByAttr returns ids of objects having the specified attribute value.
-func (db *NSSDB) findByAttr(ctx context.Context, ckaClass uint32, name string, val []byte) ([]uint32, error) {
-	col := columns[name]
-	if !db.colTable[col] {
-		return nil, fmt.Errorf("this nss db does not have a column for the attribute %q", name)
-	}
-
-	var rows *sql.Rows
-	var err error
-	switch ckaClass {
-	case CKO_PRIVATE_KEY:
-		//nolint:gosec // trusted column name
-		q := fmt.Sprintf("SELECT id FROM nssPrivate WHERE %s = ? AND a0 = ? AND id IS NOT NULL", col)
-		rows, err = db.Key.QueryContext(ctx, q, val, encodeDBUlong(CKO_PRIVATE_KEY))
-	case CKO_PUBLIC_KEY:
-		//nolint:gosec // trusted column name
-		q := fmt.Sprintf("SELECT id FROM nssPublic WHERE %s = ? AND a0 =  ? AND id IS NOT NULL", col)
-		rows, err = db.Cert.QueryContext(ctx, q, val, encodeDBUlong(CKO_PUBLIC_KEY))
-	case CKO_CERTIFICATE:
-		//nolint:gosec // trusted column name
-		q := fmt.Sprintf("SELECT id FROM nssPublic WHERE %s = ? AND a0 = ? AND a80 = ? AND id IS NOT NULL", col)
-		rows, err = db.Cert.QueryContext(ctx, q, val, encodeDBUlong(CKO_CERTIFICATE), encodeDBUlong(CKC_X_509))
-	default:
-		return nil, fmt.Errorf("unsupported class %d", ckaClass)
-	}
-	if err != nil {
-		return nil, err
-	}
-	defer rows.Close()
-
-	var ids []uint32
-	for rows.Next() {
-		var id uint32
-		if err := rows.Scan(&id); err != nil {
-			return nil, err
-		}
-		ids = append(ids, id)
-	}
-	if err := rows.Err(); err != nil {
-		return nil, err
-	}
-
-	return ids, nil
-}
diff --git a/pemutil/pem.go b/pemutil/pem.go
index e3bbf11..9202510 100644
--- a/pemutil/pem.go
+++ b/pemutil/pem.go
@@ -20,11 +20,10 @@ import (
 	"strings"
 
 	"github.com/pkg/errors"
-	"golang.org/x/crypto/ssh"
-
 	"go.step.sm/crypto/internal/utils"
 	"go.step.sm/crypto/keyutil"
 	"go.step.sm/crypto/x25519"
+	"golang.org/x/crypto/ssh"
 )
 
 // DefaultEncCipher is the default algorithm used when encrypting sensitive
@@ -641,7 +640,7 @@ func Serialize(in interface{}, opts ...Options) (*pem.Block, error) {
 				}
 			} else {
 				var err error
-				p, err = x509.EncryptPEMBlock(rand.Reader, p.Type, p.Bytes, password, DefaultEncCipher) //nolint:staticcheck // support legacy use cases
+				p, err = x509.EncryptPEMBlock(rand.Reader, p.Type, p.Bytes, password, DefaultEncCipher)
 				if err != nil {
 					return nil, errors.Wrap(err, "failed to serialize to PEM")
 				}
diff --git a/pemutil/pkcs8.go b/pemutil/pkcs8.go
index 104d267..fb6c96c 100644
--- a/pemutil/pkcs8.go
+++ b/pemutil/pkcs8.go
@@ -174,7 +174,7 @@ func (c rfc1423Algo) deriveKey(password, salt []byte, h func() hash.Hash) []byte
 // key derived using PBKDF2 over the given password.
 func DecryptPEMBlock(block *pem.Block, password []byte) ([]byte, error) {
 	if block.Headers["Proc-Type"] == "4,ENCRYPTED" {
-		return x509.DecryptPEMBlock(block, password) //nolint:staticcheck // support legacy use cases
+		return x509.DecryptPEMBlock(block, password)
 	}
 
 	// PKCS#8 header defined in RFC7468 section 11
diff --git a/sshutil/certificate.go b/sshutil/certificate.go
index bf3a36b..a2367dd 100644
--- a/sshutil/certificate.go
+++ b/sshutil/certificate.go
@@ -9,10 +9,8 @@ import (
 	"time"
 
 	"github.com/pkg/errors"
-	"golang.org/x/crypto/ssh"
-
-	"go.step.sm/crypto/internal/utils"
 	"go.step.sm/crypto/randutil"
+	"golang.org/x/crypto/ssh"
 )
 
 // Certificate is the json representation of ssh.Certificate.
@@ -132,6 +130,5 @@ func toValidity(t time.Time) uint64 {
 	if t.IsZero() {
 		return 0
 	}
-
-	return utils.MustUint64(t.Unix())
+	return uint64(t.Unix())
 }
diff --git a/sshutil/fingerprint.go b/sshutil/fingerprint.go
index 1a5fd38..9e1cd9a 100644
--- a/sshutil/fingerprint.go
+++ b/sshutil/fingerprint.go
@@ -1,15 +1,14 @@
 package sshutil
 
 import (
-	"crypto/dsa" //nolint:staticcheck // support for DSA fingerprints
+	"crypto/dsa" // support for DSA fingerprints
 	"crypto/rsa"
 	"crypto/sha256"
 	"fmt"
 
 	"github.com/pkg/errors"
-	"golang.org/x/crypto/ssh"
-
 	"go.step.sm/crypto/fingerprint"
+	"golang.org/x/crypto/ssh"
 )
 
 // FingerprintEncoding defines the supported encodings for SSH key and
diff --git a/sshutil/sshutil.go b/sshutil/sshutil.go
index 09b0158..b21ff65 100644
--- a/sshutil/sshutil.go
+++ b/sshutil/sshutil.go
@@ -2,7 +2,7 @@ package sshutil
 
 import (
 	"crypto"
-	"crypto/dsa" //nolint:staticcheck // support for DSA fingerprints
+	"crypto/dsa" // support for DSA fingerprints
 	"crypto/ecdh"
 	"crypto/ecdsa"
 	"crypto/ed25519"
diff --git a/tpm/algorithm/algorithm.go b/tpm/algorithm/algorithm.go
index 08d891f..a0adeff 100644
--- a/tpm/algorithm/algorithm.go
+++ b/tpm/algorithm/algorithm.go
@@ -105,12 +105,7 @@ var algs = map[Algorithm]string{
 type Algorithm uint16
 
 func (a Algorithm) String() string {
-	v, ok := algs[a]
-	if !ok {
-		return "UNKNOWN_ALGORITHM"
-	}
-
-	return v
+	return algs[Algorithm(int(a))]
 }
 
 func (a Algorithm) MarshalJSON() ([]byte, error) {
diff --git a/tpm/random.go b/tpm/random.go
index bc804bd..b8a0b5a 100644
--- a/tpm/random.go
+++ b/tpm/random.go
@@ -8,8 +8,6 @@ import (
 	"math"
 
 	"github.com/google/go-tpm/legacy/tpm2"
-
-	"go.step.sm/crypto/internal/utils"
 )
 
 type ShortRandomReadError struct {
@@ -72,7 +70,7 @@ func (g *generator) Read(p []byte) (n int, err error) {
 
 	var result []byte
 	requestedLength := len(p)
-	singleRequestLength := utils.MustUint16(requestedLength)
+	singleRequestLength := uint16(requestedLength)
 	for len(result) < requestedLength {
 		if r, err := g.t.generateRandom(ctx, singleRequestLength); err == nil {
 			result = append(result, r...)
@@ -80,7 +78,7 @@ func (g *generator) Read(p []byte) (n int, err error) {
 			var s ShortRandomReadError
 			if errors.As(err, &s) && s.Generated > 0 {
 				// adjust number of bytes to request if at least some data was read and continue loop
-				singleRequestLength = utils.MustUint16(s.Generated)
+				singleRequestLength = uint16(s.Generated)
 				result = append(result, r...)
 			} else {
 				g.readError = err // store the error to be returned for future calls to Read
diff --git a/tpm/tss2/signer.go b/tpm/tss2/signer.go
index e37d03c..59a6a2d 100644
--- a/tpm/tss2/signer.go
+++ b/tpm/tss2/signer.go
@@ -30,8 +30,6 @@ import (
 
 	"github.com/google/go-tpm/legacy/tpm2"
 	"github.com/google/go-tpm/tpmutil"
-
-	"go.step.sm/crypto/internal/utils"
 )
 
 var (
@@ -164,12 +162,7 @@ func (s *Signer) Public() crypto.PublicKey {
 
 // Sign implements the [crypto.Signer] interface.
 func (s *Signer) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
-	parent, err := utils.SafeUint32(s.tpmKey.Parent)
-	if err != nil {
-		return nil, fmt.Errorf("failed converting parent handle: %w", err)
-	}
-
-	parentHandle := tpmutil.Handle(parent)
+	parentHandle := tpmutil.Handle(s.tpmKey.Parent)
 	if !handleIsPersistent(s.tpmKey.Parent) {
 		parentHandle, _, err = tpm2.CreatePrimary(s.rw, parentHandle, tpm2.PCRSelection{}, "", "", s.srkTemplate)
 		if err != nil {
diff --git a/tpm/tss2/tss2.go b/tpm/tss2/tss2.go
index ef45d26..11fda2d 100644
--- a/tpm/tss2/tss2.go
+++ b/tpm/tss2/tss2.go
@@ -139,7 +139,7 @@ func MarshalPrivateKey(key *TPMKey) ([]byte, error) {
 	return asn1.Marshal(*key)
 }
 
-func readOptionalTag(input *cryptobyte.String, tag uint8) (cryptobyte.String, bool) {
+func readOptionalTag(input *cryptobyte.String, tag int) (cryptobyte.String, bool) {
 	var isPresent bool
 	var output cryptobyte.String
 	if !input.ReadOptionalASN1(&output, &isPresent, cryptobyte_asn1.Tag(tag).Constructed().ContextSpecific()) {
diff --git a/x509util/utils.go b/x509util/utils.go
index b3961da..55fe7e8 100644
--- a/x509util/utils.go
+++ b/x509util/utils.go
@@ -5,6 +5,7 @@ import (
 	"crypto"
 	"crypto/rand"
 	"crypto/sha1" //nolint:gosec // SubjectKeyIdentifier by RFC 5280
+	"crypto/sha256"
 	"crypto/x509"
 	"crypto/x509/pkix"
 	"encoding/asn1"
@@ -17,6 +18,8 @@ import (
 
 	"github.com/pkg/errors"
 	"golang.org/x/net/idna"
+
+	"go.step.sm/crypto/fipsutil"
 )
 
 var emptyASN1Subject = []byte{0x30, 0}
@@ -110,6 +113,9 @@ type subjectPublicKeyInfo struct {
 // The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the
 // BIT STRING subjectPublicKey (excluding the tag, length, and number of unused
 // bits).
+//
+// If FIPS 140-3 mode is enabled, instead of SHA-1, it will use the leftmost
+// 160-bits of the SHA-256 hash according to RFC 7093 section 2.
 func generateSubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
 	b, err := x509.MarshalPKIXPublicKey(pub)
 	if err != nil {
@@ -119,9 +125,22 @@ func generateSubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
 	if _, err = asn1.Unmarshal(b, &info); err != nil {
 		return nil, errors.Wrap(err, "error unmarshaling public key")
 	}
+	return marshalSubjectKeyID(info.SubjectPublicKey.Bytes), nil
+}
+
+// marshalSubjectKeyID marshals the key identifier data using SHA-1 according to
+// the RFC 5280 section 4.2.1.2. If FIPS 140-3 mode is enabled it will use the
+// leftmost 160-bits of the SHA-256 hash according to RFC 7093 section 2
+// instead.
+func marshalSubjectKeyID(data []byte) []byte {
+	if fipsutil.Enabled() {
+		hash := sha256.Sum256(data)
+		return hash[:20]
+	}
+
 	//nolint:gosec // SubjectKeyIdentifier by RFC 5280
-	hash := sha1.Sum(info.SubjectPublicKey.Bytes)
-	return hash[:], nil
+	hash := sha1.Sum(data)
+	return hash[:]
 }
 
 // subjectIsEmpty returns whether the given pkix.Name (aka Subject) is an empty sequence


Test patch:
diff --git a/fipsutil/fipsutil_test.go b/fipsutil/fipsutil_test.go
new file mode 100644
index 0000000..d5bac97
--- /dev/null
+++ b/fipsutil/fipsutil_test.go
@@ -0,0 +1,8 @@
+package fipsutil
+
+import "testing"
+
+func TestFipsUtil(t *testing.T) {
+	t.Log("fipsutil.Enabled() is", Enabled())
+	t.Log("fipsutil.Only() is", Only())
+}
diff --git a/internal/utils/convert_test.go b/internal/utils/convert_test.go
deleted file mode 100644
index cc10037..0000000
--- a/internal/utils/convert_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package utils
-
-import (
-	"math"
-	"testing"
-
-	"github.com/stretchr/testify/require"
-)
-
-func TestMustUint64ConvertsValues(t *testing.T) {
-	require.Equal(t, uint64(0), MustUint64(0))
-	require.Equal(t, uint64(math.MaxInt64), MustUint64(math.MaxInt64))
-	require.Equal(t, uint64(42), MustUint64(42))
-}
-
-func TestMustUint64PanicsOnNegativeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint64(-1) })
-}
-
-func TestMustUint32ConvertsValues(t *testing.T) {
-	require.Equal(t, uint32(0), MustUint32(0))
-	require.Equal(t, uint32(math.MaxUint32), MustUint32(math.MaxUint32))
-	require.Equal(t, uint32(42), MustUint32(42))
-}
-
-func TestMustUint32PanicsOnNegativeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint32(-1) })
-}
-
-func TestMustUint32PanicsOnLargeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint32(math.MaxUint32 + 1) })
-}
-
-func TestMustUint16ConvertsValues(t *testing.T) {
-	require.Equal(t, uint16(0), MustUint16(0))
-	require.Equal(t, uint16(math.MaxUint16), MustUint16(math.MaxUint16))
-	require.Equal(t, uint16(42), MustUint16(42))
-}
-
-func TestMustUint16PanicsOnNegativeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint16(-1) })
-}
-
-func TestMustUint16PanicsOnLargeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint16(math.MaxUint16 + 1) })
-}
-
-func TestMustUint8ConvertsValues(t *testing.T) {
-	require.Equal(t, uint8(0), MustUint8(0))
-	require.Equal(t, uint8(math.MaxUint8), MustUint8(math.MaxUint8))
-	require.Equal(t, uint8(42), MustUint8(42))
-}
-
-func TestMustUint8PanicsOnNegativeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint8(-1) })
-}
-
-func TestMustUint8PanicsOnLargeValue(t *testing.T) {
-	require.Panics(t, func() { MustUint8(math.MaxUint8 + 1) })
-}
diff --git a/internal/utils/io_test.go b/internal/utils/io_test.go
index df69a4d..d1f29e2 100644
--- a/internal/utils/io_test.go
+++ b/internal/utils/io_test.go
@@ -40,7 +40,7 @@ func TestReadFile(t *testing.T) {
 
 // Set content to be read from mock STDIN
 func setStdinContent(t *testing.T, content string) (cleanup func()) {
-	f, err := os.CreateTemp(t.TempDir(), "utils-read-test")
+	f, err := os.CreateTemp("" /* dir */, "utils-read-test")
 	require.NoError(t, err)
 	_, err = f.WriteString(content)
 	require.NoError(t, err)
@@ -70,7 +70,7 @@ func TestReadFromStdin(t *testing.T) {
 // Sets STDIN to a file that is already closed, and thus fails
 // to be read from.
 func setFailingStdin(t *testing.T) (cleanup func()) {
-	f, err := os.CreateTemp(t.TempDir(), "utils-read-test")
+	f, err := os.CreateTemp("" /* dir */, "utils-read-test")
 	require.NoError(t, err)
 	err = f.Close()
 	require.NoError(t, err)
@@ -134,7 +134,11 @@ func TestReadPasswordFromStdin(t *testing.T) {
 }
 
 func TestWriteFile(t *testing.T) {
-	tmpDir := t.TempDir()
+	tmpDir, err := os.MkdirTemp(os.TempDir(), "go-tests")
+	require.NoError(t, err)
+	t.Cleanup(func() {
+		os.RemoveAll(tmpDir)
+	})
 
 	type args struct {
 		filename string
diff --git a/jose/encrypt_test.go b/jose/encrypt_test.go
index c9a7387..474794e 100644
--- a/jose/encrypt_test.go
+++ b/jose/encrypt_test.go
@@ -14,9 +14,7 @@ import (
 
 	jose "github.com/go-jose/go-jose/v3"
 	"github.com/pkg/errors"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-
+	"github.com/smallstep/assert"
 	"go.step.sm/crypto/randutil"
 )
 
@@ -350,7 +348,7 @@ func TestDecrypt(t *testing.T) {
 	data := []byte("the-plain-data")
 	jwe := mustEncryptData(t, data, testPassword)
 	s, err := jwe.CompactSerialize()
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	encryptedData := []byte(s)
 
 	// Create wrong encrypted data
diff --git a/jose/generate_test.go b/jose/generate_test.go
index 2f5ff3d..cf27c34 100644
--- a/jose/generate_test.go
+++ b/jose/generate_test.go
@@ -17,9 +17,7 @@ import (
 	"testing"
 
 	jose "github.com/go-jose/go-jose/v3"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-
+	"github.com/smallstep/assert"
 	"go.step.sm/crypto/pemutil"
 	"go.step.sm/crypto/x25519"
 )
@@ -140,29 +138,29 @@ func TestGenerateJWK(t *testing.T) {
 			}
 			assert.NoError(t, err)
 			if tc.kid != "" {
-				assert.Equal(t, tc.kid, jwk.KeyID)
+				assert.Equals(t, tc.kid, jwk.KeyID)
 			}
-			assert.Equal(t, tc.expectedAlg, jwk.Algorithm)
-			assert.IsType(t, tc.expectedType, jwk.Key)
+			assert.Equals(t, tc.expectedAlg, jwk.Algorithm)
+			assert.Type(t, tc.expectedType, jwk.Key)
 
 			switch key := jwk.Key.(type) {
 			case *ecdsa.PrivateKey:
 				switch tc.expectedSize {
 				case 256:
-					assert.Equal(t, elliptic.P256(), key.Curve)
+					assert.Equals(t, elliptic.P256(), key.Curve)
 				case 384:
-					assert.Equal(t, elliptic.P384(), key.Curve)
+					assert.Equals(t, elliptic.P384(), key.Curve)
 				case 521:
-					assert.Equal(t, elliptic.P521(), key.Curve)
+					assert.Equals(t, elliptic.P521(), key.Curve)
 				default:
 					t.Errorf("unexpected size %d", tc.expectedSize)
 				}
 			case *rsa.PrivateKey:
-				assert.Equal(t, tc.expectedSize, key.N.BitLen())
+				assert.Equals(t, tc.expectedSize, key.N.BitLen())
 			case ed25519.PrivateKey:
-				assert.Equal(t, tc.expectedSize, len(key))
+				assert.Equals(t, tc.expectedSize, len(key))
 			case []byte:
-				assert.Equal(t, tc.expectedSize, len(key))
+				assert.Equals(t, tc.expectedSize, len(key))
 			default:
 				t.Errorf("unexpected key type %T", key)
 			}
@@ -215,9 +213,9 @@ func TestKeyUsageForCert(t *testing.T) {
 	for _, tt := range tests {
 		use, err := keyUsageForCert(tt.Cert)
 		if tt.ExpectErr != nil {
-			assert.Equal(t, tt.ExpectErr, err)
+			assert.Equals(t, tt.ExpectErr, err)
 		} else {
-			assert.Equal(t, tt.ExpectUse, use)
+			assert.Equals(t, tt.ExpectUse, use)
 		}
 	}
 }
@@ -226,12 +224,12 @@ func TestGenerateJWKFromPEM(t *testing.T) {
 	t.Parallel()
 	mustKey := func(filename string) interface{} {
 		key, err := pemutil.Read(filename)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		return key
 	}
 	mustCert := func(filename string) *x509.Certificate {
 		cert, err := pemutil.ReadCertificate(filename)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		return cert
 	}
 	type args struct {
@@ -301,6 +299,7 @@ func TestGenerateJWKFromPEM(t *testing.T) {
 		{"fail no subtle", args{"testdata/rsa2048.crt", false}, nil, true},
 	}
 	for _, tt := range tests {
+		tt := tt
 		t.Run(tt.name, func(t *testing.T) {
 			t.Parallel()
 			got, err := GenerateJWKFromPEM(tt.args.filename, tt.args.subtle)
@@ -358,13 +357,13 @@ func TestGenerateJWKFromPEMSubtle(t *testing.T) {
 
 			jwk, err := GenerateJWKFromPEM(f.Name(), tt.Subtle)
 			if tt.ExpectErr != nil {
-				assert.Equal(t, tt.ExpectErr, err)
+				assert.Equals(t, tt.ExpectErr, err)
 				return
 			}
 			assert.NoError(t, err)
-			assert.Equal(t, tt.ExpectSig, jwk.Use)
-			assert.Equal(t, ES256, jwk.Algorithm)
-			assert.Equal(t, 1, len(jwk.Certificates))
+			assert.Equals(t, tt.ExpectSig, jwk.Use)
+			assert.Equals(t, ES256, jwk.Algorithm)
+			assert.Equals(t, 1, len(jwk.Certificates))
 		})
 	}
 }
@@ -383,7 +382,7 @@ func newCert(t *testing.T, keyUsage x509.KeyUsage) []byte {
 }
 
 func tempFile(t *testing.T) (*os.File, func()) {
-	f, err := os.CreateTemp(t.TempDir(), "jose-generate-test")
+	f, err := os.CreateTemp("", "jose-generate-test")
 	assert.NoError(t, err)
 	return f, func() {
 		f.Close()
diff --git a/jose/parse_test.go b/jose/parse_test.go
index b25a51e..78bcd76 100644
--- a/jose/parse_test.go
+++ b/jose/parse_test.go
@@ -20,9 +20,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/stretchr/testify/assert"
+	"github.com/smallstep/assert"
 	"github.com/stretchr/testify/require"
-
 	"go.step.sm/crypto/pemutil"
 	"go.step.sm/crypto/x25519"
 )
@@ -118,24 +117,25 @@ func validateReadKey(t *testing.T, fn, pass string, td testdata) {
 	} else {
 		jwk, err = ReadKey(fn)
 	}
-	require.NoError(t, err)
-	require.NoError(t, ValidateJWK(jwk))
+	assert.NoError(t, err)
+
+	assert.NoError(t, ValidateJWK(jwk))
 
 	switch td.typ {
 	case ecdsaPublicKey:
-		assert.IsType(t, &ecdsa.PublicKey{}, jwk.Key)
+		assert.Type(t, &ecdsa.PublicKey{}, jwk.Key)
 	case ecdsaPrivateKey:
-		assert.IsType(t, &ecdsa.PrivateKey{}, jwk.Key)
+		assert.Type(t, &ecdsa.PrivateKey{}, jwk.Key)
 	case ed25519PublicKey:
-		assert.IsType(t, ed25519.PublicKey{}, jwk.Key)
+		assert.Type(t, ed25519.PublicKey{}, jwk.Key)
 	case ed25519PrivateKey:
-		assert.IsType(t, ed25519.PrivateKey{}, jwk.Key)
+		assert.Type(t, ed25519.PrivateKey{}, jwk.Key)
 	case rsaPublicKey:
-		assert.IsType(t, &rsa.PublicKey{}, jwk.Key)
+		assert.Type(t, &rsa.PublicKey{}, jwk.Key)
 	case rsaPrivateKey:
-		assert.IsType(t, &rsa.PrivateKey{}, jwk.Key)
+		assert.Type(t, &rsa.PrivateKey{}, jwk.Key)
 	case octKey:
-		assert.IsType(t, []byte{}, jwk.Key)
+		assert.Type(t, []byte{}, jwk.Key)
 	default:
 		t.Errorf("type %T not supported", jwk.Key)
 	}
@@ -143,24 +143,26 @@ func validateReadKey(t *testing.T, fn, pass string, td testdata) {
 	if jwk.IsPublic() == false && jwk.KeyID != "" {
 		hash, err := jwk.Thumbprint(crypto.SHA256)
 		assert.NoError(t, err)
-		assert.Equal(t, base64.RawURLEncoding.EncodeToString(hash), jwk.KeyID)
+		assert.Equals(t, base64.RawURLEncoding.EncodeToString(hash), jwk.KeyID)
 	}
 
 	if td.encrypted {
 		jwkPriv, err := ReadKey(strings.Replace(fn, ".enc", "", 1))
 		assert.NoError(t, err)
-		assert.Equal(t, jwkPriv, jwk)
+		assert.Equals(t, jwkPriv, jwk)
 	}
 }
 
 func TestReadKey(t *testing.T) {
 	for fn, td := range files {
+		fn, td := fn, td
 		t.Run(fn, func(t *testing.T) {
 			validateReadKey(t, fn, "password", td)
 		})
 	}
 
 	for fn, td := range pemFiles {
+		fn, td := fn, td
 		t.Run(fn, func(t *testing.T) {
 			validateReadKey(t, fn, "mypassword", td)
 		})
@@ -173,9 +175,9 @@ func TestReadKey(t *testing.T) {
 
 func TestReadKey_https(t *testing.T) {
 	ok, err := os.ReadFile("testdata/okp.pub.json")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	key, err := base64.RawURLEncoding.DecodeString("L4WYxHsMVaspyhWuSp84v2meEYMEUdYnrn-w-jqP6iw")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		switch r.RequestURI {
@@ -240,11 +242,11 @@ func TestReadKey_https(t *testing.T) {
 
 func TestReadKeyPasswordFile(t *testing.T) {
 	jwk, err := ReadKey("testdata/oct.txt", WithAlg("HS256"), WithUse("sig"), WithKid("the-kid"))
-	require.NoError(t, err)
-	assert.Equal(t, []byte("a true random password"), jwk.Key)
-	assert.Equal(t, HS256, jwk.Algorithm)
-	assert.Equal(t, "sig", jwk.Use)
-	assert.Equal(t, "the-kid", jwk.KeyID)
+	assert.FatalError(t, err)
+	assert.Equals(t, []byte("a true random password"), jwk.Key)
+	assert.Equals(t, HS256, jwk.Algorithm)
+	assert.Equals(t, "sig", jwk.Use)
+	assert.Equals(t, "the-kid", jwk.KeyID)
 }
 
 func TestParseKey(t *testing.T) {
@@ -271,15 +273,15 @@ func TestParseKey(t *testing.T) {
 	octKey := fixJWK(mustGenerateJWK(t, "oct", "", "HS256", "sig", "", 64))
 
 	encKey, err := EncryptJWK(edKey, testPassword)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	encKeyCompact, err := encKey.CompactSerialize()
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	pemKey, err := pemutil.Read("../pemutil/testdata/pkcs8/openssl.ed25519.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	ecKey.KeyID, err = Thumbprint(ecKey)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	type args struct {
 		b    []byte
@@ -363,6 +365,7 @@ func TestParseKey(t *testing.T) {
 		{"failOCTMissingOptions", args{testPassword, nil}, nil, true},
 	}
 	for _, tt := range tests {
+		tt := tt
 		t.Run(tt.name, func(t *testing.T) {
 			t.Parallel()
 			got, err := ParseKey(tt.args.b, tt.args.opts...)
@@ -391,10 +394,10 @@ func TestParseKey(t *testing.T) {
 
 func TestParseKeyPemutilPromptPassword(t *testing.T) {
 	pemKey, err := pemutil.Read("../pemutil/testdata/pkcs8/openssl.ed25519.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	pemBytes, err := os.ReadFile("../pemutil/testdata/pkcs8/openssl.ed25519.enc.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	tmp0 := pemutil.PromptPassword
 	tmp1 := PromptPassword
@@ -440,35 +443,35 @@ func TestParseKeyPemutilPromptPassword(t *testing.T) {
 func TestReadKeySet(t *testing.T) {
 	jwk, err := ReadKeySet("testdata/jwks.json", WithKid("qiCJG7r2L80rmWRrZMPfpanQHmZRcncOG7A7MBWn9qM"))
 	assert.NoError(t, err)
-	assert.IsType(t, ed25519.PublicKey{}, jwk.Key)
-	assert.Equal(t, "qiCJG7r2L80rmWRrZMPfpanQHmZRcncOG7A7MBWn9qM", jwk.KeyID)
+	assert.Type(t, ed25519.PublicKey{}, jwk.Key)
+	assert.Equals(t, "qiCJG7r2L80rmWRrZMPfpanQHmZRcncOG7A7MBWn9qM", jwk.KeyID)
 
 	jwk, err = ReadKeySet("testdata/jwks.json", WithKid("V93A-Yh7Bhw1W2E0igFciviJzX4PXPswoVgriehm9Co"))
 	assert.NoError(t, err)
-	assert.IsType(t, &ecdsa.PublicKey{}, jwk.Key)
-	assert.Equal(t, "V93A-Yh7Bhw1W2E0igFciviJzX4PXPswoVgriehm9Co", jwk.KeyID)
+	assert.Type(t, &ecdsa.PublicKey{}, jwk.Key)
+	assert.Equals(t, "V93A-Yh7Bhw1W2E0igFciviJzX4PXPswoVgriehm9Co", jwk.KeyID)
 
 	jwk, err = ReadKeySet("testdata/jwks.json", WithKid("duplicated"))
 	assert.Error(t, err)
-	assert.Equal(t, "multiple keys with kid duplicated have been found on testdata/jwks.json", err.Error())
+	assert.Equals(t, "multiple keys with kid duplicated have been found on testdata/jwks.json", err.Error())
 	assert.Nil(t, jwk)
 
 	jwk, err = ReadKeySet("testdata/jwks.json", WithKid("missing"))
 	assert.Error(t, err)
-	assert.Equal(t, "cannot find key with kid missing on testdata/jwks.json", err.Error())
+	assert.Equals(t, "cannot find key with kid missing on testdata/jwks.json", err.Error())
 	assert.Nil(t, jwk)
 
 	jwk, err = ReadKeySet("testdata/empty.json", WithKid("missing"))
 	assert.Error(t, err)
-	assert.Equal(t, "cannot find key with kid missing on testdata/empty.json", err.Error())
+	assert.Equals(t, "cannot find key with kid missing on testdata/empty.json", err.Error())
 	assert.Nil(t, jwk)
 }
 
 func TestReadKeySet_https(t *testing.T) {
 	ok, err := os.ReadFile("testdata/jwks.json")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	key, err := base64.RawURLEncoding.DecodeString("L4WYxHsMVaspyhWuSp84v2meEYMEUdYnrn-w-jqP6iw")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		switch r.RequestURI {
@@ -533,17 +536,17 @@ func TestReadKeySet_https(t *testing.T) {
 
 func TestGuessJWKAlgorithm(t *testing.T) {
 	p256, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	p384, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	p521, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	rsa2k, err := rsa.GenerateKey(rand.Reader, 2048)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	edPub, edPriv, err := ed25519.GenerateKey(rand.Reader)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	xPub, xPriv, err := x25519.GenerateKey(rand.Reader)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	tests := []struct {
 		jwk      *JSONWebKey
@@ -579,14 +582,14 @@ func TestGuessJWKAlgorithm(t *testing.T) {
 	assert.NoError(t, err)
 	jwk := &JSONWebKey{Key: []byte("password")}
 	guessJWKAlgorithm(ctx, jwk)
-	assert.Equal(t, HS256, jwk.Algorithm)
+	assert.Equals(t, HS256, jwk.Algorithm)
 
 	// With algorithm set
 	ctx, err = new(context).apply(WithAlg(HS256))
 	assert.NoError(t, err)
 	jwk = &JSONWebKey{Key: []byte("password"), Algorithm: HS384}
 	guessJWKAlgorithm(ctx, jwk)
-	assert.Equal(t, HS384, jwk.Algorithm)
+	assert.Equals(t, HS384, jwk.Algorithm)
 
 	// With no defaults
 	ctx, err = new(context).apply(WithNoDefaults(true))
@@ -594,48 +597,48 @@ func TestGuessJWKAlgorithm(t *testing.T) {
 	jwk = mustGenerateJWK(t, "EC", "P-256", "ES256", "sig", "", 0)
 	jwk.Algorithm = ""
 	guessJWKAlgorithm(ctx, jwk)
-	assert.Equal(t, ES256, jwk.Algorithm)
+	assert.Equals(t, ES256, jwk.Algorithm)
 
 	pub := jwk.Public()
 	pub.Algorithm = ""
 	guessJWKAlgorithm(ctx, &pub)
-	assert.Equal(t, ES256, pub.Algorithm)
+	assert.Equals(t, ES256, pub.Algorithm)
 
 	jwk = mustGenerateJWK(t, "OKP", "Ed25519", "EdDSA", "sig", "", 0)
 	jwk.Algorithm = ""
 	guessJWKAlgorithm(ctx, jwk)
-	assert.Equal(t, EdDSA, jwk.Algorithm)
+	assert.Equals(t, EdDSA, jwk.Algorithm)
 
 	pub = jwk.Public()
 	pub.Algorithm = ""
 	guessJWKAlgorithm(ctx, &pub)
-	assert.Equal(t, EdDSA, pub.Algorithm)
+	assert.Equals(t, EdDSA, pub.Algorithm)
 
 	jwk = &JSONWebKey{Key: xPriv, Algorithm: "", Use: "sig"}
 	guessJWKAlgorithm(ctx, jwk)
-	assert.Equal(t, XEdDSA, jwk.Algorithm)
+	assert.Equals(t, XEdDSA, jwk.Algorithm)
 
 	jwk = &JSONWebKey{Key: xPub, Algorithm: "", Use: "sig"}
 	guessJWKAlgorithm(ctx, jwk)
-	assert.Equal(t, XEdDSA, jwk.Algorithm)
+	assert.Equals(t, XEdDSA, jwk.Algorithm)
 
 	// Defaults
 	for _, tc := range tests {
 		guessJWKAlgorithm(new(context), tc.jwk)
-		assert.Equal(t, tc.expected, tc.jwk.Algorithm)
+		assert.Equals(t, tc.expected, tc.jwk.Algorithm)
 	}
 }
 
 func TestParseKeySet(t *testing.T) {
 	b, err := os.ReadFile("testdata/jwks.json")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	key, err := base64.RawURLEncoding.DecodeString("L4WYxHsMVaspyhWuSp84v2meEYMEUdYnrn-w-jqP6iw")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	jwe := mustEncryptData(t, b, testPassword)
 	encryptedJSON := []byte(jwe.FullSerialize())
 	encryptedCompact, err := jwe.CompactSerialize()
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	type args struct {
 		b    []byte
@@ -722,7 +725,7 @@ func Test_guessKeyType(t *testing.T) {
 	octHS384 := mustGenerateJWK(t, "oct", "", "HS384", "sig", "", 64)
 
 	rsaPEM, err := os.ReadFile("../pemutil/testdata/openssl.p256.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	type args struct {
 		ctx  *context
diff --git a/jose/validate_test.go b/jose/validate_test.go
index 43fa922..d09710b 100644
--- a/jose/validate_test.go
+++ b/jose/validate_test.go
@@ -12,9 +12,7 @@ import (
 	"testing"
 
 	"github.com/pkg/errors"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-
+	"github.com/smallstep/assert"
 	"go.step.sm/crypto/keyutil"
 	"go.step.sm/crypto/pemutil"
 )
@@ -98,7 +96,7 @@ func Test_validateX5(t *testing.T) {
 		},
 		"fail/bad-key": func() test {
 			certs, err := pemutil.ReadCertificateBundle(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return test{
 				certs: certs,
 				key:   nil,
@@ -107,9 +105,9 @@ func Test_validateX5(t *testing.T) {
 		},
 		"fail/cert-not-approved-for-digital-signature": func() test {
 			certs, err := pemutil.ReadCertificateBundle(badCertFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			k, err := pemutil.Read(badKeyFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return test{
 				certs: certs,
 				key:   k,
@@ -119,9 +117,9 @@ func Test_validateX5(t *testing.T) {
 		},
 		"ok": func() test {
 			certs, err := pemutil.ReadCertificateBundle(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			k, err := pemutil.Read(keyFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return test{
 				certs: certs,
 				key:   k,
@@ -133,7 +131,7 @@ func Test_validateX5(t *testing.T) {
 			tc := run()
 			if err := validateX5(tc.certs, tc.key); err != nil {
 				if assert.NotNil(t, tc.err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.Nil(t, tc.err)
@@ -159,11 +157,11 @@ func TestValidateX5T(t *testing.T) {
 		},
 		"ok": func() test {
 			certs, err := pemutil.ReadCertificateBundle(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			k, err := pemutil.Read(keyFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			cert, err := pemutil.ReadCertificate(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			// x5t is the base64 URL encoded SHA1 thumbprint
 			// (see https://tools.ietf.org/html/rfc7515#section-4.1.7)
 			// nolint:gosec // RFC 7515 - X.509 Certificate SHA-1 Thumbprint
@@ -176,14 +174,14 @@ func TestValidateX5T(t *testing.T) {
 		},
 		"ok/opaque": func() test {
 			certs, err := pemutil.ReadCertificateBundle(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			k, err := pemutil.Read(keyFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			sig, ok := k.(crypto.Signer)
 			assert.True(t, ok)
 			op := NewOpaqueSigner(sig)
 			cert, err := pemutil.ReadCertificate(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			// x5t is the base64 URL encoded SHA1 thumbprint
 			// (see https://tools.ietf.org/html/rfc7515#section-4.1.7)
 			// nolint:gosec // RFC 7515 - X.509 Certificate SHA-1 Thumbprint
@@ -200,11 +198,11 @@ func TestValidateX5T(t *testing.T) {
 			tc := run()
 			if fingerprint, err := ValidateX5T(tc.certs, tc.key); err != nil {
 				if assert.NotNil(t, tc.err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.Nil(t, tc.err)
-				assert.Equal(t, tc.fp, fingerprint)
+				assert.Equals(t, tc.fp, fingerprint)
 			}
 		})
 	}
@@ -226,9 +224,9 @@ func TestValidateX5C(t *testing.T) {
 		},
 		"ok": func() test {
 			certs, err := pemutil.ReadCertificateBundle(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			k, err := pemutil.Read(keyFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return test{
 				certs: certs,
 				key:   k,
@@ -236,9 +234,9 @@ func TestValidateX5C(t *testing.T) {
 		},
 		"ok/opaque": func() test {
 			certs, err := pemutil.ReadCertificateBundle(certFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			k, err := pemutil.Read(keyFile)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			sig, ok := k.(crypto.Signer)
 			assert.True(t, ok)
 			op := NewOpaqueSigner(sig)
@@ -253,11 +251,11 @@ func TestValidateX5C(t *testing.T) {
 			tc := run()
 			if certs, err := ValidateX5C(tc.certs, tc.key); err != nil {
 				if assert.NotNil(t, tc.err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.Nil(t, tc.err)
-				assert.Equal(t, []string{`MIIDCTCCAfGgAwIBAgIQIdY8a5pFZ/FGUowvuGdJvTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwR0ZXN0MB4XDTIwMDQyMTA0MDg0MFoXDTIwMDQyMjA0MDg0MFowDzENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0zsTneONS0eNto7LMlD8GtcUYXqILSEWD07v0HgbIguBT+yC8BozpAT3lyB+oBBZkFLzfEHAteULngPwlq0R5hsEZJ6lcL1Z9WXwyLE4nkEndIPMA+zQmHnOzoqgKy7pIqUnFqSGXtGp384fFF3Y0/qjeFciLnmf+Wn0PneaToY1rDj2Eb9sFf5UDiVaSLT1NzpSyXOS5uGbGplPe+WE8uEb3u3Vg2VGbEPau2l5MPYroCwSyxqlpKsmzJ558uvjQ7KpRExSNdb6f0iRfdRMbw3LahrxhbKV1mmM6GD5onmbgBCZpw5htOJj1MzVFZOdnoTHmMl/Y/IUdMjv0jG/UCAwEAAaNhMF8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUXlQCQL6RymQZnvqY15F/GlE3H4UwDwYDVR0RBAgwBoIEdGVzdDANBgkqhkiG9w0BAQsFAAOCAQEArVmOL5L+NVsnCcUWfOVXQYg/6P8AGdPJBECk+BE5pbtMg0GuH5Ml/vCTBqD+diWC4O0TZDxPMhXH5Ehl+67hcqeu4riwB2WvvKOlAqHqIuqVDRHtxwknvS1efstBKVdDC6aAfIa5f2dmCSxvd8elpcnufEefLGALTSPxg4uMVvpfWUkkmpmvOUpI3gNrlvP2H4KZk7hKYz+J4x2jv2pdPWUAtt1U4M8oQ4BCPrrHSxznw2Q5mdCMIB64ZeYnZ+rAMQS6WnZy1fTC3d0pCs0UCXH5JefBpha1clqHDUkxHA6/1EYYsSlKGFaPEmfv2uw7MFz0o+yntG34KVdsC8HO3g==`}, certs)
+				assert.Equals(t, []string{`MIIDCTCCAfGgAwIBAgIQIdY8a5pFZ/FGUowvuGdJvTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwR0ZXN0MB4XDTIwMDQyMTA0MDg0MFoXDTIwMDQyMjA0MDg0MFowDzENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0zsTneONS0eNto7LMlD8GtcUYXqILSEWD07v0HgbIguBT+yC8BozpAT3lyB+oBBZkFLzfEHAteULngPwlq0R5hsEZJ6lcL1Z9WXwyLE4nkEndIPMA+zQmHnOzoqgKy7pIqUnFqSGXtGp384fFF3Y0/qjeFciLnmf+Wn0PneaToY1rDj2Eb9sFf5UDiVaSLT1NzpSyXOS5uGbGplPe+WE8uEb3u3Vg2VGbEPau2l5MPYroCwSyxqlpKsmzJ558uvjQ7KpRExSNdb6f0iRfdRMbw3LahrxhbKV1mmM6GD5onmbgBCZpw5htOJj1MzVFZOdnoTHmMl/Y/IUdMjv0jG/UCAwEAAaNhMF8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUXlQCQL6RymQZnvqY15F/GlE3H4UwDwYDVR0RBAgwBoIEdGVzdDANBgkqhkiG9w0BAQsFAAOCAQEArVmOL5L+NVsnCcUWfOVXQYg/6P8AGdPJBECk+BE5pbtMg0GuH5Ml/vCTBqD+diWC4O0TZDxPMhXH5Ehl+67hcqeu4riwB2WvvKOlAqHqIuqVDRHtxwknvS1efstBKVdDC6aAfIa5f2dmCSxvd8elpcnufEefLGALTSPxg4uMVvpfWUkkmpmvOUpI3gNrlvP2H4KZk7hKYz+J4x2jv2pdPWUAtt1U4M8oQ4BCPrrHSxznw2Q5mdCMIB64ZeYnZ+rAMQS6WnZy1fTC3d0pCs0UCXH5JefBpha1clqHDUkxHA6/1EYYsSlKGFaPEmfv2uw7MFz0o+yntG34KVdsC8HO3g==`}, certs)
 			}
 		})
 	}
diff --git a/keyutil/key_test.go b/keyutil/key_test.go
index 066c910..5d8f047 100644
--- a/keyutil/key_test.go
+++ b/keyutil/key_test.go
@@ -13,10 +13,9 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/stretchr/testify/require"
-	"golang.org/x/crypto/ssh"
-
+	"github.com/smallstep/assert"
 	"go.step.sm/crypto/x25519"
+	"golang.org/x/crypto/ssh"
 )
 
 const (
@@ -146,7 +145,7 @@ func TestPublicKey(t *testing.T) {
 	rsaKey := must(generateRSAKey(2048)).(*rsa.PrivateKey)
 	ed25519Key := must(generateOKPKey("Ed25519")).(ed25519.PrivateKey)
 	x25519Pub, x25519Priv, err := x25519.GenerateKey(rand.Reader)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	type args struct {
 		priv interface{}
@@ -566,21 +565,21 @@ func TestExtractKey(t *testing.T) {
 
 	b, _ := pem.Decode([]byte(testCRT))
 	cert, err := x509.ParseCertificate(b.Bytes)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	b, _ = pem.Decode([]byte(testCSR))
 	csr, err := x509.ParseCertificateRequest(b.Bytes)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	b, _ = pem.Decode([]byte(testSSHPubPEM))
 	sshKey, err := x509.ParsePKIXPublicKey(b.Bytes)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	sshPub, _, _, _, err := ssh.ParseAuthorizedKey([]byte(testSSHPub))
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	sshCert, _, _, _, err := ssh.ParseAuthorizedKey([]byte(testSSHCert))
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	type args struct {
 		in interface{}
diff --git a/minica/minica_test.go b/minica/minica_test.go
index d1846a9..e197476 100644
--- a/minica/minica_test.go
+++ b/minica/minica_test.go
@@ -12,11 +12,9 @@ import (
 	"testing"
 	"time"
 
-	"golang.org/x/crypto/ssh"
-
-	"go.step.sm/crypto/internal/utils"
 	"go.step.sm/crypto/keyutil"
 	"go.step.sm/crypto/x509util"
+	"golang.org/x/crypto/ssh"
 )
 
 type badSigner struct{}
@@ -381,8 +379,8 @@ func TestCA_SignSSH(t *testing.T) {
 			CertType:        ssh.UserCert,
 			KeyId:           "jane@test.com",
 			ValidPrincipals: []string{"jane"},
-			ValidAfter:      utils.MustUint64(time.Now().Unix()),
-			ValidBefore:     utils.MustUint64(time.Now().Add(time.Hour).Unix()),
+			ValidAfter:      uint64(time.Now().Unix()),
+			ValidBefore:     uint64(time.Now().Add(time.Hour).Unix()),
 		}}, ssh.UserCert, "jane", false},
 		{"ok infinity", mustCA(t), args{&ssh.Certificate{
 			Key:             publicKey,
diff --git a/nssdb/certificate_test.go b/nssdb/certificate_test.go
index 5b83d49..eaf6f4b 100644
--- a/nssdb/certificate_test.go
+++ b/nssdb/certificate_test.go
@@ -3,7 +3,6 @@ package nssdb
 import (
 	"context"
 	"crypto/x509"
-	"database/sql"
 	"os/exec"
 	"testing"
 
@@ -130,19 +129,6 @@ func TestNSSDB_AddCertificate(t *testing.T) {
 			pubKeyObj.ID = 0
 			assert.Equal(t, oldPubKeyObj, pubKeyObj)
 		})
-
-		t.Run(v.name("ok replace"), func(t *testing.T) {
-			certID, pubKeyID, err := db.AddCertificate(ctx, leafCrt, "name")
-			require.NoError(t, err)
-			assert.NotEqual(t, v.certID, certID)
-			assert.NotEqual(t, v.pubKeyID, pubKeyID)
-			_, err = db.GetObjectPublic(ctx, v.certID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-			_, err = db.GetObjectPublic(ctx, v.pubKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-			_, err = db.GetObjectPrivate(ctx, v.privateKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-		})
 	}
 }
 
@@ -181,16 +167,12 @@ func TestNSSDB_Import(t *testing.T) {
 			if err != nil {
 				t.Skip("pk1sign not installed")
 			}
-
 			db, dir := v.connectDir(t)
-			require.NoError(t, db.Reset(ctx))
-
 			_, _, _, err = db.Import(ctx, "leaf", leafCrt, leafKey)
 			require.NoError(t, err)
 
 			cmd := exec.Command(p, "-d", dir, "-k", "leaf", "-i", "README.md")
-			output, err := cmd.CombinedOutput()
-			assert.NoError(t, err, string(output))
+			assert.NoError(t, cmd.Run())
 		})
 	}
 }
@@ -210,68 +192,3 @@ func TestNSSDB_ListCertificateObjects(t *testing.T) {
 		})
 	}
 }
-
-func TestNSSDB_DeleteCertificatesByName(t *testing.T) {
-	ctx := context.Background()
-
-	for _, v := range nssVersions {
-		t.Run(v.name("ok"), func(t *testing.T) {
-			db := v.connect(t)
-
-			err := db.DeleteCertificatesByName(ctx, "leaf")
-			require.NoError(t, err)
-			_, err = db.GetObjectPublic(ctx, v.certID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-			_, err = db.GetObjectPublic(ctx, v.pubKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-			_, err = db.GetObjectPrivate(ctx, v.privateKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-		})
-
-		t.Run(v.name("ok nothing to do"), func(t *testing.T) {
-			db := v.connect(t)
-
-			err := db.DeleteCertificatesByName(ctx, "leafx")
-			require.NoError(t, err)
-			_, err = db.GetObjectPublic(ctx, v.certID)
-			assert.NoError(t, err)
-			_, err = db.GetObjectPublic(ctx, v.pubKeyID)
-			assert.NoError(t, err)
-			_, err = db.GetObjectPrivate(ctx, v.privateKeyID)
-			assert.NoError(t, err)
-		})
-	}
-}
-
-func TestNSSDB_DeleteCertificate(t *testing.T) {
-	ctx := context.Background()
-
-	for _, v := range nssVersions {
-		t.Run(v.name("ok"), func(t *testing.T) {
-			db := v.connect(t)
-
-			err := db.DeleteCertificate(ctx, v.certID)
-			require.NoError(t, err)
-			_, err = db.GetObjectPublic(ctx, v.certID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-			_, err = db.GetObjectPublic(ctx, v.pubKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-			_, err = db.GetObjectPrivate(ctx, v.privateKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-		})
-
-		t.Run(v.name("ok nothing to do"), func(t *testing.T) {
-			db := v.connect(t)
-
-			err := db.DeleteCertificate(ctx, 7)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-		})
-
-		t.Run(v.name("fail not a cert"), func(t *testing.T) {
-			db := v.connect(t)
-
-			err := db.DeleteCertificate(ctx, v.pubKeyID)
-			assert.Error(t, err)
-		})
-	}
-}
diff --git a/nssdb/keys_test.go b/nssdb/keys_test.go
index 5e3981d..820670f 100644
--- a/nssdb/keys_test.go
+++ b/nssdb/keys_test.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"crypto/ecdsa"
 	"crypto/elliptic"
-	"database/sql"
 	"encoding/hex"
 	"path/filepath"
 	"testing"
@@ -107,50 +106,5 @@ func TestNSSDB_AddPrivateKey(t *testing.T) {
 			privKeyObj.Metadata = nil
 			assert.Equal(t, oldKeyObj, privKeyObj)
 		})
-
-		t.Run(v.name("ok replace"), func(t *testing.T) {
-			db := v.connect(t)
-			privKeyID, err := db.AddPrivateKey(ctx, leafKey, "leaf", leafCrt.SubjectKeyId, "leaf")
-			require.NoError(t, err)
-			assert.NotEqual(t, v.privateKeyID, privKeyID)
-			_, err = db.GetObjectPrivate(ctx, v.privateKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-		})
-	}
-}
-
-func TestNSSDB_AddPublicKey(t *testing.T) {
-	ctx := context.Background()
-	for _, v := range nssVersions {
-		t.Run(v.name("ok"), func(t *testing.T) {
-			db := v.connect(t)
-			oldKeyObj, err := db.GetObjectPublic(ctx, v.pubKeyID)
-			require.NoError(t, err)
-			require.NoError(t, db.Reset(ctx))
-
-			pubKeyID, err := db.AddPublicKey(ctx, &leafKey.PublicKey, leafCrt.SubjectKeyId)
-			require.NoError(t, err)
-			assert.NotEmpty(t, pubKeyID)
-
-			pubKeyObj, err := db.GetObjectPublic(ctx, pubKeyID)
-			require.NoError(t, err)
-			assert.EqualValues(t, CKO_PUBLIC_KEY, pubKeyObj.ULongAttributes["CKA_CLASS"])
-			assert.Len(t, pubKeyObj.Metadata, 0)
-
-			// verify the public key imported by this library matches the public key
-			// imported with pk12util in everything besides the id
-			oldKeyObj.ID = 0
-			pubKeyObj.ID = 0
-			assert.Equal(t, oldKeyObj, pubKeyObj)
-		})
-
-		t.Run(v.name("ok replace"), func(t *testing.T) {
-			db := v.connect(t)
-			pubKeyID, err := db.AddPublicKey(ctx, &leafKey.PublicKey, leafCrt.SubjectKeyId)
-			require.NoError(t, err)
-			assert.NotEqual(t, v.pubKeyID, pubKeyID)
-			_, err = db.GetObjectPublic(ctx, v.pubKeyID)
-			assert.ErrorIs(t, err, sql.ErrNoRows)
-		})
 	}
 }
diff --git a/nssdb/nssdb_test.go b/nssdb/nssdb_test.go
index 8189690..e900cb2 100644
--- a/nssdb/nssdb_test.go
+++ b/nssdb/nssdb_test.go
@@ -403,48 +403,3 @@ func TestNSSDB_Reset(t *testing.T) {
 		})
 	}
 }
-
-func TestNSSDB_findByAttr(t *testing.T) {
-	ctx := context.Background()
-
-	for _, v := range nssVersions {
-		db := v.connect(t)
-
-		t.Run(v.name("ok certificate"), func(t *testing.T) {
-			ids, err := db.findByAttr(ctx, CKO_CERTIFICATE, "CKA_LABEL", []byte(leafCrt.Subject.CommonName))
-			require.NoError(t, err)
-			require.Len(t, ids, 1)
-			assert.Equal(t, v.certID, ids[0])
-		})
-
-		t.Run(v.name("ok public key"), func(t *testing.T) {
-			ids, err := db.findByAttr(ctx, CKO_PUBLIC_KEY, "CKA_ID", leafCrt.SubjectKeyId)
-			require.NoError(t, err)
-			require.Len(t, ids, 1)
-			assert.Equal(t, v.pubKeyID, ids[0])
-		})
-
-		t.Run(v.name("ok private key"), func(t *testing.T) {
-			ids, err := db.findByAttr(ctx, CKO_PRIVATE_KEY, "CKA_ID", leafCrt.SubjectKeyId)
-			require.NoError(t, err)
-			require.Len(t, ids, 1)
-			assert.Equal(t, v.privateKeyID, ids[0])
-		})
-
-		t.Run(v.name("not found"), func(t *testing.T) {
-			ids, err := db.findByAttr(ctx, CKO_PRIVATE_KEY, "CKA_ID", []byte{0x04})
-			require.NoError(t, err)
-			assert.Len(t, ids, 0)
-		})
-
-		t.Run(v.name("unsupported attribute"), func(t *testing.T) {
-			_, err := db.findByAttr(ctx, CKO_CERTIFICATE, "CKA_NOPE", []byte{0x01})
-			assert.Error(t, err)
-		})
-
-		t.Run(v.name("unsupported class"), func(t *testing.T) {
-			_, err := db.findByAttr(ctx, CKO_SECRET_KEY, "CKA_ID", []byte{0x01})
-			assert.Error(t, err)
-		})
-	}
-}
diff --git a/pemutil/pem_test.go b/pemutil/pem_test.go
index 11ba4f5..65dcd9e 100644
--- a/pemutil/pem_test.go
+++ b/pemutil/pem_test.go
@@ -20,12 +20,10 @@ import (
 	"testing"
 
 	"github.com/pkg/errors"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"golang.org/x/crypto/ssh"
-
+	"github.com/smallstep/assert"
 	"go.step.sm/crypto/keyutil"
 	"go.step.sm/crypto/x25519"
+	"golang.org/x/crypto/ssh"
 )
 
 type keyType int
@@ -162,21 +160,21 @@ func TestRead(t *testing.T) {
 
 			switch td.typ {
 			case ecdsaPublicKey:
-				assert.IsType(t, &ecdsa.PublicKey{}, key)
+				assert.Type(t, &ecdsa.PublicKey{}, key)
 			case ecdsaPrivateKey:
-				assert.IsType(t, &ecdsa.PrivateKey{}, key)
+				assert.Type(t, &ecdsa.PrivateKey{}, key)
 			case ed25519PublicKey:
-				assert.IsType(t, ed25519.PublicKey{}, key)
+				assert.Type(t, ed25519.PublicKey{}, key)
 			case ed25519PrivateKey:
-				assert.IsType(t, ed25519.PrivateKey{}, key)
+				assert.Type(t, ed25519.PrivateKey{}, key)
 			case rsaPublicKey:
-				assert.IsType(t, &rsa.PublicKey{}, key)
+				assert.Type(t, &rsa.PublicKey{}, key)
 			case rsaPrivateKey:
-				assert.IsType(t, &rsa.PrivateKey{}, key)
+				assert.Type(t, &rsa.PrivateKey{}, key)
 			case x25519PublicKey:
-				assert.IsType(t, x25519.PublicKey{}, key)
+				assert.Type(t, x25519.PublicKey{}, key)
 			case x25519PrivateKey:
-				assert.IsType(t, x25519.PrivateKey{}, key)
+				assert.Type(t, x25519.PrivateKey{}, key)
 			default:
 				t.Errorf("type %T not supported", key)
 			}
@@ -185,7 +183,7 @@ func TestRead(t *testing.T) {
 			if td.encrypted {
 				k, err := Read(strings.Replace(fn, ".enc", "", 1))
 				assert.NoError(t, err)
-				assert.Equal(t, k, key)
+				assert.Equals(t, k, key)
 			}
 
 			// Check against public
@@ -198,7 +196,7 @@ func TestRead(t *testing.T) {
 				assert.NoError(t, err)
 
 				if pk, ok := key.(crypto.Signer); ok {
-					assert.Equal(t, k, pk.Public())
+					assert.Equals(t, k, pk.Public())
 
 					var signature, digest []byte
 					message := []byte("message")
@@ -258,11 +256,11 @@ func TestParseCertificate(t *testing.T) {
 			crt, err := ParseCertificate(b)
 			if tc.err != nil {
 				if assert.Error(t, err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.NoError(t, err)
-				assert.IsType(t, &x509.Certificate{}, crt)
+				assert.Type(t, &x509.Certificate{}, crt)
 			}
 		})
 	}
@@ -292,11 +290,11 @@ func TestReadCertificate(t *testing.T) {
 			crt, err := ReadCertificate(tc.fn, tc.opts...)
 			if tc.err != nil {
 				if assert.Error(t, err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.NoError(t, err)
-				assert.IsType(t, &x509.Certificate{}, crt)
+				assert.Type(t, &x509.Certificate{}, crt)
 			}
 		})
 	}
@@ -325,13 +323,13 @@ func TestReadCertificateBundle(t *testing.T) {
 			certs, err := ReadCertificateBundle(tc.fn)
 			if tc.err != nil {
 				if assert.Error(t, err, tc.fn, "- expected error but got nil") {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.NoError(t, err)
-				assert.Len(t, certs, tc.len, tc.fn)
+				assert.Len(t, tc.len, certs, tc.fn)
 				for i := range certs {
-					assert.IsType(t, &x509.Certificate{}, certs[i])
+					assert.Type(t, &x509.Certificate{}, certs[i])
 				}
 			}
 		})
@@ -366,13 +364,13 @@ func TestParseCertificateBundle(t *testing.T) {
 			certs, err := ParseCertificateBundle(b)
 			if tc.err != nil {
 				if assert.Error(t, err, tc.fn, "- expected error but got nil") {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.NoError(t, err)
-				assert.Len(t, certs, tc.len, tc.fn)
+				assert.Len(t, tc.len, certs, tc.fn)
 				for i := range certs {
-					assert.IsType(t, &x509.Certificate{}, certs[i])
+					assert.Type(t, &x509.Certificate{}, certs[i])
 				}
 			}
 		})
@@ -389,7 +387,7 @@ func TestParse(t *testing.T) {
 	tests := map[string]func(t *testing.T) *ParseTest{
 		"success-ecdsa-public-key": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/openssl.p256.pub.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    nil,
@@ -398,7 +396,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-rsa-public-key": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/openssl.rsa1024.pub.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    nil,
@@ -407,7 +405,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-rsa-private-key": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/openssl.rsa1024.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    nil,
@@ -416,7 +414,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-ecdsa-private-key": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/openssl.p256.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    nil,
@@ -425,7 +423,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-ed25519-private-key": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/pkcs8/openssl.ed25519.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    nil,
@@ -434,7 +432,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-ed25519-enc-private-key": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/pkcs8/openssl.ed25519.enc.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    []Options{WithPassword([]byte("mypassword"))},
@@ -443,7 +441,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-x509-crt": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/ca.crt")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    nil,
@@ -452,7 +450,7 @@ func TestParse(t *testing.T) {
 		},
 		"success-x509-crt-trim-spaces": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/ca.crt")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			b = append(b, []byte(" \n \n ")...)
 			return &ParseTest{
 				in:      b,
@@ -462,7 +460,7 @@ func TestParse(t *testing.T) {
 		},
 		"fail-options": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/ca.crt")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			err = errors.New("an error")
 			return &ParseTest{
 				in:      b,
@@ -473,7 +471,7 @@ func TestParse(t *testing.T) {
 		},
 		"fail-password": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/openssl.p256.enc.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    []Options{WithPassword([]byte("badpassword"))},
@@ -483,7 +481,7 @@ func TestParse(t *testing.T) {
 		},
 		"fail-pkcs8-password": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/pkcs8/openssl.ed25519.enc.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    []Options{WithPassword([]byte("badpassword"))},
@@ -493,7 +491,7 @@ func TestParse(t *testing.T) {
 		},
 		"fail-type": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/openssl.p256.pub.pem")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			b = bytes.ReplaceAll(b, []byte("PUBLIC KEY"), []byte("EC PUBLIC KEY"))
 			return &ParseTest{
 				in:      b,
@@ -504,7 +502,7 @@ func TestParse(t *testing.T) {
 		},
 		"fail-nebula-pub-size": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/badnebula.pub")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    []Options{},
@@ -514,7 +512,7 @@ func TestParse(t *testing.T) {
 		},
 		"fail-nebula-key-size": func(t *testing.T) *ParseTest {
 			b, err := os.ReadFile("testdata/badnebula.key")
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return &ParseTest{
 				in:      b,
 				opts:    []Options{},
@@ -530,11 +528,11 @@ func TestParse(t *testing.T) {
 			i, err := Parse(tc.in, tc.opts...)
 			if err != nil {
 				if assert.NotNil(t, tc.err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				if assert.Nil(t, tc.err) {
-					assert.IsType(t, i, tc.cmpType)
+					assert.Type(t, i, tc.cmpType)
 				}
 			}
 		})
@@ -636,12 +634,12 @@ func TestSerialize(t *testing.T) {
 
 	for name, test := range tests {
 		if _, err := os.Stat("./test.key"); err == nil {
-			require.NoError(t, os.Remove("./test.key"))
+			assert.FatalError(t, os.Remove("./test.key"))
 		}
 		t.Logf("Running test case: %s", name)
 
 		in, err := test.in()
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 
 		var p *pem.Block
 		switch {
@@ -661,7 +659,7 @@ func TestSerialize(t *testing.T) {
 
 		if err != nil {
 			if assert.NotNil(t, test.err) {
-				assert.Contains(t, err.Error(), test.err.Error())
+				assert.HasPrefix(t, err.Error(), test.err.Error())
 			}
 		} else {
 			if assert.Nil(t, test.err) {
@@ -670,43 +668,43 @@ func TestSerialize(t *testing.T) {
 				case *rsa.PrivateKey:
 					if test.pass == "" {
 						assert.False(t, x509.IsEncryptedPEMBlock(p))
-						assert.Equal(t, p.Type, "RSA PRIVATE KEY")
-						assert.Equal(t, p.Bytes, x509.MarshalPKCS1PrivateKey(k))
+						assert.Equals(t, p.Type, "RSA PRIVATE KEY")
+						assert.Equals(t, p.Bytes, x509.MarshalPKCS1PrivateKey(k))
 					} else {
 						assert.True(t, x509.IsEncryptedPEMBlock(p))
-						assert.Equal(t, p.Type, "RSA PRIVATE KEY")
-						assert.Equal(t, p.Headers["Proc-Type"], "4,ENCRYPTED")
+						assert.Equals(t, p.Type, "RSA PRIVATE KEY")
+						assert.Equals(t, p.Headers["Proc-Type"], "4,ENCRYPTED")
 
 						var der []byte
 						der, err = x509.DecryptPEMBlock(p, []byte(test.pass))
-						require.NoError(t, err)
-						assert.Equal(t, der, x509.MarshalPKCS1PrivateKey(k))
+						assert.FatalError(t, err)
+						assert.Equals(t, der, x509.MarshalPKCS1PrivateKey(k))
 					}
 				case *rsa.PublicKey, *ecdsa.PublicKey:
 					assert.False(t, x509.IsEncryptedPEMBlock(p))
-					assert.Equal(t, p.Type, "PUBLIC KEY")
+					assert.Equals(t, p.Type, "PUBLIC KEY")
 
 					var b []byte
 					b, err = x509.MarshalPKIXPublicKey(k)
-					require.NoError(t, err)
-					assert.Equal(t, p.Bytes, b)
+					assert.FatalError(t, err)
+					assert.Equals(t, p.Bytes, b)
 				case *ecdsa.PrivateKey:
 					var actualBytes []byte
 					switch {
 					case test.pass == "":
-						assert.Equal(t, p.Type, "EC PRIVATE KEY")
+						assert.Equals(t, p.Type, "EC PRIVATE KEY")
 						assert.False(t, x509.IsEncryptedPEMBlock(p))
 						actualBytes = p.Bytes
 					case test.pkcs8:
-						assert.Equal(t, p.Type, "ENCRYPTED PRIVATE KEY")
+						assert.Equals(t, p.Type, "ENCRYPTED PRIVATE KEY")
 						actualBytes, err = DecryptPKCS8PrivateKey(p.Bytes, []byte(test.pass))
-						require.NoError(t, err)
+						assert.FatalError(t, err)
 					default:
-						assert.Equal(t, p.Type, "EC PRIVATE KEY")
+						assert.Equals(t, p.Type, "EC PRIVATE KEY")
 						assert.True(t, x509.IsEncryptedPEMBlock(p))
-						assert.Equal(t, p.Headers["Proc-Type"], "4,ENCRYPTED")
+						assert.Equals(t, p.Headers["Proc-Type"], "4,ENCRYPTED")
 						actualBytes, err = x509.DecryptPEMBlock(p, []byte(test.pass))
-						require.NoError(t, err)
+						assert.FatalError(t, err)
 					}
 					var expectedBytes []byte
 					if test.pkcs8 {
@@ -714,66 +712,66 @@ func TestSerialize(t *testing.T) {
 					} else {
 						expectedBytes, err = x509.MarshalECPrivateKey(k)
 					}
-					require.NoError(t, err)
-					assert.Equal(t, actualBytes, expectedBytes)
+					assert.FatalError(t, err)
+					assert.Equals(t, actualBytes, expectedBytes)
 
 					if test.file != "" {
 						// Check key permissions
 						var fileInfo os.FileInfo
 						fileInfo, err = os.Stat(test.file)
-						require.NoError(t, err)
-						assert.Equal(t, fileInfo.Mode(), os.FileMode(0600))
+						assert.FatalError(t, err)
+						assert.Equals(t, fileInfo.Mode(), os.FileMode(0600))
 						// Verify that key written to file is correct
 						var keyFileBytes []byte
 						keyFileBytes, err = os.ReadFile(test.file)
-						require.NoError(t, err)
+						assert.FatalError(t, err)
 						pemKey, _ := pem.Decode(keyFileBytes)
-						assert.Equal(t, pemKey.Type, "EC PRIVATE KEY")
+						assert.Equals(t, pemKey.Type, "EC PRIVATE KEY")
 						if x509.IsEncryptedPEMBlock(pemKey) {
-							assert.Equal(t, pemKey.Headers["Proc-Type"], "4,ENCRYPTED")
+							assert.Equals(t, pemKey.Headers["Proc-Type"], "4,ENCRYPTED")
 							actualBytes, err = x509.DecryptPEMBlock(pemKey, []byte(test.pass))
-							require.NoError(t, err)
+							assert.FatalError(t, err)
 						} else {
 							actualBytes = pemKey.Bytes
 						}
-						assert.Equal(t, actualBytes, expectedBytes)
+						assert.Equals(t, actualBytes, expectedBytes)
 					}
 				case ed25519.PrivateKey:
-					assert.Equal(t, p.Type, "PRIVATE KEY")
+					assert.Equals(t, p.Type, "PRIVATE KEY")
 					var actualBytes []byte
 					if test.pass == "" {
 						assert.False(t, x509.IsEncryptedPEMBlock(p))
 						actualBytes = p.Bytes
 					} else {
 						assert.True(t, x509.IsEncryptedPEMBlock(p))
-						assert.Equal(t, p.Headers["Proc-Type"], "4,ENCRYPTED")
+						assert.Equals(t, p.Headers["Proc-Type"], "4,ENCRYPTED")
 
 						actualBytes, err = x509.DecryptPEMBlock(p, []byte(test.pass))
-						require.NoError(t, err)
+						assert.FatalError(t, err)
 					}
 
 					var priv pkcs8
 					_, err = asn1.Unmarshal(actualBytes, &priv)
-					require.NoError(t, err)
-					assert.Equal(t, priv.Version, 0)
-					assert.Equal(t, priv.Algo, pkix.AlgorithmIdentifier{
+					assert.FatalError(t, err)
+					assert.Equals(t, priv.Version, 0)
+					assert.Equals(t, priv.Algo, pkix.AlgorithmIdentifier{
 						Algorithm:  asn1.ObjectIdentifier{1, 3, 101, 112},
 						Parameters: asn1.RawValue{},
 					})
-					assert.Equal(t, priv.PrivateKey[:2], []byte{4, 32})
-					assert.Equal(t, priv.PrivateKey[2:ed25519.SeedSize+2], k.Seed())
+					assert.Equals(t, priv.PrivateKey[:2], []byte{4, 32})
+					assert.Equals(t, priv.PrivateKey[2:ed25519.SeedSize+2], k.Seed())
 				case ed25519.PublicKey:
-					assert.Equal(t, p.Type, "PUBLIC KEY")
+					assert.Equals(t, p.Type, "PUBLIC KEY")
 					assert.False(t, x509.IsEncryptedPEMBlock(p))
 
 					var pub publicKeyInfo
 					_, err = asn1.Unmarshal(p.Bytes, &pub)
-					require.NoError(t, err)
-					assert.Equal(t, pub.Algo, pkix.AlgorithmIdentifier{
+					assert.FatalError(t, err)
+					assert.Equals(t, pub.Algo, pkix.AlgorithmIdentifier{
 						Algorithm:  asn1.ObjectIdentifier{1, 3, 101, 112},
 						Parameters: asn1.RawValue{},
 					})
-					assert.Equal(t, pub.PublicKey, asn1.BitString{
+					assert.Equals(t, pub.PublicKey, asn1.BitString{
 						Bytes:     k,
 						BitLength: ed25519.PublicKeySize * 8,
 					})
@@ -783,38 +781,38 @@ func TestSerialize(t *testing.T) {
 			}
 		}
 		if _, err := os.Stat("./test.key"); err == nil {
-			require.NoError(t, os.Remove("./test.key"))
+			assert.FatalError(t, os.Remove("./test.key"))
 		}
 	}
 }
 
 func TestParseDER(t *testing.T) {
 	k1, err := Read("testdata/openssl.rsa2048.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	k2, err := Read("testdata/openssl.p256.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	k3, err := Read("testdata/pkcs8/openssl.ed25519.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	rsaKey := k1.(*rsa.PrivateKey)
 	ecdsaKey := k2.(*ecdsa.PrivateKey)
 	edKey := k3.(ed25519.PrivateKey)
 	// Ed25519 der files
 	edPubDer, err := os.ReadFile("testdata/pkcs8/openssl.ed25519.pub.der")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	edPrivDer, err := os.ReadFile("testdata/pkcs8/openssl.ed25519.der")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	toDER := func(k interface{}) []byte {
 		switch k := k.(type) {
 		case *rsa.PublicKey, *ecdsa.PublicKey:
 			b, err := x509.MarshalPKIXPublicKey(k)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return b
 		case *rsa.PrivateKey:
 			return x509.MarshalPKCS1PrivateKey(k)
 		case *ecdsa.PrivateKey:
 			b, err := x509.MarshalECPrivateKey(k)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			return b
 		default:
 			t.Fatalf("unsupported key type %T", k)
@@ -863,7 +861,7 @@ func TestParseKey(t *testing.T) {
 		}
 		t.Run(fn, func(t *testing.T) {
 			data, err := os.ReadFile(fn)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			if td.encrypted {
 				key, err = ParseKey(data, WithPassword([]byte("mypassword")))
 			} else {
@@ -874,21 +872,21 @@ func TestParseKey(t *testing.T) {
 
 			switch td.typ {
 			case ecdsaPublicKey:
-				assert.IsType(t, &ecdsa.PublicKey{}, key)
+				assert.Type(t, &ecdsa.PublicKey{}, key)
 			case ecdsaPrivateKey:
-				assert.IsType(t, &ecdsa.PrivateKey{}, key)
+				assert.Type(t, &ecdsa.PrivateKey{}, key)
 			case ed25519PublicKey:
-				assert.IsType(t, ed25519.PublicKey{}, key)
+				assert.Type(t, ed25519.PublicKey{}, key)
 			case ed25519PrivateKey:
-				assert.IsType(t, ed25519.PrivateKey{}, key)
+				assert.Type(t, ed25519.PrivateKey{}, key)
 			case rsaPublicKey:
-				assert.IsType(t, &rsa.PublicKey{}, key)
+				assert.Type(t, &rsa.PublicKey{}, key)
 			case rsaPrivateKey:
-				assert.IsType(t, &rsa.PrivateKey{}, key)
+				assert.Type(t, &rsa.PrivateKey{}, key)
 			case x25519PublicKey:
-				assert.IsType(t, x25519.PublicKey{}, key)
+				assert.Type(t, x25519.PublicKey{}, key)
 			case x25519PrivateKey:
-				assert.IsType(t, x25519.PrivateKey{}, key)
+				assert.Type(t, x25519.PrivateKey{}, key)
 			default:
 				t.Errorf("type %T not supported", key)
 			}
@@ -899,24 +897,24 @@ func TestParseKey(t *testing.T) {
 func TestParseKey_x509(t *testing.T) {
 	b, _ := pem.Decode([]byte(testCRT))
 	cert, err := x509.ParseCertificate(b.Bytes)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	key, err := ParseKey([]byte(testCRT))
-	require.NoError(t, err)
-	assert.Equal(t, cert.PublicKey, key)
+	assert.FatalError(t, err)
+	assert.Equals(t, cert.PublicKey, key)
 
 	b, _ = pem.Decode([]byte(testCSR))
 	csr, err := x509.ParseCertificateRequest(b.Bytes)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	key, err = ParseKey([]byte(testCSR))
-	require.NoError(t, err)
-	assert.Equal(t, csr.PublicKey, key)
+	assert.FatalError(t, err)
+	assert.Equals(t, csr.PublicKey, key)
 
 	b, _ = pem.Decode([]byte(testCSRKeytool))
 	csr, err = x509.ParseCertificateRequest(b.Bytes)
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	key, err = ParseKey([]byte(testCSRKeytool))
-	require.NoError(t, err)
-	assert.Equal(t, csr.PublicKey, key)
+	assert.FatalError(t, err)
+	assert.Equals(t, csr.PublicKey, key)
 }
 
 func TestParseSSH(t *testing.T) {
@@ -927,18 +925,18 @@ func TestParseSSH(t *testing.T) {
 		}
 		t.Run(fn, func(t *testing.T) {
 			data, err := os.ReadFile(fn)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			key, err = ParseSSH(data)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			assert.NotNil(t, key)
 
 			switch td.typ {
 			case ecdsaPublicKey:
-				assert.IsType(t, &ecdsa.PublicKey{}, key)
+				assert.Type(t, &ecdsa.PublicKey{}, key)
 			case ed25519PublicKey:
-				assert.IsType(t, ed25519.PublicKey{}, key)
+				assert.Type(t, ed25519.PublicKey{}, key)
 			case rsaPublicKey:
-				assert.IsType(t, &rsa.PublicKey{}, key)
+				assert.Type(t, &rsa.PublicKey{}, key)
 			default:
 				t.Errorf("type %T not supported", key)
 			}
@@ -956,7 +954,9 @@ func TestOpenSSH(t *testing.T) {
 		if td.typ == x25519PublicKey || td.typ == x25519PrivateKey {
 			continue
 		}
-
+		// To be able to run this in parallel we need to declare local
+		// variables.
+		fn, td := fn, td
 		t.Run(fn, func(t *testing.T) {
 			t.Parallel()
 			opts := []Options{
@@ -968,26 +968,26 @@ func TestOpenSSH(t *testing.T) {
 			}
 
 			key, err := Read(fn, opts...)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 
 			// using their own methods
 			block, err := SerializeOpenSSHPrivateKey(key, opts...)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 
 			key2, err := ParseOpenSSHPrivateKey(pem.EncodeToMemory(block), opts...)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 
-			assert.Equal(t, key, key2)
+			assert.Equals(t, key, key2)
 
 			// using main methods
 			block2, err := Serialize(key2, opts...)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 			// salt must be different
-			assert.NotEqual(t, block, block2)
+			assert.NotEquals(t, block, block2)
 
 			key3, err := Parse(pem.EncodeToMemory(block2), opts...)
-			require.NoError(t, err)
-			assert.Equal(t, key2, key3)
+			assert.FatalError(t, err)
+			assert.Equals(t, key2, key3)
 		})
 	}
 }
@@ -995,9 +995,9 @@ func TestOpenSSH(t *testing.T) {
 func TestRead_options(t *testing.T) {
 	mustKey := func(filename string) interface{} {
 		b, err := os.ReadFile(filename)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		key, err := ssh.ParseRawPrivateKey(b)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		return key
 	}
 
@@ -1042,9 +1042,9 @@ func TestRead_options(t *testing.T) {
 func TestRead_promptPassword(t *testing.T) {
 	mustKey := func(filename string) interface{} {
 		b, err := os.ReadFile(filename)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		key, err := ssh.ParseRawPrivateKey(b)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		return key
 	}
 
@@ -1267,15 +1267,15 @@ func TestBundleCertificate(t *testing.T) {
 			got, added, err := BundleCertificate(bundlePEM, certsPEM...)
 			if tc.err != nil {
 				if assert.Error(t, err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.NoError(t, err)
-				assert.Equal(t, tc.added, added)
+				assert.Equals(t, tc.added, added)
 				if added {
-					assert.NotEqual(t, bundlePEM, got)
+					assert.NotEquals(t, bundlePEM, got)
 				} else {
-					assert.Equal(t, bundlePEM, got)
+					assert.Equals(t, bundlePEM, got)
 				}
 			}
 		})
@@ -1317,11 +1317,11 @@ func TestUnbundleCertificate(t *testing.T) {
 			got, modified, err := UnbundleCertificate(bundlePEM, certsPEM...)
 			if tc.err != nil {
 				if assert.Error(t, err) {
-					assert.Contains(t, err.Error(), tc.err.Error())
+					assert.HasPrefix(t, err.Error(), tc.err.Error())
 				}
 			} else {
 				assert.NoError(t, err)
-				assert.Equal(t, tc.modified, modified)
+				assert.Equals(t, tc.modified, modified)
 				if tc.wantBundle == "" {
 					assert.Nil(t, got)
 				} else {
@@ -1329,7 +1329,7 @@ func TestUnbundleCertificate(t *testing.T) {
 					if err != nil {
 						t.Fatal(err)
 					}
-					assert.Equal(t, strings.TrimSpace(string(want)), strings.TrimSpace(string(got)))
+					assert.Equals(t, strings.TrimSpace(string(want)), strings.TrimSpace(string(got)))
 				}
 			}
 		})
diff --git a/pemutil/pkcs8_test.go b/pemutil/pkcs8_test.go
index 2bcdabf..2f7b083 100644
--- a/pemutil/pkcs8_test.go
+++ b/pemutil/pkcs8_test.go
@@ -13,8 +13,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
+	"github.com/smallstep/assert"
 )
 
 func TestEncryptDecryptPKCS8(t *testing.T) {
@@ -30,11 +29,14 @@ func TestEncryptDecryptPKCS8(t *testing.T) {
 			continue
 		}
 
+		// To be able to run this in parallel we need to declare local
+		// variables.
+		fn := fn
 		t.Run(fn, func(t *testing.T) {
 			t.Parallel()
 
 			data, err := os.ReadFile(fn)
-			require.NoError(t, err)
+			assert.FatalError(t, err)
 
 			key1, err := Parse(data)
 			if err != nil {
@@ -54,7 +56,7 @@ func TestEncryptDecryptPKCS8(t *testing.T) {
 					t.Errorf("failed to decrypt %s with %s: %v", fn, alg.name, err)
 					continue
 				}
-				assert.Equal(t, "ENCRYPTED PRIVATE KEY", encBlock.Type)
+				assert.Equals(t, "ENCRYPTED PRIVATE KEY", encBlock.Type)
 				assert.NotNil(t, encBlock.Bytes)
 				assert.Nil(t, encBlock.Headers)
 
@@ -70,7 +72,7 @@ func TestEncryptDecryptPKCS8(t *testing.T) {
 					continue
 				}
 
-				assert.Equal(t, key1, key2)
+				assert.Equals(t, key1, key2)
 			}
 		})
 	}
@@ -79,7 +81,7 @@ func TestEncryptDecryptPKCS8(t *testing.T) {
 func TestSerialize_PKCS8(t *testing.T) {
 	mustPKIX := func(pub interface{}) *pem.Block {
 		b, err := x509.MarshalPKIXPublicKey(pub)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		return &pem.Block{
 			Type:  "PUBLIC KEY",
 			Bytes: b,
@@ -87,7 +89,7 @@ func TestSerialize_PKCS8(t *testing.T) {
 	}
 	mustPKCS8 := func(priv interface{}) *pem.Block {
 		b, err := x509.MarshalPKCS8PrivateKey(priv)
-		require.NoError(t, err)
+		assert.FatalError(t, err)
 		return &pem.Block{
 			Type:  "PRIVATE KEY",
 			Bytes: b,
@@ -95,11 +97,11 @@ func TestSerialize_PKCS8(t *testing.T) {
 	}
 
 	rsaKey, err := Read("testdata/openssl.rsa2048.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	ecdsaKey, err := Read("testdata/openssl.p256.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 	edKey, err := Read("testdata/pkcs8/openssl.ed25519.pem")
-	require.NoError(t, err)
+	assert.FatalError(t, err)
 
 	rsaKeyPub := rsaKey.(*rsa.PrivateKey).Public()
 	ecdsaKeyPub := ecdsaKey.(*ecdsa.PrivateKey).Public()
diff --git a/randutil/random_test.go b/randutil/random_test.go
index 45554f0..d42aea4 100644
--- a/randutil/random_test.go
+++ b/randutil/random_test.go
@@ -7,7 +7,7 @@ import (
 	"regexp"
 	"testing"
 
-	"github.com/stretchr/testify/assert"
+	"github.com/smallstep/assert"
 )
 
 func TestErrors(t *testing.T) {
@@ -17,33 +17,33 @@ func TestErrors(t *testing.T) {
 
 	str, err := UUIDv4()
 	assert.Error(t, err)
-	assert.Len(t, str, 0)
+	assert.Len(t, 0, str)
 
 	sizes := []int{4, 8, 16, 32}
 	for _, size := range sizes {
 		b, err := Salt(size)
 		assert.Error(t, err)
-		assert.Len(t, b, 0)
+		assert.Len(t, 0, b)
 
 		str, err = String(size, "0123456789")
 		assert.Error(t, err)
-		assert.Len(t, str, 0)
+		assert.Len(t, 0, str)
 
 		str, err = Hex(size)
 		assert.Error(t, err)
-		assert.Len(t, str, 0)
+		assert.Len(t, 0, str)
 
 		str, err = Alphanumeric(size)
 		assert.Error(t, err)
-		assert.Len(t, str, 0)
+		assert.Len(t, 0, str)
 
 		str, err = ASCII(size)
 		assert.Error(t, err)
-		assert.Len(t, str, 0)
+		assert.Len(t, 0, str)
 
 		str, err = Alphabet(size)
 		assert.Error(t, err)
-		assert.Len(t, str, 0)
+		assert.Len(t, 0, str)
 	}
 }
 
@@ -55,7 +55,7 @@ func TestSalt(t *testing.T) {
 		b, err := Salt(size)
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -67,7 +67,7 @@ func TestBytes(t *testing.T) {
 		b, err := Bytes(size)
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -83,7 +83,7 @@ func TestString(t *testing.T) {
 		assert.True(t, re.MatchString(b))
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -98,7 +98,7 @@ func TestHex(t *testing.T) {
 		assert.True(t, re.MatchString(b))
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -113,7 +113,7 @@ func TestAlphanumeric(t *testing.T) {
 		assert.True(t, re.MatchString(b))
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -128,7 +128,7 @@ func TestASCII(t *testing.T) {
 		assert.True(t, re.MatchString(b))
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -143,7 +143,7 @@ func TestAlphabet(t *testing.T) {
 		assert.True(t, re.MatchString(b))
 		assert.NoError(t, err)
 		// Most of the time
-		assert.NotEqual(t, a, b)
+		assert.NotEquals(t, a, b)
 	}
 }
 
@@ -151,7 +151,7 @@ func TestUUIDv4(t *testing.T) {
 	re := regexp.MustCompilePOSIX(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
 	uuid, err := UUIDv4()
 	assert.NoError(t, err)
-	assert.Len(t, uuid, 36)
+	assert.Len(t, 36, uuid)
 	assert.True(t, re.MatchString(uuid))
 
 	b := make([]byte, 32)
diff --git a/tpm/algorithm/algorithm_test.go b/tpm/algorithm/algorithm_test.go
index 33855a0..1e59d0d 100644
--- a/tpm/algorithm/algorithm_test.go
+++ b/tpm/algorithm/algorithm_test.go
@@ -2,7 +2,6 @@ package algorithm
 
 import (
 	"encoding/json"
-	"math"
 	"testing"
 
 	"github.com/google/go-tpm/legacy/tpm2"
@@ -17,7 +16,6 @@ func Test_AlgorithmString(t *testing.T) {
 	}{
 		{"ok/RSA", tpm2.AlgRSA, "RSA"},
 		{"ok/3DES", 0x0003, "3DES"},
-		{"ok/UNKNOWN", math.MaxUint16, "UNKNOWN_ALGORITHM"},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/x509util/testdata/letsencrypt.crt b/x509util/testdata/letsencrypt.crt
new file mode 100644
index 0000000..a6f5134
--- /dev/null
+++ b/x509util/testdata/letsencrypt.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID1DCCA1qgAwIBAgISA7NpNuqAqIBOmvpNUK3sJ3ZfMAoGCCqGSM49BAMDMDIx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
+NjAeFw0yNTAyMDUxMzU0MDFaFw0yNTA1MDYxMzU0MDBaMBoxGDAWBgNVBAMTD2xl
+dHNlbmNyeXB0Lm9yZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFMtO1UPccGh
+Sc22brM9UZ0iQBrOTA591YIbOYIMjcRosUr1QvUCU6qytEG05I2Q+q3/7CuKWJWM
+YBrpngAneh+jggJmMIICYjAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYB
+BQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFI8WiTHls/Xf
+jkRIel9K6z5hu6g+MB8GA1UdIwQYMBaAFJMnRpgDqVFojpjWxEJI2yO/WJTSMFUG
+CCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDovL2U2Lm8ubGVuY3Iub3Jn
+MCIGCCsGAQUFBzAChhZodHRwOi8vZTYuaS5sZW5jci5vcmcvMG8GA1UdEQRoMGaC
+CWxlbmNyLm9yZ4IPbGV0c2VuY3J5cHQuY29tgg9sZXRzZW5jcnlwdC5vcmeCDXd3
+dy5sZW5jci5vcmeCE3d3dy5sZXRzZW5jcnlwdC5jb22CE3d3dy5sZXRzZW5jcnlw
+dC5vcmcwEwYDVR0gBAwwCjAIBgZngQwBAgEwggEEBgorBgEEAdZ5AgQCBIH1BIHy
+APAAdgDM+w9qhXEJZf6Vm1PO6bJ8IumFXA2XjbapflTA/kwNsAAAAZTWmTBDAAAE
+AwBHMEUCIQC3rNgMmSLcU0QEirE7KRJJUNvPdTfGYovR+9DKfQ6nRQIgBRCe7Pkb
+/1Jbdjs2b3WveDO7gXEIeh180dTRyTyJWfcAdgDgkrP8DB3I52g2H95huZZNClJ4
+GYpy1nLEsE2lbW9UBAAAAZTWmTAtAAAEAwBHMEUCIFzFrg1ekuosIsD2iN/xWGpu
++F1lrVUT11937GsIGfUSAiEA2ZUliRQ9+0DQoozWE2ynI4CmnZ6V5qYTSLczPBMu
+yLAwCgYIKoZIzj0EAwMDaAAwZQIxAMS9K8+IQbIIfLoVJRPgIvI3MRVmR1CuGUmr
+Jwu4+my9nOMcVXmgL+wVaBB2iE/MMQIwdZIKNllOWwM2NeXbgnjERy3+1ytbMVAf
+t0cHSdM2e7EH2MJuSg5fhFhg07MAboJJ
+-----END CERTIFICATE-----
diff --git a/x509util/utils_test.go b/x509util/utils_test.go
index 534b884..b541ffa 100644
--- a/x509util/utils_test.go
+++ b/x509util/utils_test.go
@@ -9,6 +9,10 @@ import (
 	"os"
 	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"go.step.sm/crypto/fipsutil"
 )
 
 func decodeCertificateFile(t *testing.T, filename string) *x509.Certificate {
@@ -144,6 +148,10 @@ func TestCreateSANs(t *testing.T) {
 }
 
 func Test_generateSubjectKeyID(t *testing.T) {
+	if fipsutil.Enabled() {
+		t.Skip("FIPS 140-3 mode is enabled")
+	}
+
 	ecdsaCrt := decodeCertificateFile(t, "testdata/google.crt")
 	rsaCrt := decodeCertificateFile(t, "testdata/smallstep.crt")
 	ed25519Crt := decodeCertificateFile(t, "testdata/ed25519.crt")
@@ -176,6 +184,33 @@ func Test_generateSubjectKeyID(t *testing.T) {
 	}
 }
 
+func Test_generateSubjectKeyID_fips(t *testing.T) {
+	if !fipsutil.Enabled() {
+		t.Skip("FIPS 140-3 mode is not enabled")
+	}
+
+	sha256Cert := decodeCertificateFile(t, "testdata/letsencrypt.crt")
+	type args struct {
+		pub crypto.PublicKey
+	}
+	tests := []struct {
+		name      string
+		args      args
+		want      []byte
+		assertion assert.ErrorAssertionFunc
+	}{
+		{"ok", args{sha256Cert.PublicKey}, sha256Cert.SubjectKeyId, assert.NoError},
+		{"fail", args{[]byte("fail")}, nil, assert.Error},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := generateSubjectKeyID(tt.args.pub)
+			tt.assertion(t, err)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
+
 func TestSanitizeName(t *testing.T) {
 	type args struct {
 		domain string