diff --git a/acme/api/account.go b/acme/api/account.go index 09205622b..451655aaa 100644 --- a/acme/api/account.go +++ b/acme/api/account.go @@ -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) diff --git a/acme/api/api.go b/acme/api/api.go index 0f12d71ce..57c79e745 100644 --- a/acme/api/api.go +++ b/acme/api/api.go @@ -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 } diff --git a/acme/api/internal/secure/jws.go b/acme/api/internal/secure/jws.go index 35e6b97ce..0160b1e72 100644 --- a/acme/api/internal/secure/jws.go +++ b/acme/api/internal/secure/jws.go @@ -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) { diff --git a/certcrypto/crypto.go b/certcrypto/crypto.go index 25a9c4913..631719744 100644 --- a/certcrypto/crypto.go +++ b/certcrypto/crypto.go @@ -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 diff --git a/certcrypto/crypto_test.go b/certcrypto/crypto_test.go index f5609fdf4..1b542f4fd 100644 --- a/certcrypto/crypto_test.go +++ b/certcrypto/crypto_test.go @@ -38,7 +38,7 @@ func TestGenerateCSR(t *testing.T) { testCases := []struct { desc string - privateKey crypto.PrivateKey + privateKey crypto.Signer opts CSROptions expected expected }{ diff --git a/certificate/certificates.go b/certificate/certificates.go index 6d6e270a2..557b51ab4 100644 --- a/certificate/certificates.go +++ b/certificate/certificates.go @@ -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 { diff --git a/cmd/internal/migrate/accounts.go b/cmd/internal/migrate/accounts.go index bbb061ce5..87222ec85 100644 --- a/cmd/internal/migrate/accounts.go +++ b/cmd/internal/migrate/accounts.go @@ -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() { diff --git a/cmd/internal/storage/account.go b/cmd/internal/storage/account.go index 892552137..d195907b9 100644 --- a/cmd/internal/storage/account.go +++ b/cmd/internal/storage/account.go @@ -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 } diff --git a/cmd/internal/storage/accounts.go b/cmd/internal/storage/accounts.go index b1fed22d2..9bd344464 100644 --- a/cmd/internal/storage/accounts.go +++ b/cmd/internal/storage/accounts.go @@ -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() diff --git a/cmd/internal/storage/accounts_test.go b/cmd/internal/storage/accounts_test.go index e78fe30cf..3b529fc85 100644 --- a/cmd/internal/storage/accounts_test.go +++ b/cmd/internal/storage/accounts_test.go @@ -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) diff --git a/cmd/internal/storage/certificates.go b/cmd/internal/storage/certificates.go index bd46cef3f..0b80ba089 100644 --- a/cmd/internal/storage/certificates.go +++ b/cmd/internal/storage/certificates.go @@ -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) diff --git a/cmd/internal/storage/certificates_reader.go b/cmd/internal/storage/certificates_reader.go index 6ba8aec49..8bdedeca2 100644 --- a/cmd/internal/storage/certificates_reader.go +++ b/cmd/internal/storage/certificates_reader.go @@ -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) diff --git a/e2e/internal/fakeuser.go b/e2e/internal/fakeuser.go index 4bd09b9e7..b60e4c4a9 100644 --- a/e2e/internal/fakeuser.go +++ b/e2e/internal/fakeuser.go @@ -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 } diff --git a/lego/client_test.go b/lego/client_test.go index e76d5899d..f8d73735b 100644 --- a/lego/client_test.go +++ b/lego/client_test.go @@ -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 } diff --git a/registration/registar.go b/registration/registar.go index 40a4653eb..3d19d9ae7 100644 --- a/registration/registar.go +++ b/registration/registar.go @@ -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) } diff --git a/registration/user.go b/registration/user.go index 206638c79..299161fe1 100644 --- a/registration/user.go +++ b/registration/user.go @@ -11,5 +11,5 @@ import ( type User interface { GetEmail() string GetRegistration() *acme.ExtendedAccount - GetPrivateKey() crypto.PrivateKey + GetPrivateKey() crypto.Signer } diff --git a/registration/user_test.go b/registration/user_test.go index 055cc814a..9e6df4199 100644 --- a/registration/user_test.go +++ b/registration/user_test.go @@ -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 }