feat: replace crypto.PrivateKey with crypto.Signer

This commit is contained in:
Fernandez Ludovic 2026-03-04 17:12:05 +01:00
commit bce7264bfc
17 changed files with 40 additions and 39 deletions

View file

@ -91,7 +91,7 @@ func (a *AccountService) Deactivate(ctx context.Context, accountURL string) erro
}
// KeyChange Changes the account key.
func (a *AccountService) KeyChange(ctx context.Context, newKey crypto.PrivateKey) error {
func (a *AccountService) KeyChange(ctx context.Context, newKey crypto.Signer) error {
uri := a.core.GetDirectory().KeyChangeURL
eabJWS, err := a.core.jws().SignKeyChange(uri, newKey)

View file

@ -26,7 +26,7 @@ type Core struct {
HTTPClient *http.Client
privateKey crypto.PrivateKey
privateKey crypto.Signer
kid string
common service // Reuse a single struct instead of allocating one for each service on the heap.
@ -38,7 +38,7 @@ type Core struct {
}
// New Creates a new Core.
func New(httpClient *http.Client, userAgent, caDirURL, kid string, privateKey crypto.PrivateKey) (*Core, error) {
func New(httpClient *http.Client, userAgent, caDirURL, kid string, privateKey crypto.Signer) (*Core, error) {
doer := sender.NewDoer(httpClient, userAgent)
// NOTE(ldez) add context as a parameter of the constructor?
@ -85,7 +85,7 @@ func (a *Core) GetKid() string {
return a.kid
}
func (a *Core) setPrivateKey(privateKey crypto.PrivateKey) {
func (a *Core) setPrivateKey(privateKey crypto.Signer) {
a.privateKey = privateKey
}

View file

@ -21,13 +21,13 @@ type nonceSourceCreator interface {
// JWS Represents a JWS.
type JWS struct {
privKey crypto.PrivateKey
privKey crypto.Signer
kid string // Key identifier
nonces nonceSourceCreator
}
// NewJWS Create a new JWS.
func NewJWS(privateKey crypto.PrivateKey, kid string, nonceManager nonceSourceCreator) *JWS {
func NewJWS(privateKey crypto.Signer, kid string, nonceManager nonceSourceCreator) *JWS {
return &JWS{
privKey: privateKey,
nonces: nonceManager,
@ -82,12 +82,7 @@ func (j *JWS) SignEAB(url, kid string, hmac []byte) (*jose.JSONWebSignature, err
// GetKeyAuthorization Gets the key authorization for a token.
func (j *JWS) GetKeyAuthorization(token string) (string, error) {
var publicKey crypto.PublicKey
signer, ok := j.privKey.(crypto.Signer)
if ok {
publicKey = signer.Public()
}
publicKey := j.privKey.Public()
// Generate the Key Authorization for the challenge
jwk := &jose.JSONWebKey{Key: publicKey}
@ -103,7 +98,7 @@ func (j *JWS) GetKeyAuthorization(token string) (string, error) {
return token + "." + keyThumb, nil
}
func (j *JWS) SignKeyChange(url string, newKey crypto.PrivateKey) (*jose.JSONWebSignature, error) {
func (j *JWS) SignKeyChange(url string, newKey crypto.Signer) (*jose.JSONWebSignature, error) {
if j.kid == "" {
return nil, errors.New("missing kid")
}
@ -151,7 +146,7 @@ func sign(content []byte, signKey jose.SigningKey, options *jose.SignerOptions)
return signed, nil
}
func signatureAlgorithm(privKey crypto.PrivateKey) jose.SignatureAlgorithm {
func signatureAlgorithm(privKey crypto.Signer) jose.SignatureAlgorithm {
var alg jose.SignatureAlgorithm
switch k := privKey.(type) {

View file

@ -76,7 +76,7 @@ func ParsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
// Borrowed from Go standard library, to handle various private key and PEM block types.
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L291-L308
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238
func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
func ParsePEMPrivateKey(key []byte) (crypto.Signer, error) {
keyBlockDER, _ := pem.Decode(key)
if keyBlockDER == nil {
return nil, errors.New("invalid PEM block")
@ -92,7 +92,11 @@ func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
if key, err := x509.ParsePKCS8PrivateKey(keyBlockDER.Bytes); err == nil {
switch key := key.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey:
case *rsa.PrivateKey:
return key, nil
case *ecdsa.PrivateKey:
return key, nil
case ed25519.PrivateKey:
return key, nil
default:
return nil, fmt.Errorf("found unknown private key type in PKCS#8 wrapping: %T", key)
@ -106,7 +110,7 @@ func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
return nil, errors.New("failed to parse private key")
}
func GeneratePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {
func GeneratePrivateKey(keyType KeyType) (crypto.Signer, error) {
switch keyType {
case EC256:
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
@ -132,7 +136,7 @@ type CSROptions struct {
EmailAddresses []string
}
func CreateCSR(privateKey crypto.PrivateKey, opts CSROptions) ([]byte, error) {
func CreateCSR(privateKey crypto.Signer, opts CSROptions) ([]byte, error) {
var (
dnsNames []string
ipAddresses []net.IP

View file

@ -38,7 +38,7 @@ func TestGenerateCSR(t *testing.T) {
testCases := []struct {
desc string
privateKey crypto.PrivateKey
privateKey crypto.Signer
opts CSROptions
expected expected
}{

View file

@ -71,7 +71,7 @@ type Resource struct {
// See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
type ObtainRequest struct {
Domains []string
PrivateKey crypto.PrivateKey
PrivateKey crypto.Signer
MustStaple bool
EmailAddresses []string
@ -103,7 +103,7 @@ type ObtainRequest struct {
type ObtainForCSRRequest struct {
CSR *x509.CertificateRequest
PrivateKey crypto.PrivateKey
PrivateKey crypto.Signer
NotBefore time.Time
NotAfter time.Time
@ -548,7 +548,7 @@ func (c *Certifier) Renew(ctx context.Context, certRes Resource, options *RenewO
return c.ObtainForCSR(ctx, request)
}
var privateKey crypto.PrivateKey
var privateKey crypto.Signer
if certRes.PrivateKey != nil {
privateKey, err = certcrypto.ParsePEMPrivateKey(certRes.PrivateKey)
if err != nil {

View file

@ -138,7 +138,7 @@ func getKeyType(srcKeyPath string) (certcrypto.KeyType, error) {
return kt, nil
}
func guessKeyType(key crypto.PrivateKey) (certcrypto.KeyType, error) {
func guessKeyType(key crypto.Signer) (certcrypto.KeyType, error) {
switch k := key.(type) {
case *rsa.PrivateKey:
switch k.Size() {

View file

@ -16,10 +16,10 @@ type Account struct {
KeyType certcrypto.KeyType `json:"keyType"`
Registration *acme.ExtendedAccount `json:"registration"`
key crypto.PrivateKey
key crypto.Signer
}
func NewAccount(email, id string, keyType certcrypto.KeyType, key crypto.PrivateKey) *Account {
func NewAccount(email, id string, keyType certcrypto.KeyType, key crypto.Signer) *Account {
return &Account{Email: email, ID: id, KeyType: keyType, key: key}
}
@ -41,7 +41,7 @@ func (a *Account) GetKeyType() certcrypto.KeyType {
}
// GetPrivateKey returns the private account key.
func (a *Account) GetPrivateKey() crypto.PrivateKey {
func (a *Account) GetPrivateKey() crypto.Signer {
return a.key
}

View file

@ -204,7 +204,7 @@ func (s *AccountsStorage) getAccount(ctx context.Context, keyType certcrypto.Key
}
// createPrivateKey generates a new private key and saves it to a file.
func (s *AccountsStorage) createPrivateKey(keyType certcrypto.KeyType, effectiveAccountID string) (crypto.PrivateKey, error) {
func (s *AccountsStorage) createPrivateKey(keyType certcrypto.KeyType, effectiveAccountID string) (crypto.Signer, error) {
keysPath := s.getKeyPath(keyType, effectiveAccountID)
accKeyPath := filepath.Join(keysPath, effectiveAccountID+".key")
@ -242,7 +242,7 @@ func (s *AccountsStorage) createPrivateKey(keyType certcrypto.KeyType, effective
}
// readPrivateKey reads the private key from a file.
func (s *AccountsStorage) readPrivateKey(keyType certcrypto.KeyType, effectiveAccountID string) (crypto.PrivateKey, error) {
func (s *AccountsStorage) readPrivateKey(keyType certcrypto.KeyType, effectiveAccountID string) (crypto.Signer, error) {
keysPath := s.getKeyPath(keyType, effectiveAccountID)
accKeyPath := filepath.Join(keysPath, effectiveAccountID+".key")
@ -293,7 +293,7 @@ func (s *AccountsStorage) getRootUserPath(effectiveAccountID string) string {
}
// tryRecoverRegistration tries to recover the registration from the private key.
func (s *AccountsStorage) tryRecoverRegistration(ctx context.Context, privateKey crypto.PrivateKey) (*acme.ExtendedAccount, error) {
func (s *AccountsStorage) tryRecoverRegistration(ctx context.Context, privateKey crypto.Signer) (*acme.ExtendedAccount, error) {
// couldn't load account but got a key. Try to look the account up.
config := lego.NewConfig(&Account{key: privateKey})
config.CADirURL = s.server.String()

View file

@ -1,7 +1,6 @@
package storage
import (
"crypto"
"os"
"path/filepath"
"strings"
@ -41,6 +40,9 @@ func TestAccountsStorage_Save(t *testing.T) {
accountID := "test@example.com"
keyType := certcrypto.RSA4096
privateKey, err := certcrypto.GeneratePrivateKey(keyType)
require.NoError(t, err)
account := &Account{
Email: "account@example.com",
ID: accountID,
@ -56,7 +58,7 @@ func TestAccountsStorage_Save(t *testing.T) {
},
Location: "https://ame.example.com",
},
key: crypto.PrivateKey(""),
key: privateKey,
}
accountFilePath := storage.getAccountFilePath(keyType, accountID)

View file

@ -92,7 +92,7 @@ func SanitizedName(name string) string {
}
// ReadPrivateKeyFile reads a private key file.
func ReadPrivateKeyFile(filename string) (crypto.PrivateKey, error) {
func ReadPrivateKeyFile(filename string) (crypto.Signer, error) {
keyBytes, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("reading the private key: %w", err)

View file

@ -32,7 +32,7 @@ func (s *CertificatesStorage) ReadCertificate(certID string) ([]*x509.Certificat
return ReadCertificateFile(s.GetFileName(certID, ExtCert))
}
func (s *CertificatesStorage) ReadPrivateKey(certID string) (crypto.PrivateKey, error) {
func (s *CertificatesStorage) ReadPrivateKey(certID string) (crypto.Signer, error) {
privateKey, err := ReadPrivateKeyFile(s.GetFileName(certID, ExtKey))
if err != nil {
return nil, fmt.Errorf("error while parsing the private key for %q: %w", certID, err)

View file

@ -8,10 +8,10 @@ import (
type FakeUser struct {
Email string
PrivateKey crypto.PrivateKey
PrivateKey crypto.Signer
Registration *acme.ExtendedAccount
}
func (f *FakeUser) GetEmail() string { return f.Email }
func (f *FakeUser) GetRegistration() *acme.ExtendedAccount { return f.Registration }
func (f *FakeUser) GetPrivateKey() crypto.PrivateKey { return f.PrivateKey }
func (f *FakeUser) GetPrivateKey() crypto.Signer { return f.PrivateKey }

View file

@ -42,4 +42,4 @@ type mockUser struct {
func (u mockUser) GetEmail() string { return u.email }
func (u mockUser) GetRegistration() *acme.ExtendedAccount { return u.regres }
func (u mockUser) GetPrivateKey() crypto.PrivateKey { return u.privatekey }
func (u mockUser) GetPrivateKey() crypto.Signer { return u.privatekey }

View file

@ -171,7 +171,7 @@ func (r *Registrar) ResolveAccountByKey(ctx context.Context) (*acme.ExtendedAcco
}
// KeyRollover will attempt to change the account key.
func (r *Registrar) KeyRollover(ctx context.Context, newKey crypto.PrivateKey) error {
func (r *Registrar) KeyRollover(ctx context.Context, newKey crypto.Signer) error {
return r.core.Accounts.KeyChange(ctx, newKey)
}

View file

@ -11,5 +11,5 @@ import (
type User interface {
GetEmail() string
GetRegistration() *acme.ExtendedAccount
GetPrivateKey() crypto.PrivateKey
GetPrivateKey() crypto.Signer
}

View file

@ -15,4 +15,4 @@ type mockUser struct {
func (u mockUser) GetEmail() string { return u.email }
func (u mockUser) GetRegistration() *acme.ExtendedAccount { return u.regres }
func (u mockUser) GetPrivateKey() crypto.PrivateKey { return u.privatekey }
func (u mockUser) GetPrivateKey() crypto.Signer { return u.privatekey }