Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for generating Ed25519 certs #66

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ Writing state: certs.state
| --- | ----------- | -------- |
| subject | Distinguished name for the certificate. `subject` is the only mandatory field and it must be unique. | `CN=Joe` |
| sans | List of values for x509 Subject Alternative Name extension. | `DNS:www.example.com`, `IP:1.2.3.4`, `URI:https://www.example.com` |
| key_type | Certificate key algorithm. Default value is `EC` (elliptic curve). | `EC` or `RSA` |
| key_size | The key length in bits. Default value is 256 if `key_size` is not defined. | For key_type EC: `256`, `384`, `521`. For key_type RSA: `1024`, `2048`, `4096` |
| key_type | Certificate key algorithm. Default value is `EC` (elliptic curve). | `EC`, `RSA` or `ED25519` |
| key_size | The key length in bits. Default value is 256 if `key_size` is not defined. | For key_type EC: `256`, `384`, `521`. For key_type RSA: `1024`, `2048`, `4096`. For key_type ED25519: `256`. |
| expires | Certificate NotAfter field is calculated by adding duration defined in `expires` to current time. Default value is 8760h (one year) if `expires` is not defined. `not_after` takes precedence over `expires`. | `1s`, `10m`, `1h` |
| key_usages | List of values for x509 key usage extension. If `key_usages` is not defined, `CertSign` and `CRLSign` are set for CA certificates, `KeyEncipherment` and `DigitalSignature` are set for end-entity certificates. | `DigitalSignature`, `ContentCommitment`, `KeyEncipherment`, `DataEncipherment`, `KeyAgreement`, `CertSign`, `CRLSign`, `EncipherOnly`, `DecipherOnly` |
| ext_key_usages | List of values for x509 extended key usage extension. Not set by default. | `Any`, `ServerAuth`, `ClientAuth`, `CodeSigning`, `EmailProtection`, `IPSECEndSystem`, `IPSECTunnel`, `IPSECUser`. `TimeStamping`, `OCSPSigning`, `MicrosoftServerGatedCrypto`, `NetscapeServerGatedCrypto`, `MicrosoftCommercialCodeSigning`, `MicrosoftKernelCodeSigning` |
Expand Down
11 changes: 10 additions & 1 deletion certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
Expand Down Expand Up @@ -54,7 +55,7 @@ type Certificate struct {

// KeySize defines the key length in bits.
// Default value is 256 (EC) or 2048 (RSA) if KeySize is undefined (when value is 0).
// Examples: For key_type EC: 256, 384, 521. For key_type RSA: 1024, 2048, 4096.
// Examples: For key_type EC: 256, 384, 521. For key_type RSA: 1024, 2048, 4096. For key_type ED25519: 256.
KeySize int `json:"key_size"`

// Expires automatically defines certificate's NotAfter field by adding duration defined in Expires to the current time.
Expand Down Expand Up @@ -106,6 +107,7 @@ type KeyType uint
const (
KeyTypeEC = iota
KeyTypeRSA
KeyTypeEd25519
)

// TLSCertificate returns the Certificate as tls.Certificate.
Expand Down Expand Up @@ -221,6 +223,8 @@ func (c *Certificate) defaults() error {
c.KeySize = 256
} else if c.KeyType == KeyTypeRSA {
c.KeySize = 2048
} else if c.KeyType == KeyTypeEd25519 {
c.KeySize = 256
}
}

Expand Down Expand Up @@ -300,6 +304,11 @@ func (c *Certificate) Generate() error {
key, err = ecdsa.GenerateKey(curve, rand.Reader)
} else if c.KeyType == KeyTypeRSA {
key, err = rsa.GenerateKey(rand.Reader, c.KeySize)
} else if c.KeyType == KeyTypeEd25519 {
if c.KeySize != 256 {
return fmt.Errorf("invalid Ed25519 key size: %d (valid: 256)", c.KeySize)
}
_, key, err = ed25519.GenerateKey(rand.Reader)
}
if err != nil {
return err
Expand Down
4 changes: 4 additions & 0 deletions certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ func TestInvalidKeySize(t *testing.T) {
input = Certificate{Subject: "CN=Joe", KeyType: KeyTypeRSA, KeySize: 1}
_, err = input.X509Certificate()
assert.NotNil(t, err)

input = Certificate{Subject: "CN=Joe", KeyType: KeyTypeEd25519, KeySize: 1}
_, err = input.X509Certificate()
assert.NotNil(t, err)
}

func TestPEM(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions internal/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ func (m *Manifest) processCertificate(c *CertificateManifest) error {
c.KeyType = api.KeyTypeEC
case "RSA":
c.KeyType = api.KeyTypeRSA
case "ED25519":
c.KeyType = api.KeyTypeEd25519
default:
return fmt.Errorf("key_type contains invalid value: %s", c.KeyTypeAsString)
}
Expand Down
10 changes: 10 additions & 0 deletions internal/manifest/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ func TestParsingAllCertificateFields(t *testing.T) {
assert.Empty(t, got.IPAddresses)

assert.Equal(t, big.NewInt(123), got.SerialNumber)

// Check fields Ee25519 end-entity cert.
tlsCert, err = tls.LoadX509KeyPair(path.Join(dir, "ed25519-cert.pem"), path.Join(dir, "ed25519-cert-key.pem"))
assert.Nil(t, err)
got, err = x509.ParseCertificate(tlsCert.Certificate[0])
assert.Nil(t, err)

assert.Equal(t, "ed25519-cert", got.Issuer.CommonName)
assert.Equal(t, "ed25519-cert", got.Subject.CommonName)
assert.Equal(t, x509.Ed25519, got.PublicKeyAlgorithm)
}

func TestRevocation(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions internal/manifest/testdata/certs-test-all-fields.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ key_size: 256
not_before: 2020-01-01T09:00:00Z
expires: 1h
serial: 123
---
subject: cn=ed25519-cert
key_type: ED25519
Loading