Add support for ed25519 (#11780)

* update azure instructions

Update instructions in regards to azure AD Authentication and OIDC

* Initial pass of ed25519

* Fix typos on marshal function

* test wip

* typo

* fix tests

* missef changelog

* fix mismatch between signature and algo

* added test coverage for ed25519

* remove pkcs1 since does not exist for ed25519

* add ed25519 support to getsigner

* pull request feedback

Signed-off-by: Anner J. Bonilla <abonilla@hoyosintegrity.com>

* typo on key

Signed-off-by: Anner J. Bonilla <abonilla@hoyosintegrity.com>

* cast mistake

Signed-off-by: Anner J. Bonilla <abonilla@hoyosintegrity.com>

Co-authored-by: Jim Kalafut <jkalafut@hashicorp.com>
This commit is contained in:
Anner J. Bonilla 2021-10-05 11:28:49 -04:00 committed by GitHub
parent b979b52ed8
commit 8c29f49e1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 317 additions and 24 deletions

View File

@ -5,6 +5,7 @@ import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
@ -211,6 +212,8 @@ func TestBackend_Roles(t *testing.T) {
{"RSACSR", &rsaCAKey, &rsaCACert, true},
{"EC", &ecCAKey, &ecCACert, false},
{"ECCSR", &ecCAKey, &ecCACert, true},
{"ED", &edCAKey, &edCACert, false},
{"EDCSR", &edCAKey, &edCACert, true},
}
for _, tc := range cases {
@ -309,6 +312,13 @@ func checkCertsAndPrivateKey(keyType string, key crypto.Signer, usage x509.KeyUs
if err != nil {
return nil, fmt.Errorf("error parsing EC key: %s", err)
}
case "ed25519":
parsedCertBundle.PrivateKeyType = certutil.Ed25519PrivateKey
parsedCertBundle.PrivateKey = key
parsedCertBundle.PrivateKeyBytes, err = x509.MarshalPKCS8PrivateKey(key.(ed25519.PrivateKey))
if err != nil {
return nil, fmt.Errorf("error parsing Ed25519 key: %s", err)
}
}
}
@ -324,6 +334,8 @@ func checkCertsAndPrivateKey(keyType string, key crypto.Signer, usage x509.KeyUs
}
switch {
case parsedCertBundle.PrivateKeyType == certutil.Ed25519PrivateKey && keyType != "ed25519":
fallthrough
case parsedCertBundle.PrivateKeyType == certutil.RSAPrivateKey && keyType != "rsa":
fallthrough
case parsedCertBundle.PrivateKeyType == certutil.ECPrivateKey && keyType != "ec":
@ -707,7 +719,7 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {
generatedRSAKeys := map[int]crypto.Signer{}
generatedECKeys := map[int]crypto.Signer{}
generatedEdKeys := map[int]crypto.Signer{}
/*
// For the number of tests being run, a seed of 1 has been tested
// to hit all of the various values below. However, for normal
@ -1017,6 +1029,13 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {
generatedECKeys[keyBits] = privKey
}
case "ed25519":
privKey, ok = generatedEdKeys[keyBits]
if !ok {
_, privKey, _ = ed25519.GenerateKey(rand.Reader)
generatedEdKeys[keyBits] = privKey
}
default:
panic("invalid key type: " + keyType)
}
@ -3095,6 +3114,36 @@ func setCerts() {
Bytes: caBytes,
}
rsaCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
_, edk, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
marshaledKey, err = x509.MarshalPKCS8PrivateKey(edk)
if err != nil {
panic(err)
}
keyPEMBlock = &pem.Block{
Type: "PRIVATE KEY",
Bytes: marshaledKey,
}
edCAKey = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
if err != nil {
panic(err)
}
subjKeyID, err = certutil.GetSubjKeyID(edk)
if err != nil {
panic(err)
}
caBytes, err = x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, edk.Public(), edk)
if err != nil {
panic(err)
}
caCertPEMBlock = &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
}
edCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
}
func TestBackend_RevokePlusTidy_Intermediate(t *testing.T) {
@ -3281,4 +3330,6 @@ var (
rsaCACert string
ecCAKey string
ecCACert string
edCAKey string
edCACert string
)

View File

@ -3,6 +3,7 @@ package pki
import (
"context"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
@ -49,7 +50,7 @@ func TestBackend_CA_Steps(t *testing.T) {
client := cluster.Cores[0].Client
// Set RSA/EC CA certificates
var rsaCAKey, rsaCACert, ecCAKey, ecCACert string
var rsaCAKey, rsaCACert, ecCAKey, ecCACert, edCAKey, edCACert string
{
cak, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
@ -119,10 +120,40 @@ func TestBackend_CA_Steps(t *testing.T) {
Bytes: caBytes,
}
rsaCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
_, edk, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
marshaledKey, err = x509.MarshalPKCS8PrivateKey(edk)
if err != nil {
panic(err)
}
keyPEMBlock = &pem.Block{
Type: "PRIVATE KEY",
Bytes: marshaledKey,
}
edCAKey = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
if err != nil {
panic(err)
}
_, err = certutil.GetSubjKeyID(edk)
if err != nil {
panic(err)
}
caBytes, err = x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, edk.Public(), edk)
if err != nil {
panic(err)
}
caCertPEMBlock = &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
}
edCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
}
// Setup backends
var rsaRoot, rsaInt, ecRoot, ecInt *backend
var rsaRoot, rsaInt, ecRoot, ecInt, edRoot, edInt *backend
{
if err := client.Sys().Mount("rsaroot", &api.MountInput{
Type: "pki",
@ -167,6 +198,28 @@ func TestBackend_CA_Steps(t *testing.T) {
t.Fatal(err)
}
ecInt = b
if err := client.Sys().Mount("ed25519root", &api.MountInput{
Type: "pki",
Config: api.MountConfigInput{
DefaultLeaseTTL: "16h",
MaxLeaseTTL: "60h",
},
}); err != nil {
t.Fatal(err)
}
edRoot = b
if err := client.Sys().Mount("ed25519int", &api.MountInput{
Type: "pki",
Config: api.MountConfigInput{
DefaultLeaseTTL: "16h",
MaxLeaseTTL: "60h",
},
}); err != nil {
t.Fatal(err)
}
edInt = b
}
t.Run("teststeps", func(t *testing.T) {
@ -188,6 +241,15 @@ func TestBackend_CA_Steps(t *testing.T) {
subClient.SetToken(client.Token())
runSteps(t, ecRoot, ecInt, subClient, "ecroot/", "ecint/", ecCACert, ecCAKey)
})
t.Run("ed25519", func(t *testing.T) {
t.Parallel()
subClient, err := client.Clone()
if err != nil {
t.Fatal(err)
}
subClient.SetToken(client.Token())
runSteps(t, edRoot, edInt, subClient, "ed25519root/", "ed25519int/", edCACert, edCAKey)
})
})
}

View File

@ -4,6 +4,7 @@ import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
@ -597,6 +598,18 @@ func signCert(b *backend,
pubKey.Params().BitSize)}
}
case "ed25519":
// Verify that the key matches the role type
if csr.PublicKeyAlgorithm != x509.PublicKeyAlgorithm(x509.Ed25519) {
return nil, errutil.UserError{Err: fmt.Sprintf(
"role requires keys of type %s",
data.role.KeyType)}
}
_, ok := csr.PublicKey.(ed25519.PublicKey)
if !ok {
return nil, errutil.UserError{Err: "could not parse CSR's public key"}
}
case "any":
// We only care about running RSA < 2048 bit checks, so if not RSA
// break out

View File

@ -270,8 +270,8 @@ Set to 384 for SHA384 and 512 for SHA512.
Type: framework.TypeString,
Default: "rsa",
Description: `The type of key to use; defaults to RSA. "rsa"
and "ec" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec"},
"ec" and "ed25519" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec", "ed25519"},
DisplayAttrs: &framework.DisplayAttributes{
Value: "rsa",
},

View File

@ -193,8 +193,8 @@ protection use. Defaults to false.`,
Type: framework.TypeString,
Default: "rsa",
Description: `The type of key to use; defaults to RSA. "rsa"
and "ec" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec"},
"ec" and "ed25519" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec", "ed25519"},
},
"key_bits": {

3
changelog/11780.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:feature
pki: Support ed25519 as a key for the pki backend
```

View File

@ -3,6 +3,7 @@ package certutil
import (
"bytes"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
@ -36,6 +37,8 @@ func TestCertBundleConversion(t *testing.T) {
refreshECCertBundleWithChain(),
refreshEC8CertBundle(),
refreshEC8CertBundleWithChain(),
refreshEd255198CertBundle(),
refreshEd255198CertBundleWithChain(),
}
for i, cbut := range cbuts {
@ -75,6 +78,8 @@ func BenchmarkCertBundleParsing(b *testing.B) {
refreshECCertBundleWithChain(),
refreshEC8CertBundle(),
refreshEC8CertBundleWithChain(),
refreshEd255198CertBundle(),
refreshEd255198CertBundleWithChain(),
}
for i, cbut := range cbuts {
@ -103,6 +108,8 @@ func TestCertBundleParsing(t *testing.T) {
refreshECCertBundleWithChain(),
refreshEC8CertBundle(),
refreshEC8CertBundleWithChain(),
refreshEd255198CertBundle(),
refreshEd255198CertBundleWithChain(),
}
for i, cbut := range cbuts {
@ -179,6 +186,10 @@ func compareCertBundleToParsedCertBundle(cbut *CertBundle, pcbut *ParsedCertBund
if pcbut.PrivateKeyType != ECPrivateKey {
return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'ec' (%v)", pcbut.PrivateKeyType, ECPrivateKey)
}
case privEd255198KeyPem:
if pcbut.PrivateKeyType != Ed25519PrivateKey {
return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'ed25519' (%v)", pcbut.PrivateKeyType, ECPrivateKey)
}
default:
return fmt.Errorf("parsed bundle has unknown private key type")
}
@ -221,6 +232,10 @@ func compareCertBundleToParsedCertBundle(cbut *CertBundle, pcbut *ParsedCertBund
if cb.PrivateKey != privECKeyPem && cb.PrivateKey != privEC8KeyPem {
return fmt.Errorf("bundle private key does not match")
}
case Ed25519PrivateKey:
if cb.PrivateKey != privEd255198KeyPem {
return fmt.Errorf("bundle private key does not match")
}
default:
return fmt.Errorf("certBundle has unknown private key type")
}
@ -245,6 +260,7 @@ func TestCSRBundleConversion(t *testing.T) {
csrbuts := []*CSRBundle{
refreshRSACSRBundle(),
refreshECCSRBundle(),
refreshEd25519CSRBundle(),
}
for _, csrbut := range csrbuts {
@ -294,6 +310,10 @@ func compareCSRBundleToParsedCSRBundle(csrbut *CSRBundle, pcsrbut *ParsedCSRBund
if pcsrbut.PrivateKeyType != ECPrivateKey {
return fmt.Errorf("parsed bundle has wrong private key type")
}
case privEd255198KeyPem:
if pcsrbut.PrivateKeyType != Ed25519PrivateKey {
return fmt.Errorf("parsed bundle has wrong private key type")
}
default:
return fmt.Errorf("parsed bundle has unknown private key type")
}
@ -325,6 +345,13 @@ func compareCSRBundleToParsedCSRBundle(csrbut *CSRBundle, pcsrbut *ParsedCSRBund
if csrb.PrivateKey != privECKeyPem {
return fmt.Errorf("bundle ec private key does not match")
}
case "ed25519":
if pcsrbut.PrivateKeyType != Ed25519PrivateKey {
return fmt.Errorf("bundle has wrong private key type")
}
if csrb.PrivateKey != privEd255198KeyPem {
return fmt.Errorf("bundle ed25519 private key does not match")
}
default:
return fmt.Errorf("bundle has unknown private key type")
}
@ -476,6 +503,30 @@ func refreshECCertBundleWithChain() *CertBundle {
return ret
}
func refreshEd255198CertBundle() *CertBundle {
initTest.Do(setCerts)
return &CertBundle{
Certificate: certEd25519Pem,
PrivateKey: privEd255198KeyPem,
CAChain: []string{issuingCaChainPem[0]},
}
}
func refreshEd255198CertBundleWithChain() *CertBundle {
initTest.Do(setCerts)
ret := refreshEd255198CertBundle()
ret.CAChain = issuingCaChainPem
return ret
}
func refreshEd25519CSRBundle() *CSRBundle {
initTest.Do(setCerts)
return &CSRBundle{
CSR: csrEd25519Pem,
PrivateKey: privEd255198KeyPem,
}
}
func refreshRSACSRBundle() *CSRBundle {
initTest.Do(setCerts)
return &CSRBundle{
@ -714,18 +765,81 @@ func setCerts() {
privRSA8KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
}
// Ed25519 generation
{
pubkey, privkey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
subjKeyID, err := GetSubjKeyID(privkey)
if err != nil {
panic(err)
}
certTemplate := &x509.Certificate{
Subject: pkix.Name{
CommonName: "localhost",
},
SubjectKeyId: subjKeyID,
DNSNames: []string{"localhost"},
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement,
SerialNumber: big.NewInt(mathrand.Int63()),
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
}
csrTemplate := &x509.CertificateRequest{
Subject: pkix.Name{
CommonName: "localhost",
},
DNSNames: []string{"localhost"},
}
csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, privkey)
if err != nil {
panic(err)
}
csrPEMBlock := &pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: csrBytes,
}
csrEd25519Pem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock)))
certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, pubkey, intKey)
if err != nil {
panic(err)
}
certPEMBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certEd25519Pem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock)))
marshaledKey, err := x509.MarshalPKCS8PrivateKey(privkey)
if err != nil {
panic(err)
}
keyPEMBlock := &pem.Block{
Type: "PRIVATE KEY",
Bytes: marshaledKey,
}
privEd255198KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
}
issuingCaChainPem = []string{intCertPEM, caCertPEM}
}
var (
initTest sync.Once
privRSA8KeyPem string
privRSAKeyPem string
csrRSAPem string
certRSAPem string
privECKeyPem string
csrECPem string
privEC8KeyPem string
certECPem string
issuingCaChainPem []string
initTest sync.Once
privRSA8KeyPem string
privRSAKeyPem string
csrRSAPem string
certRSAPem string
privEd255198KeyPem string
csrEd25519Pem string
certEd25519Pem string
privECKeyPem string
csrECPem string
privEC8KeyPem string
certECPem string
issuingCaChainPem []string
)

View File

@ -164,6 +164,10 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
parsedBundle.PrivateKey = signer
parsedBundle.PrivateKeyType = ECPrivateKey
parsedBundle.PrivateKeyBytes = pemBlock.Bytes
case ed25519.PrivateKey:
parsedBundle.PrivateKey = signer
parsedBundle.PrivateKeyType = Ed25519PrivateKey
parsedBundle.PrivateKeyBytes = pemBlock.Bytes
}
} else if certificates, err := x509.ParseCertificates(pemBlock.Bytes); err == nil {
certPath = append(certPath, &CertBlock{
@ -246,6 +250,16 @@ func generatePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyC
if err != nil {
return errutil.InternalError{Err: fmt.Sprintf("error marshalling EC private key: %v", err)}
}
case "ed25519":
privateKeyType = Ed25519PrivateKey
_, privateKey, err = ed25519.GenerateKey(randReader)
if err != nil {
return errutil.InternalError{Err: fmt.Sprintf("error generating ed25519 private key: %v", err)}
}
privateKeyBytes, err = x509.MarshalPKCS8PrivateKey(privateKey.(ed25519.PrivateKey))
if err != nil {
return errutil.InternalError{Err: fmt.Sprintf("error marshalling Ed25519 private key: %v", err)}
}
default:
return errutil.UserError{Err: fmt.Sprintf("unknown key type: %s", keyType)}
}
@ -309,7 +323,16 @@ func ComparePublicKeys(key1Iface, key2Iface crypto.PublicKey) (bool, error) {
return false, nil
}
return true, nil
case ed25519.PublicKey:
key1 := key1Iface.(ed25519.PublicKey)
key2, ok := key2Iface.(ed25519.PublicKey)
if !ok {
return false, fmt.Errorf("key types do not match: %T and %T", key1Iface, key2Iface)
}
if !key1.Equal(key2) {
return false, nil
}
return true, nil
default:
return false, fmt.Errorf("cannot compare key with type %T", key1Iface)
}
@ -521,7 +544,7 @@ func ValidateKeyTypeLength(keyType string, keyBits int) error {
default:
return fmt.Errorf("unsupported bit length for EC key: %d", keyBits)
}
case "any":
case "any", "ed25519":
default:
return fmt.Errorf("unknown key type %s", keyType)
}
@ -617,6 +640,8 @@ func createCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertB
case 512:
certTemplate.SignatureAlgorithm = x509.SHA512WithRSA
}
case Ed25519PrivateKey:
certTemplate.SignatureAlgorithm = x509.PureEd25519
case ECPrivateKey:
switch data.Params.SignatureBits {
case 256:
@ -651,6 +676,8 @@ func createCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertB
case 512:
certTemplate.SignatureAlgorithm = x509.SHA512WithRSA
}
case "ed25519":
certTemplate.SignatureAlgorithm = x509.PureEd25519
case "ec":
switch data.Params.SignatureBits {
case 256:
@ -754,6 +781,8 @@ func createCSR(data *CreationBundle, addBasicConstraints bool, randReader io.Rea
csrTemplate.SignatureAlgorithm = x509.SHA256WithRSA
case "ec":
csrTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
case "ed25519":
csrTemplate.SignatureAlgorithm = x509.PureEd25519
}
csr, err := x509.CreateCertificateRequest(randReader, csrTemplate, result.PrivateKey)

View File

@ -12,6 +12,7 @@ import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
@ -56,6 +57,7 @@ const (
UnknownPrivateKey PrivateKeyType = ""
RSAPrivateKey PrivateKeyType = "rsa"
ECPrivateKey PrivateKeyType = "ec"
Ed25519PrivateKey PrivateKeyType = "ed25519"
)
// TLSUsage controls whether the intended usage of a *tls.Config
@ -185,6 +187,8 @@ func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
c.PrivateKeyType = ECPrivateKey
case RSAPrivateKey:
c.PrivateKeyType = RSAPrivateKey
case Ed25519PrivateKey:
c.PrivateKeyType = Ed25519PrivateKey
}
default:
return nil, errutil.UserError{Err: fmt.Sprintf("Unsupported key block type: %s", pemBlock.Type)}
@ -290,6 +294,8 @@ func (p *ParsedCertBundle) ToCertBundle() (*CertBundle, error) {
block.Type = string(ECBlock)
case RSAPrivateKey:
block.Type = string(PKCS1Block)
case Ed25519PrivateKey:
block.Type = string(PKCS8Block)
}
}
@ -380,7 +386,7 @@ func (p *ParsedCertBundle) getSigner() (crypto.Signer, error) {
case PKCS8Block:
if k, err := x509.ParsePKCS8PrivateKey(p.PrivateKeyBytes); err == nil {
switch k := k.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey:
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey:
return k.(crypto.Signer), nil
default:
return nil, errutil.UserError{Err: "Found unknown private key type in pkcs#8 wrapping"}
@ -411,6 +417,8 @@ func getPKCS8Type(bs []byte) (PrivateKeyType, error) {
return ECPrivateKey, nil
case *rsa.PrivateKey:
return RSAPrivateKey, nil
case ed25519.PrivateKey:
return Ed25519PrivateKey, nil
default:
return UnknownPrivateKey, errutil.UserError{Err: "Found unknown private key type in pkcs#8 wrapping"}
}
@ -443,6 +451,9 @@ func (c *CSRBundle) ToParsedCSRBundle() (*ParsedCSRBundle, error) {
} else if _, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err == nil {
result.PrivateKeyType = RSAPrivateKey
c.PrivateKeyType = "rsa"
} else if _, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes); err == nil {
result.PrivateKeyType = Ed25519PrivateKey
c.PrivateKeyType = "ed25519"
} else {
return nil, errutil.UserError{Err: fmt.Sprintf("Unknown private key type in bundle: %s", c.PrivateKeyType)}
}
@ -491,6 +502,9 @@ func (p *ParsedCSRBundle) ToCSRBundle() (*CSRBundle, error) {
case ECPrivateKey:
result.PrivateKeyType = "ec"
block.Type = "EC PRIVATE KEY"
case Ed25519PrivateKey:
result.PrivateKeyType = "ed25519"
block.Type = "PRIVATE KEY"
default:
return nil, errutil.InternalError{Err: "Could not determine private key type when creating block"}
}
@ -525,8 +539,15 @@ func (p *ParsedCSRBundle) getSigner() (crypto.Signer, error) {
return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
}
case Ed25519PrivateKey:
signerd, err := x509.ParsePKCS8PrivateKey(p.PrivateKeyBytes)
signer = signerd.(ed25519.PrivateKey)
if err != nil {
return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private Ed25519 key: %s", err)}
}
default:
return nil, errutil.UserError{Err: "Unable to determine type of private key; only RSA and EC are supported"}
return nil, errutil.UserError{Err: "Unable to determine type of private key; only RSA, Ed25519 and EC are supported"}
}
return signer, nil
}

View File

@ -128,7 +128,7 @@ export default Certificate.extend({
}),
keyType: attr('string', {
possibleValues: ['rsa', 'ec'],
possibleValues: ['rsa', 'ec','ed25519'],
defaultValue: 'rsa',
}),
keyBits: attr('number', {

View File

@ -463,7 +463,7 @@ can be set in a CSR are supported.
PEM-encoded DER, depending on the value of `format`. The other option is
`pkcs8` which will return the key marshalled as PEM-encoded PKCS8.
- `key_type` `(string: "rsa")`  Specifies the desired key type; must be `rsa`
- `key_type` `(string: "rsa")`  Specifies the desired key type; must be `rsa`, `ed25519`
or `ec`.
- `key_bits` `(int: 2048)`  Specifies the number of bits to use. This must be
@ -1084,7 +1084,7 @@ overwrite the existing cert/key with new values.
PEM-encoded DER, depending on the value of `format`. The other option is
`pkcs8` which will return the key marshalled as PEM-encoded PKCS8.
- `key_type` `(string: "rsa")`  Specifies the desired key type; must be `rsa`
- `key_type` `(string: "rsa")`  Specifies the desired key type; must be `rsa`, `ed25519`
or `ec`.
- `key_bits` `(int: 2048)`  Specifies the number of bits to use. This must be