diff --git a/api/client/proxy/transport/transportv1/client_test.go b/api/client/proxy/transport/transportv1/client_test.go
index 2743443a4b342..ce1579c9ce7cd 100644
--- a/api/client/proxy/transport/transportv1/client_test.go
+++ b/api/client/proxy/transport/transportv1/client_test.go
@@ -17,8 +17,8 @@ package transportv1
import (
"bytes"
"context"
+ "crypto/ed25519"
"crypto/rand"
- "crypto/rsa"
"errors"
"fmt"
"io"
@@ -555,7 +555,7 @@ func newServer(t *testing.T, srv transportv1pb.TransportServiceServer) testPack
// newKeyring returns an [agent.ExtendedAgent] that has
// one key populated in it.
func newKeyring(t *testing.T) agent.ExtendedAgent {
- private, err := rsa.GenerateKey(rand.Reader, 2048)
+ _, private, err := ed25519.GenerateKey(rand.Reader)
require.NoError(t, err)
keyring := agent.NewKeyring()
diff --git a/api/observability/tracing/ssh/ssh_test.go b/api/observability/tracing/ssh/ssh_test.go
index 5564eb40153f2..441073d61b5f9 100644
--- a/api/observability/tracing/ssh/ssh_test.go
+++ b/api/observability/tracing/ssh/ssh_test.go
@@ -16,12 +16,10 @@ package ssh
import (
"context"
+ "crypto/ed25519"
"crypto/rand"
- "crypto/rsa"
"crypto/subtle"
- "crypto/x509"
"encoding/json"
- "encoding/pem"
"errors"
"net"
"testing"
@@ -73,19 +71,11 @@ func (s *server) Stop() error {
}
func generateSigner(t *testing.T) ssh.Signer {
- private, err := rsa.GenerateKey(rand.Reader, 2048)
+ _, private, err := ed25519.GenerateKey(rand.Reader)
require.NoError(t, err)
-
- block := &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: x509.MarshalPKCS1PrivateKey(private),
- }
-
- privatePEM := pem.EncodeToMemory(block)
- signer, err := ssh.ParsePrivateKey(privatePEM)
+ sshSigner, err := ssh.NewSignerFromSigner(private)
require.NoError(t, err)
-
- return signer
+ return sshSigner
}
func (s *server) GetClient(t *testing.T) (ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request) {
diff --git a/api/utils/keys/privatekey_test.go b/api/utils/keys/privatekey_test.go
index 3d3eb1305f28b..6e4759eb44a2c 100644
--- a/api/utils/keys/privatekey_test.go
+++ b/api/utils/keys/privatekey_test.go
@@ -36,6 +36,7 @@ import (
)
func TestMarshalAndParseKey(t *testing.T) {
+ //nolint:forbidigo // Generating a small RSA key allowed for test.
rsaKey, err := rsa.GenerateKey(rand.Reader, 1024)
require.NoError(t, err)
ecKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
diff --git a/api/utils/sshutils/checker_test.go b/api/utils/sshutils/checker_test.go
index f32470e812552..be5e5af70c7a2 100644
--- a/api/utils/sshutils/checker_test.go
+++ b/api/utils/sshutils/checker_test.go
@@ -40,8 +40,10 @@ func TestCheckerValidateFIPS(t *testing.T) {
FIPS: true,
}
+ //nolint:forbidigo // Generating RSA keys allowed for key check test.
rsaKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
require.NoError(t, err)
+ //nolint:forbidigo // Generating RSA keys allowed for key check test.
smallRSAKey, err := rsa.GenerateKey(rand.Reader, 1024)
require.NoError(t, err)
ellipticKeyP224, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
diff --git a/api/utils/sshutils/conn_test.go b/api/utils/sshutils/conn_test.go
index ad34220726c12..e3e802ab79e4f 100644
--- a/api/utils/sshutils/conn_test.go
+++ b/api/utils/sshutils/conn_test.go
@@ -17,10 +17,8 @@ limitations under the License.
package sshutils
import (
+ "crypto/ed25519"
"crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "encoding/pem"
"net"
"testing"
"time"
@@ -64,19 +62,11 @@ func (s *server) Stop() error {
}
func generateSigner(t *testing.T) ssh.Signer {
- private, err := rsa.GenerateKey(rand.Reader, 2048)
+ _, private, err := ed25519.GenerateKey(rand.Reader)
require.NoError(t, err)
-
- block := &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: x509.MarshalPKCS1PrivateKey(private),
- }
-
- privatePEM := pem.EncodeToMemory(block)
- signer, err := ssh.ParsePrivateKey(privatePEM)
+ sshSigner, err := ssh.NewSignerFromSigner(private)
require.NoError(t, err)
-
- return signer
+ return sshSigner
}
func (s *server) GetClient(t *testing.T) (ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request) {
diff --git a/api/utils/sshutils/test.go b/api/utils/sshutils/test.go
index 516e903aa71f2..b52b0dcc4b168 100644
--- a/api/utils/sshutils/test.go
+++ b/api/utils/sshutils/test.go
@@ -17,25 +17,24 @@ limitations under the License.
package sshutils
import (
+ "crypto"
+ "crypto/ed25519"
"crypto/rand"
- "crypto/rsa"
"time"
"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
-
- "github.com/gravitational/teleport/api/constants"
)
const defaultPrincipal = "127.0.0.1"
// MakeTestSSHCA generates a new SSH certificate authority for tests.
func MakeTestSSHCA() (ssh.Signer, error) {
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ _, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, trace.Wrap(err)
}
- ca, err := ssh.NewSignerFromKey(privateKey)
+ ca, err := ssh.NewSignerFromSigner(privateKey)
if err != nil {
return nil, trace.Wrap(err)
}
@@ -49,33 +48,41 @@ func MakeSpoofedHostCert(realCA ssh.Signer) (ssh.Signer, error) {
if err != nil {
return nil, trace.Wrap(err)
}
- return makeHostCert(realCA.PublicKey(), fakeCA, defaultPrincipal)
+ _, hostKey, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return makeHostCert(hostKey, realCA.PublicKey(), fakeCA, defaultPrincipal)
}
// MakeRealHostCert makes an SSH host certificate that is signed by the
// provided CA.
func MakeRealHostCert(realCA ssh.Signer) (ssh.Signer, error) {
- return makeHostCert(realCA.PublicKey(), realCA, defaultPrincipal)
+ _, hostKey, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return makeHostCert(hostKey, realCA.PublicKey(), realCA, defaultPrincipal)
+}
+
+// MakeRealHostCertWithKey makes an SSH host certificate with the provided key that is
+// signed by the provided CA.
+func MakeRealHostCertWithKey(hostKey crypto.Signer, realCA ssh.Signer) (ssh.Signer, error) {
+ return makeHostCert(hostKey, realCA.PublicKey(), realCA, defaultPrincipal)
}
// MakeRealHostCertWithPrincipals makes an SSH host certificate that is signed by the
// provided CA for the provided principals.
func MakeRealHostCertWithPrincipals(realCA ssh.Signer, principals ...string) (ssh.Signer, error) {
- return makeHostCert(realCA.PublicKey(), realCA, principals...)
-}
-
-func makeHostCert(signKey ssh.PublicKey, signer ssh.Signer, principals ...string) (ssh.Signer, error) {
- priv, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
- if err != nil {
- return nil, trace.Wrap(err)
- }
-
- privSigner, err := ssh.NewSignerFromKey(priv)
+ _, hostKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, trace.Wrap(err)
}
+ return makeHostCert(hostKey, realCA.PublicKey(), realCA, principals...)
+}
- pub, err := ssh.NewPublicKey(priv.Public())
+func makeHostCert(hostKey crypto.Signer, caPublicKey ssh.PublicKey, caSigner ssh.Signer, principals ...string) (ssh.Signer, error) {
+ hostSigner, err := ssh.NewSignerFromSigner(hostKey)
if err != nil {
return nil, trace.Wrap(err)
}
@@ -87,9 +94,9 @@ func makeHostCert(signKey ssh.PublicKey, signer ssh.Signer, principals ...string
cert := &ssh.Certificate{
Nonce: nonce,
- Key: pub,
+ Key: hostSigner.PublicKey(),
CertType: ssh.HostCert,
- SignatureKey: signKey,
+ SignatureKey: caPublicKey,
ValidPrincipals: principals,
ValidBefore: uint64(time.Now().Add(time.Hour).Unix()),
}
@@ -104,12 +111,12 @@ func makeHostCert(signKey ssh.PublicKey, signer ssh.Signer, principals ...string
bytesForSigning := cert.Marshal()
bytesForSigning = bytesForSigning[:len(bytesForSigning)-4]
- cert.Signature, err = signer.Sign(rand.Reader, bytesForSigning)
+ cert.Signature, err = caSigner.Sign(rand.Reader, bytesForSigning)
if err != nil {
return nil, trace.Wrap(err)
}
- certSigner, err := ssh.NewCertSigner(cert, privSigner)
+ certSigner, err := ssh.NewCertSigner(cert, hostSigner)
if err != nil {
return nil, trace.Wrap(err)
}
diff --git a/integration/helpers/instance.go b/integration/helpers/instance.go
index df01f95d753fa..275837306b9d3 100644
--- a/integration/helpers/instance.go
+++ b/integration/helpers/instance.go
@@ -21,7 +21,6 @@ package helpers
import (
"bytes"
"context"
- "crypto/rsa"
"crypto/tls"
"crypto/x509/pkix"
"encoding/json"
@@ -47,6 +46,7 @@ import (
"github.com/gravitational/teleport/api/breaker"
clientproto "github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/auth/keygen"
"github.com/gravitational/teleport/lib/auth/state"
@@ -55,6 +55,7 @@ import (
"github.com/gravitational/teleport/lib/backend/lite"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/cloud/imds"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/httplib/csrf"
@@ -343,24 +344,27 @@ func NewInstance(t *testing.T, cfg InstanceConfig) *TeleInstance {
}
// generate instance secrets (keys):
- keygen := keygen.New(context.TODO())
if cfg.Priv == nil || cfg.Pub == nil {
- cfg.Priv, cfg.Pub, _ = keygen.GenerateKeyPair()
+ privateKey, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
+ fatalIf(err)
+ cfg.Priv = privateKey.PrivateKeyPEM()
+ cfg.Pub = privateKey.MarshalSSHPublicKey()
}
- rsaKey, err := ssh.ParseRawPrivateKey(cfg.Priv)
+ key, err := keys.ParsePrivateKey(cfg.Priv)
fatalIf(err)
- tlsCACert, err := tlsca.GenerateSelfSignedCAWithSigner(rsaKey.(*rsa.PrivateKey), pkix.Name{
+ tlsCACert, err := tlsca.GenerateSelfSignedCAWithSigner(key, pkix.Name{
CommonName: cfg.ClusterName,
Organization: []string{cfg.ClusterName},
}, nil, defaults.CATTL)
fatalIf(err)
- signer, err := ssh.ParsePrivateKey(cfg.Priv)
+ sshSigner, err := ssh.NewSignerFromSigner(key)
fatalIf(err)
+ keygen := keygen.New(context.TODO())
cert, err := keygen.GenerateHostCert(services.HostCertParams{
- CASigner: signer,
+ CASigner: sshSigner,
PublicHostKey: cfg.Pub,
HostID: cfg.HostID,
NodeName: cfg.NodeName,
diff --git a/integration/helpers/testmain.go b/integration/helpers/testmain.go
index b045546e24c68..5bc37898bffcf 100644
--- a/integration/helpers/testmain.go
+++ b/integration/helpers/testmain.go
@@ -23,7 +23,7 @@ import (
"testing"
"time"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/srv"
"github.com/gravitational/teleport/lib/utils"
@@ -34,7 +34,7 @@ import (
// it as an argument. Otherwise, it will run tests as normal.
func TestMainImplementation(m *testing.M) {
utils.InitLoggerForTests()
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
SetTestTimeouts(3 * time.Second)
modules.SetInsecureTestMode(true)
// If the test is re-executing itself, execute the command that comes over
diff --git a/integration/kube/fixtures.go b/integration/kube/fixtures.go
index 42228789a0f1b..5b4ba4910ca33 100644
--- a/integration/kube/fixtures.go
+++ b/integration/kube/fixtures.go
@@ -29,7 +29,7 @@ import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/integration/helpers"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/utils"
@@ -88,11 +88,11 @@ func ProxyClient(cfg ProxyConfig) (*kubernetes.Clientset, *rest.Config, error) {
if err != nil {
return nil, nil, trace.Wrap(err)
}
- privPEM, _, err := native.GenerateKeyPair()
+ priv, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
if err != nil {
return nil, nil, trace.Wrap(err)
}
- priv, err := keys.ParsePrivateKey(privPEM)
+ privPEM, err := keys.MarshalPrivateKey(priv)
if err != nil {
return nil, nil, trace.Wrap(err)
}
diff --git a/integrations/event-handler/mtls_certs.go b/integrations/event-handler/mtls_certs.go
index 84a7cc80b9827..553acf2c0ef01 100644
--- a/integrations/event-handler/mtls_certs.go
+++ b/integrations/event-handler/mtls_certs.go
@@ -186,6 +186,7 @@ func (c *MTLSCerts) generate(length int) error {
// genCertAndPK generates and returns certificate and primary key
func (c *MTLSCerts) genCertAndPK(length int, cert *x509.Certificate, parent *x509.Certificate, signer *rsa.PrivateKey) (*rsa.PrivateKey, []byte, error) {
// Generate PK
+ //nolint:forbidigo // Allow integration to generate RSA key without importing Teleport.
pk, err := rsa.GenerateKey(rand.Reader, length)
if err != nil {
return nil, nil, trace.Wrap(err)
diff --git a/integrations/lib/credentials/credentials_test.go b/integrations/lib/credentials/credentials_test.go
index a0c917323d726..3bedf5dad56b8 100644
--- a/integrations/lib/credentials/credentials_test.go
+++ b/integrations/lib/credentials/credentials_test.go
@@ -20,7 +20,6 @@ package credentials
import (
"crypto/rand"
- "crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
@@ -33,6 +32,7 @@ import (
"golang.org/x/crypto/ssh"
"github.com/gravitational/teleport/api/client"
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
// mockTLSCredentials mocks insecure Client credentials.
@@ -85,13 +85,13 @@ func TestCheckExpiredCredentials(t *testing.T) {
NotAfter: time.Now().Add(1 * time.Hour),
}
- caKey, err := rsa.GenerateKey(rand.Reader, 1024)
+ caKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
- clientKey, err := rsa.GenerateKey(rand.Reader, 1024)
+ clientKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
- validCertBytes, err := x509.CreateCertificate(rand.Reader, validCert, ca, &clientKey.PublicKey, caKey)
+ validCertBytes, err := x509.CreateCertificate(rand.Reader, validCert, ca, clientKey.Public(), caKey)
require.NoError(t, err)
- invalidCertBytes, err := x509.CreateCertificate(rand.Reader, expiredCert, ca, &clientKey.PublicKey, caKey)
+ invalidCertBytes, err := x509.CreateCertificate(rand.Reader, expiredCert, ca, clientKey.Public(), caKey)
require.NoError(t, err)
expiredCred := &mockTLSCredentials{CertificateChain: &tls.Certificate{Certificate: [][]byte{invalidCertBytes}}}
diff --git a/integrations/lib/testing/fakejoin/kubesigner.go b/integrations/lib/testing/fakejoin/kubesigner.go
index 3db707a1f8bc5..271c913d2758f 100644
--- a/integrations/lib/testing/fakejoin/kubesigner.go
+++ b/integrations/lib/testing/fakejoin/kubesigner.go
@@ -19,8 +19,6 @@
package fakejoin
import (
- "crypto/rand"
- "crypto/rsa"
"encoding/json"
"fmt"
"time"
@@ -31,6 +29,7 @@ import (
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/kubernetestoken"
)
@@ -38,7 +37,6 @@ import (
// allows us to do Kube joining locally. This is useful in tests as this is currently the easiest
// delegated join method we can use without having to rely on external infrastructure/providers.
type KubernetesSigner struct {
- key *rsa.PrivateKey
signer jose.Signer
jwks *jose.JSONWebKeySet
clock clockwork.Clock
@@ -48,12 +46,12 @@ const fakeKeyID = "foo"
// NewKubernetesSigner generates a keypair and creates a new KubernetesSigner.
func NewKubernetesSigner(clock clockwork.Clock) (*KubernetesSigner, error) {
- key, err := rsa.GenerateKey(rand.Reader, 2048)
+ key, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
if err != nil {
return nil, trace.Wrap(err, "generating key")
}
signer, err := jose.NewSigner(
- jose.SigningKey{Algorithm: jose.RS256, Key: key},
+ jose.SigningKey{Algorithm: jose.ES256, Key: key},
(&jose.SignerOptions{}).
WithType("JWT").
WithHeader("kid", fakeKeyID),
@@ -65,12 +63,11 @@ func NewKubernetesSigner(clock clockwork.Clock) (*KubernetesSigner, error) {
{
Key: key.Public(),
Use: "sig",
- Algorithm: string(jose.RS256),
+ Algorithm: string(jose.ES256),
KeyID: fakeKeyID,
},
}}
return &KubernetesSigner{
- key: key,
signer: signer,
jwks: jwks,
clock: clock,
diff --git a/lib/auth/auth_test.go b/lib/auth/auth_test.go
index c8f8bf6a713ea..d9170412d839e 100644
--- a/lib/auth/auth_test.go
+++ b/lib/auth/auth_test.go
@@ -21,7 +21,6 @@ package auth
import (
"context"
"crypto/rand"
- "crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
@@ -66,7 +65,6 @@ import (
"github.com/gravitational/teleport/api/utils/sshutils"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/auth/keystore"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/auth/testauthority"
wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
"github.com/gravitational/teleport/lib/authz"
@@ -216,7 +214,7 @@ func newAuthSuite(t *testing.T) *testPack {
func TestMain(m *testing.M) {
utils.InitLoggerForTests()
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
modules.SetInsecureTestMode(true)
os.Exit(m.Run())
}
@@ -1396,7 +1394,7 @@ func TestSAMLConnectorCRUDEventsEmitted(t *testing.T) {
ca, err := tlsca.FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
testClock := clockwork.NewFakeClock()
@@ -2581,7 +2579,7 @@ func TestGenerateOpenSSHCert(t *testing.T) {
role, ok := r.(*types.RoleV6)
require.True(t, ok)
- priv, err := native.GeneratePrivateKey()
+ priv, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
reply, err := p.a.GenerateOpenSSHCert(ctx, &proto.OpenSSHCertRequest{
@@ -2693,7 +2691,7 @@ func TestGenerateHostCertWithLocks(t *testing.T) {
hostID := uuid.New().String()
keygen := testauthority.New()
- _, pub, err := keygen.GetNewKeyPairFromPool()
+ _, pub, err := keygen.GenerateKeyPair()
require.NoError(t, err)
_, err = p.a.GenerateHostCert(ctx, pub, hostID, "test-node", []string{},
p.clusterName.GetClusterName(), types.RoleNode, time.Minute)
diff --git a/lib/auth/auth_with_roles_test.go b/lib/auth/auth_with_roles_test.go
index 9eca3cae6fa15..06fcd9e849a09 100644
--- a/lib/auth/auth_with_roles_test.go
+++ b/lib/auth/auth_with_roles_test.go
@@ -62,7 +62,6 @@ import (
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/api/utils/sshutils"
"github.com/gravitational/teleport/lib/auth/authclient"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/auth/testauthority"
"github.com/gravitational/teleport/lib/authz"
"github.com/gravitational/teleport/lib/cryptosuites"
@@ -1484,7 +1483,7 @@ func TestGenerateDatabaseCert(t *testing.T) {
}
// Generate CSR once for speed sake.
- priv, err := native.GeneratePrivateKey()
+ priv, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
csr, err := tlsca.GenerateCertificateRequestPEM(pkix.Name{CommonName: "test"}, priv)
diff --git a/lib/auth/db_test.go b/lib/auth/db_test.go
index 4127b9a2ed570..13ea93087fd33 100644
--- a/lib/auth/db_test.go
+++ b/lib/auth/db_test.go
@@ -30,7 +30,7 @@ import (
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
- "github.com/gravitational/teleport/lib/auth/testauthority"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/tlsca"
)
@@ -110,7 +110,7 @@ func TestDBCertSigning(t *testing.T) {
ctx := context.Background()
- privateKey, err := testauthority.New().GeneratePrivateKey()
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
csr, err := tlsca.GenerateCertificateRequestPEM(pkix.Name{
diff --git a/lib/auth/grpcserver_test.go b/lib/auth/grpcserver_test.go
index d1dcd4de42214..c04e48ba5e24a 100644
--- a/lib/auth/grpcserver_test.go
+++ b/lib/auth/grpcserver_test.go
@@ -2750,7 +2750,7 @@ func TestGenerateDatabaseCerts(t *testing.T) {
require.NoError(t, err)
// Generate CSR once for speed sake.
- priv, err := testauthority.New().GeneratePrivateKey()
+ priv, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
csr, err := tlsca.GenerateCertificateRequestPEM(pkix.Name{CommonName: "test"}, priv)
require.NoError(t, err)
diff --git a/lib/auth/keygen/keygen.go b/lib/auth/keygen/keygen.go
index a4d185c722d45..bb77f36012188 100644
--- a/lib/auth/keygen/keygen.go
+++ b/lib/auth/keygen/keygen.go
@@ -35,7 +35,6 @@ import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/wrappers"
apiutils "github.com/gravitational/teleport/api/utils"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/utils"
@@ -70,11 +69,6 @@ func New(_ context.Context, opts ...Option) *Keygen {
return k
}
-// GenerateKeyPair returns fresh priv/pub keypair, takes about 300ms to execute.
-func (k *Keygen) GenerateKeyPair() ([]byte, []byte, error) {
- return native.GenerateKeyPair()
-}
-
// GenerateHostCert generates a host certificate with the passed in parameters.
// The private key of the CA to sign the certificate must be provided.
func (k *Keygen) GenerateHostCert(c services.HostCertParams) ([]byte, error) {
diff --git a/lib/auth/keygen/keygen_test.go b/lib/auth/keygen/keygen_test.go
index 09313f5c6b7b6..e2d68d91a923e 100644
--- a/lib/auth/keygen/keygen_test.go
+++ b/lib/auth/keygen/keygen_test.go
@@ -25,6 +25,7 @@ import (
"time"
"github.com/google/go-cmp/cmp"
+ "github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
@@ -32,9 +33,10 @@ import (
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/api/utils/sshutils"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/auth/test"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/services"
)
@@ -48,9 +50,15 @@ func setupNativeContext(ctx context.Context, _ *testing.T) *nativeContext {
clock := clockwork.NewFakeClockAt(time.Date(2016, 9, 8, 7, 6, 5, 0, time.UTC))
tt.suite = &test.AuthSuite{
- A: New(ctx, SetClock(clock)),
- Keygen: native.GenerateKeyPair,
- Clock: clock,
+ A: New(ctx, SetClock(clock)),
+ Keygen: func() ([]byte, []byte, error) {
+ privateKey, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
+ if err != nil {
+ return nil, nil, trace.Wrap(err)
+ }
+ return privateKey.PrivateKeyPEM(), privateKey.MarshalSSHPublicKey(), nil
+ },
+ Clock: clock,
}
return &tt
@@ -91,14 +99,16 @@ func TestBuildPrincipals(t *testing.T) {
tt := setupNativeContext(context.Background(), t)
- caPrivateKey, _, err := native.GenerateKeyPair()
+ caPrivateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
-
- caSigner, err := ssh.ParsePrivateKey(caPrivateKey)
+ caSigner, err := ssh.NewSignerFromSigner(caPrivateKey)
require.NoError(t, err)
- _, hostPublicKey, err := native.GenerateKeyPair()
+ hostKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
+ hostPrivateKey, err := keys.NewSoftwarePrivateKey(hostKey)
+ require.NoError(t, err)
+ hostPublicKey := hostPrivateKey.MarshalSSHPublicKey()
tests := []struct {
desc string
@@ -191,10 +201,9 @@ func TestUserCertCompatibility(t *testing.T) {
tt := setupNativeContext(context.Background(), t)
- priv, pub, err := native.GenerateKeyPair()
+ caKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
-
- caSigner, err := ssh.ParsePrivateKey(priv)
+ caSigner, err := ssh.NewSignerFromSigner(caKey)
require.NoError(t, err)
tests := []struct {
@@ -219,7 +228,7 @@ func TestUserCertCompatibility(t *testing.T) {
userCertificateBytes, err := tt.suite.A.GenerateUserCert(services.UserCertParams{
CASigner: caSigner,
- PublicUserKey: pub,
+ PublicUserKey: ssh.MarshalAuthorizedKey(caSigner.PublicKey()),
Username: "user",
AllowedLogins: []string{"centos", "root"},
TTL: time.Hour,
diff --git a/lib/auth/kube_test.go b/lib/auth/kube_test.go
index 9b8222deda8b7..08af05f555701 100644
--- a/lib/auth/kube_test.go
+++ b/lib/auth/kube_test.go
@@ -19,7 +19,6 @@
package auth
import (
- "crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
@@ -33,6 +32,7 @@ import (
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/auth/authclient"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/tlsca"
)
@@ -105,15 +105,15 @@ func TestProcessKubeCSR(t *testing.T) {
// newTestCSR creates and PEM-encodes an x509 CSR with given subject.
func newTestCSR(subj pkix.Name) ([]byte, error) {
- // Use math/rand to avoid blocking on system entropy.
- rng := rand.New(rand.NewSource(0))
- priv, err := rsa.GenerateKey(rng, 2048)
+ priv, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
if err != nil {
return nil, err
}
x509CSR := &x509.CertificateRequest{
Subject: subj,
}
+ // Use math/rand to avoid blocking on system entropy.
+ rng := rand.New(rand.NewSource(0))
derCSR, err := x509.CreateCertificateRequest(rng, x509CSR, priv)
if err != nil {
return nil, err
diff --git a/lib/auth/machineid/machineidv1/workload_identity_service_test.go b/lib/auth/machineid/machineidv1/workload_identity_service_test.go
index 38bff691642f8..dfe099c483b15 100644
--- a/lib/auth/machineid/machineidv1/workload_identity_service_test.go
+++ b/lib/auth/machineid/machineidv1/workload_identity_service_test.go
@@ -32,7 +32,7 @@ import (
machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/auth"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
libjwt "github.com/gravitational/teleport/lib/jwt"
)
@@ -93,7 +93,7 @@ func TestWorkloadIdentityService_SignX509SVIDs(t *testing.T) {
)
require.NoError(t, err)
- privateKey, err := native.GenerateRSAPrivateKey()
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
pubBytes, err := x509.MarshalPKIXPublicKey(privateKey.Public())
require.NoError(t, err)
diff --git a/lib/auth/native/native.go b/lib/auth/native/native.go
index 093e6947713e7..e8128fa06c2dc 100644
--- a/lib/auth/native/native.go
+++ b/lib/auth/native/native.go
@@ -16,166 +16,44 @@
* along with this program. If not, see .
*/
+// Package native will be deleted as soon as references are removed from
+// teleport.e.
package native
import (
- "crypto/ed25519"
- "crypto/rand"
"crypto/rsa"
- "crypto/x509"
- "encoding/pem"
- "sync"
"testing"
- "time"
"github.com/gravitational/trace"
- "github.com/sirupsen/logrus"
- "github.com/gravitational/teleport"
- "github.com/gravitational/teleport/api/constants"
- "github.com/gravitational/teleport/api/utils/keys"
+ "github.com/gravitational/teleport/lib/cryptosuites"
+ "github.com/gravitational/teleport/lib/modules"
)
-var log = logrus.WithFields(logrus.Fields{
- teleport.ComponentKey: teleport.ComponentKeyGen,
-})
-
-// precomputedKeys is a queue of cached keys ready for usage.
-var precomputedKeys = make(chan *rsa.PrivateKey, 25)
-
-// startPrecomputeOnce is used to start the background task that precomputes key pairs.
-var startPrecomputeOnce sync.Once
-
-// GenerateKeyPair generates a new RSA key pair.
-func GenerateKeyPair() ([]byte, []byte, error) {
- priv, err := GeneratePrivateKey()
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
- return priv.PrivateKeyPEM(), priv.MarshalSSHPublicKey(), nil
-}
-
-// GenerateEICEKey generates a key that can be send to an Amazon EC2 instance using the ec2instanceconnect.SendSSHPublicKey method.
-func GenerateEICEKey() (publicKey any, privateKey any, err error) {
- if IsBoringBinary() {
- privKey, err := GeneratePrivateKey()
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- return privKey.Public(), privKey, nil
- }
-
- pubKey, privKey, err := ed25519.GenerateKey(nil)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- return pubKey, privKey, nil
-}
-
-// GeneratePrivateKey generates a new RSA private key.
-func GeneratePrivateKey() (*keys.PrivateKey, error) {
- rsaKey, err := getOrGenerateRSAPrivateKey()
+// GenerateRSAPrivateKey will be deleted as soon as references are removed from
+// teleport.e.
+func GenerateRSAPrivateKey() (*rsa.PrivateKey, error) {
+ key, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
if err != nil {
return nil, trace.Wrap(err)
}
-
- // We encode the private key in PKCS #1, ASN.1 DER form
- // instead of PKCS #8 to maintain compatibility with some
- // third party clients.
- keyPEM := pem.EncodeToMemory(&pem.Block{
- Type: keys.PKCS1PrivateKeyType,
- Headers: nil,
- Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
- })
-
- return keys.NewPrivateKey(rsaKey, keyPEM)
-}
-
-func GenerateRSAPrivateKey() (*rsa.PrivateKey, error) {
- return getOrGenerateRSAPrivateKey()
-}
-
-func getOrGenerateRSAPrivateKey() (*rsa.PrivateKey, error) {
- select {
- case k := <-precomputedKeys:
- return k, nil
- default:
- rsaKeyPair, err := generateRSAPrivateKey()
- if err != nil {
- return nil, err
- }
- return rsaKeyPair, nil
- }
+ return key.(*rsa.PrivateKey), nil
}
-func generateRSAPrivateKey() (*rsa.PrivateKey, error) {
- return rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
-}
-
-func precomputeKeys() {
- const backoff = time.Second * 30
- for {
- rsaPrivateKey, err := generateRSAPrivateKey()
- if err != nil {
- log.WithError(err).Errorf("Failed to precompute key pair, retrying in %s (this might be a bug).", backoff)
- time.Sleep(backoff)
- }
-
- precomputedKeys <- rsaPrivateKey
- }
-}
-
-func precomputeTestKeys() {
- generatedTestKeys := generateTestKeys()
- keysToReuse := make([]*rsa.PrivateKey, 0, testKeysNumber)
- for range testKeysNumber {
- k := <-generatedTestKeys
- precomputedKeys <- k
- keysToReuse = append(keysToReuse, k)
- }
- for {
- for _, k := range keysToReuse {
- precomputedKeys <- k
- }
- }
-}
-
-// testKeysNumber is the number of RSA keys generated in tests.
-const testKeysNumber = 25
-
-func generateTestKeys() <-chan *rsa.PrivateKey {
- generatedTestKeys := make(chan *rsa.PrivateKey, testKeysNumber)
- for range testKeysNumber {
- // Generate each key in a separate goroutine to take advantage of
- // multiple cores if possible.
- go func() {
- private, err := generateRSAPrivateKey()
- if err != nil {
- // Use only in tests. Safe to panic.
- panic(err)
- }
- generatedTestKeys <- private
- }()
- }
- return generatedTestKeys
+// PrecomputeKeys is an alias of [cryptosuites.PrecomputeRSAKeys]. It will be
+// deleted as soon as references are removed from teleport.e.
+func PrecomputeKeys() {
+ cryptosuites.PrecomputeRSAKeys()
}
-// PrecomputeKeys sets this package into a mode where a small backlog of keys are
-// computed in advance. This should only be enabled if large spikes in key computation
-// are expected (e.g. in auth/proxy services). Safe to double-call.
-func PrecomputeKeys() {
- startPrecomputeOnce.Do(func() {
- go precomputeKeys()
- })
+// PrecomputeTestKeys is an alias of [cryptosuites.PrecomputeRSATestKeys]. It
+// will be deleted as soon as references are removed from teleport.e.
+func PrecomputeTestKeys(m *testing.M) {
+ cryptosuites.PrecomputeRSATestKeys(m)
}
-// PrecomputeTestKeys generates RSA keys and reuse them to reduce CPU usage. This method should
-// only be in tests. Safe to call multiple times.
-// This function takes *testing.M, so is only can be used from TestMain in tests.
-func PrecomputeTestKeys(_ *testing.M) {
- startPrecomputeOnce.Do(func() {
- go precomputeTestKeys()
- })
+// IsBoringBinary is an alias of [modules.IsBoringBinary]. It will be deleted as
+// soon as references are removed from teleport.e.
+func IsBoringBinary() bool {
+ return modules.IsBoringBinary()
}
diff --git a/lib/auth/native/native_test.go b/lib/auth/native/native_test.go
deleted file mode 100644
index 319b242b4f3e5..0000000000000
--- a/lib/auth/native/native_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Teleport
- * Copyright (C) 2023 Gravitational, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package native
-
-import (
- "crypto/ed25519"
- "crypto/rsa"
- "crypto/x509"
- "encoding/pem"
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
-
- "github.com/gravitational/teleport/lib/utils"
-)
-
-func TestMain(m *testing.M) {
- utils.InitLoggerForTests()
- os.Exit(m.Run())
-}
-
-// TestPrecomputeMode verifies that package enters precompute mode when
-// PrecomputeKeys is called.
-func TestPrecomputeMode(t *testing.T) {
- t.Parallel()
-
- PrecomputeKeys()
-
- select {
- case <-precomputedKeys:
- case <-time.After(time.Second * 10):
- t.Fatal("Key precompute routine failed to start.")
- }
-}
-
-// TestGenerateRSAPKSC1Keypair tests that GeneratePrivateKey generates
-// a valid PKCS1 rsa key.
-func TestGeneratePKSC1RSAKey(t *testing.T) {
- t.Parallel()
-
- priv, err := GeneratePrivateKey()
- require.NoError(t, err)
-
- block, rest := pem.Decode(priv.PrivateKeyPEM())
- require.NoError(t, err)
- require.Empty(t, rest)
-
- _, err = x509.ParsePKCS1PrivateKey(block.Bytes)
- require.NoError(t, err)
-}
-
-func TestGenerateEICEKey_when_boringbinary(t *testing.T) {
- if !IsBoringBinary() {
- t.Skip()
- }
-
- publicKey, privateKey, err := GenerateEICEKey()
- require.NoError(t, err)
-
- // We expect an RSA Key because boringcrypto doesn't yet support generating ED25519 keys.
- require.IsType(t, rsa.PublicKey{}, publicKey)
- require.IsType(t, rsa.PrivateKey{}, privateKey)
-}
-
-func TestGenerateEICEKey(t *testing.T) {
- if IsBoringBinary() {
- t.Skip()
- }
-
- publicKey, privateKey, err := GenerateEICEKey()
- require.NoError(t, err)
-
- // We expect an ED25519 key
- require.IsType(t, ed25519.PublicKey{}, publicKey)
- require.IsType(t, ed25519.PrivateKey{}, privateKey)
-}
diff --git a/lib/auth/sessions.go b/lib/auth/sessions.go
index 0b394e1450da4..e93ac15133d11 100644
--- a/lib/auth/sessions.go
+++ b/lib/auth/sessions.go
@@ -38,7 +38,6 @@ import (
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/entitlements"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
dtconfig "github.com/gravitational/teleport/lib/devicetrust/config"
@@ -257,12 +256,12 @@ func (a *Server) newWebSession(
return nil, nil, trace.Wrap(err)
}
if _, isRSA := sshKey.Public().(*rsa.PublicKey); isRSA {
- // Ensure the native package is precomputing RSA keys if we ever
- // generate one. [native.PrecomputeKeys] is idempotent.
+ // Start precomputing RSA keys if we ever generate one.
+ // [cryptosuites.PrecomputeRSAKeys] is idempotent.
// Doing this lazily easily handles changing signature algorithm
// suites and won't start precomputing keys if they are never needed
// (a major benefit in tests).
- native.PrecomputeKeys()
+ cryptosuites.PrecomputeRSAKeys()
}
}
diff --git a/lib/auth/testauthority/testauthority.go b/lib/auth/testauthority/testauthority.go
index 2bd004aecf909..8dae039d9c1f4 100644
--- a/lib/auth/testauthority/testauthority.go
+++ b/lib/auth/testauthority/testauthority.go
@@ -26,9 +26,8 @@ import (
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
- "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/lib/auth/keygen"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/services"
)
@@ -47,24 +46,14 @@ func NewWithClock(clock clockwork.Clock) *Keygen {
return &Keygen{Keygen: inner}
}
-// GeneratePrivateKey generates a new PrivateKey.
-func (n *Keygen) GeneratePrivateKey() (*keys.PrivateKey, error) {
- priv, _, err := n.GenerateKeyPair()
- if err != nil {
- return nil, trace.Wrap(err)
- }
-
- return keys.ParsePrivateKey(priv)
-}
-
-func (n *Keygen) GetNewKeyPairFromPool() (priv []byte, pub []byte, err error) {
- return n.GenerateKeyPair()
-}
-
// GenerateKeyPair returns a new private key in PEM format and an ssh
// public key in authorized_key format.
func (n *Keygen) GenerateKeyPair() (priv []byte, pub []byte, err error) {
- return native.GenerateKeyPair()
+ privateKey, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
+ if err != nil {
+ return nil, nil, trace.Wrap(err)
+ }
+ return privateKey.PrivateKeyPEM(), privateKey.MarshalSSHPublicKey(), nil
}
func (n *Keygen) GenerateHostCert(c services.HostCertParams) ([]byte, error) {
diff --git a/lib/auth/windows/windows.go b/lib/auth/windows/windows.go
index c44f7f35be8e2..b198075036a4d 100644
--- a/lib/auth/windows/windows.go
+++ b/lib/auth/windows/windows.go
@@ -34,6 +34,7 @@ import (
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/tlsca"
)
@@ -70,12 +71,12 @@ func getCertRequest(req *GenerateCredentialsRequest) (*certRequest, error) {
// Important: rdpclient currently only supports 2048-bit RSA keys.
// If you switch the key type here, update handle_general_authentication in
// rdp/rdpclient/src/piv.rs accordingly.
- rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ rsaKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
if err != nil {
return nil, trace.Wrap(err)
}
// Also important: rdpclient expects the private key to be in PKCS1 format.
- keyDER := x509.MarshalPKCS1PrivateKey(rsaKey)
+ keyDER := x509.MarshalPKCS1PrivateKey(rsaKey.(*rsa.PrivateKey))
// Generate the Windows-compatible certificate, see
// https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/enabling-smart-card-logon-third-party-certification-authorities
diff --git a/lib/circleci/token_validator_test.go b/lib/circleci/token_validator_test.go
index 99d56f731b461..5d0a65b683ed5 100644
--- a/lib/circleci/token_validator_test.go
+++ b/lib/circleci/token_validator_test.go
@@ -20,8 +20,6 @@ package circleci
import (
"context"
- "crypto/rand"
- "crypto/rsa"
"encoding/json"
"fmt"
"net/http"
@@ -33,6 +31,8 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
// fakeIDP pretends to be a circle CI org OIDC provider, e.g:
@@ -76,7 +76,7 @@ func (f *fakeIDP) issuerURLTemplate() string {
func newFakeIDP(t *testing.T, organizationID string) *fakeIDP {
// Generate keypair for IDP
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
signer, err := jose.NewSigner(
@@ -121,7 +121,7 @@ func newFakeIDP(t *testing.T, organizationID string) *fakeIDP {
jwks := jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
- Key: &privateKey.PublicKey,
+ Key: privateKey.Public(),
},
},
}
diff --git a/lib/client/api_test.go b/lib/client/api_test.go
index 536809ceea02b..5558fb27b112a 100644
--- a/lib/client/api_test.go
+++ b/lib/client/api_test.go
@@ -41,7 +41,7 @@ import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/grpc/interceptors"
"github.com/gravitational/teleport/api/utils/keys"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/modules"
@@ -53,7 +53,7 @@ import (
func TestMain(m *testing.M) {
utils.InitLoggerForTests()
modules.SetInsecureTestMode(true)
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
os.Exit(m.Run())
}
diff --git a/lib/client/keystore_test.go b/lib/client/keystore_test.go
index 613f0a7481929..620ec8f687981 100644
--- a/lib/client/keystore_test.go
+++ b/lib/client/keystore_test.go
@@ -218,7 +218,7 @@ func TestCheckKey(t *testing.T) {
keyRing := auth.makeSignedKeyRing(t, idx, false)
// Swap out the key with a ECDSA SSH key.
- ellipticCertificate, _, err := cert.CreateEllipticCertificate("foo", ssh.UserCert)
+ ellipticCertificate, _, err := cert.CreateTestECDSACertificate("foo", ssh.UserCert)
require.NoError(t, err)
keyRing.Cert = ssh.MarshalAuthorizedKey(ellipticCertificate)
@@ -246,7 +246,7 @@ func TestCheckKeyFIPS(t *testing.T) {
keyRing := auth.makeSignedKeyRing(t, idx, false)
// Swap out the key with a ECDSA SSH key.
- ellipticCertificate, _, err := cert.CreateEllipticCertificate("foo", ssh.UserCert)
+ ellipticCertificate, _, err := cert.CreateTestECDSACertificate("foo", ssh.UserCert)
require.NoError(t, err)
keyRing.Cert = ssh.MarshalAuthorizedKey(ellipticCertificate)
diff --git a/lib/client/local_proxy_middleware_test.go b/lib/client/local_proxy_middleware_test.go
index bc32ab4b16e32..cfb79e335601e 100644
--- a/lib/client/local_proxy_middleware_test.go
+++ b/lib/client/local_proxy_middleware_test.go
@@ -29,8 +29,8 @@ import (
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/client"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/tlsca"
)
@@ -120,7 +120,7 @@ func newMockCertIssuer(t *testing.T, clock clockwork.Clock) *mockCertIssuer {
}
func (c *mockCertIssuer) initCA(t *testing.T) {
- priv, err := native.GeneratePrivateKey()
+ priv, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
cert, err := tlsca.GenerateSelfSignedCAWithConfig(tlsca.GenerateCAConfig{
@@ -147,7 +147,7 @@ func (c *mockCertIssuer) IssueCert(ctx context.Context) (tls.Certificate, error)
return tls.Certificate{}, trace.Wrap(c.issueErr)
}
- priv, err := native.GeneratePrivateKey()
+ priv, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
if err != nil {
return tls.Certificate{}, trace.Wrap(err)
}
diff --git a/lib/cryptosuites/internal/rsa/rsa.go b/lib/cryptosuites/internal/rsa/rsa.go
new file mode 100644
index 0000000000000..2203bd22bf05e
--- /dev/null
+++ b/lib/cryptosuites/internal/rsa/rsa.go
@@ -0,0 +1,129 @@
+// Teleport
+// Copyright (C) 2023 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package rsa
+
+import (
+ "context"
+ "crypto/rand"
+ "crypto/rsa"
+ "log/slog"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/gravitational/teleport"
+ "github.com/gravitational/teleport/api/constants"
+)
+
+var log = slog.With(teleport.ComponentKey, teleport.ComponentKeyGen)
+
+// precomputedKeys is a queue of cached keys ready for usage.
+var precomputedKeys = make(chan *rsa.PrivateKey, 25)
+
+// startPrecomputeOnce is used to start the background task that precomputes key pairs.
+var startPrecomputeOnce sync.Once
+
+// GenerateKey returns a newly generated RSA private key.
+func GenerateKey() (*rsa.PrivateKey, error) {
+ return getOrGenerateRSAPrivateKey()
+}
+
+func getOrGenerateRSAPrivateKey() (*rsa.PrivateKey, error) {
+ select {
+ case k := <-precomputedKeys:
+ return k, nil
+ default:
+ rsaKeyPair, err := generateRSAPrivateKey()
+ if err != nil {
+ return nil, err
+ }
+ return rsaKeyPair, nil
+ }
+}
+
+func generateRSAPrivateKey() (*rsa.PrivateKey, error) {
+ //nolint:forbidigo // This is the one function allowed to generate RSA keys.
+ return rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+}
+
+func precomputeKeys() {
+ const backoff = time.Second * 30
+ for {
+ rsaPrivateKey, err := generateRSAPrivateKey()
+ if err != nil {
+ log.ErrorContext(context.Background(), "Failed to precompute key pair, retrying (this might be a bug).",
+ slog.Any("error", err), slog.Duration("backoff", backoff))
+ time.Sleep(backoff)
+ }
+
+ precomputedKeys <- rsaPrivateKey
+ }
+}
+
+func precomputeTestKeys() {
+ generatedTestKeys := generateTestKeys()
+ keysToReuse := make([]*rsa.PrivateKey, 0, testKeysNumber)
+ for range testKeysNumber {
+ k := <-generatedTestKeys
+ precomputedKeys <- k
+ keysToReuse = append(keysToReuse, k)
+ }
+ for {
+ for _, k := range keysToReuse {
+ precomputedKeys <- k
+ }
+ }
+}
+
+// testKeysNumber is the number of RSA keys generated in tests.
+const testKeysNumber = 25
+
+func generateTestKeys() <-chan *rsa.PrivateKey {
+ generatedTestKeys := make(chan *rsa.PrivateKey, testKeysNumber)
+ for range testKeysNumber {
+ // Generate each key in a separate goroutine to take advantage of
+ // multiple cores if possible.
+ go func() {
+ private, err := generateRSAPrivateKey()
+ if err != nil {
+ // Use only in tests. Safe to panic.
+ panic(err)
+ }
+ generatedTestKeys <- private
+ }()
+ }
+ return generatedTestKeys
+}
+
+// PrecomputeKeys sets this package into a mode where a small backlog of keys are
+// computed in advance. This should only be enabled if large spikes in key computation
+// are expected (e.g. in auth/proxy services). Safe to double-call.
+func PrecomputeKeys() {
+ startPrecomputeOnce.Do(func() {
+ go precomputeKeys()
+ })
+}
+
+// PrecomputeTestKeys generates a fixed number of RSA keys and reuses them to
+// reduce CPU usage. This method should only be in tests. Safe to call multiple
+// times. This function takes *testing.M so it can only be used from TestMain in
+// tests.
+func PrecomputeTestKeys(_ *testing.M) {
+ startPrecomputeOnce.Do(func() {
+ go precomputeTestKeys()
+ })
+}
diff --git a/lib/cryptosuites/internal/rsa/rsa_test.go b/lib/cryptosuites/internal/rsa/rsa_test.go
new file mode 100644
index 0000000000000..15bbf508f37d4
--- /dev/null
+++ b/lib/cryptosuites/internal/rsa/rsa_test.go
@@ -0,0 +1,36 @@
+// Teleport
+// Copyright (C) 2023 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package rsa
+
+import (
+ "testing"
+ "time"
+)
+
+// TestPrecomputeMode verifies that package enters precompute mode when
+// PrecomputeKeys is called.
+func TestPrecomputeMode(t *testing.T) {
+ t.Parallel()
+
+ PrecomputeKeys()
+
+ select {
+ case <-precomputedKeys:
+ case <-time.After(time.Second * 10):
+ t.Fatal("Key precompute routine failed to start.")
+ }
+}
diff --git a/lib/cryptosuites/precompute.go b/lib/cryptosuites/precompute.go
new file mode 100644
index 0000000000000..6e25378f9eaf6
--- /dev/null
+++ b/lib/cryptosuites/precompute.go
@@ -0,0 +1,38 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package cryptosuites
+
+import (
+ "testing"
+
+ "github.com/gravitational/teleport/lib/cryptosuites/internal/rsa"
+)
+
+// PrecomputeKeys sets this package into a mode where a small backlog of RSA keys are
+// computed in advance. This should only be enabled if large spikes in RSA key
+// computation are expected (e.g. in auth/proxy services when the legacy suite
+// is configured). Safe to double-call.
+func PrecomputeRSAKeys() {
+ rsa.PrecomputeKeys()
+}
+
+// PrecomputeRSATestKeys may be called from TestMain to set this package into a
+// mode where it will precompute a fixed number of RSA keys and reuse them to
+// save on CPU usage.
+func PrecomputeRSATestKeys(m *testing.M) {
+ rsa.PrecomputeTestKeys(m)
+}
diff --git a/lib/cryptosuites/suites.go b/lib/cryptosuites/suites.go
index 6d8d509b74952..641c53ce1c8ac 100644
--- a/lib/cryptosuites/suites.go
+++ b/lib/cryptosuites/suites.go
@@ -32,7 +32,8 @@ import (
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/api/utils/keys"
+ internalrsa "github.com/gravitational/teleport/lib/cryptosuites/internal/rsa"
)
const defaultSuite = types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_LEGACY
@@ -76,6 +77,9 @@ const (
// SPIFFECAJWT represents the JWT key for the spiffe CA.
SPIFFECAJWT
+ // OktaCAJWT represents the JWT key for the Okta CA.
+ OktaCAJWT
+
// ProxyToDatabaseAgent represents keys used by the Proxy to dial the
// Database agent over a reverse tunnel.
ProxyToDatabaseAgent
@@ -105,10 +109,8 @@ const (
// BotSVID represents a key used for a SPIFFE SVID generated by tbot.
BotSVID
- // OktaCAJWT represents the JWT key for the Okta CA.
- OktaCAJWT
-
- // TODO(nklaassen): define remaining key purposes.
+ // EC2InstanceConnect is a key used for the EC2 Instance Connect service.
+ EC2InstanceConnect
// keyPurposeMax is 1 greater than the last valid key purpose, used to test that all values less than this
// are valid for each suite.
@@ -179,7 +181,8 @@ var (
// never restricted algorithm support.
ProxyToDatabaseAgent: RSA2048,
ProxyKubeClient: RSA2048,
- // TODO(nklaassen): define remaining key purposes.
+ // EC2InstanceConnect has always used Ed25519 by default.
+ EC2InstanceConnect: Ed25519,
}
// balancedV1 strikes a balance between security, compatibility, and
@@ -209,7 +212,7 @@ var (
BotSVID: ECDSAP256,
ProxyToDatabaseAgent: ECDSAP256,
ProxyKubeClient: ECDSAP256,
- // TODO(nklaassen): define remaining key purposes.
+ EC2InstanceConnect: Ed25519,
}
// fipsv1 is an algorithm suite tailored for FIPS compliance. It is based on
@@ -239,7 +242,7 @@ var (
BotSVID: ECDSAP256,
ProxyToDatabaseAgent: ECDSAP256,
ProxyKubeClient: ECDSAP256,
- // TODO(nklaassen): define remaining key purposes.
+ EC2InstanceConnect: ECDSAP256,
}
// hsmv1 in an algorithm suite tailored for clusters using an HSM or KMS
@@ -271,7 +274,7 @@ var (
BotSVID: ECDSAP256,
ProxyToDatabaseAgent: ECDSAP256,
ProxyKubeClient: ECDSAP256,
- // TODO(nklaassen): define remaining key purposes.
+ EC2InstanceConnect: Ed25519,
}
allSuites = map[types.SignatureAlgorithmSuite]suite{
@@ -421,8 +424,19 @@ func GenerateKeyWithAlgorithm(alg Algorithm) (crypto.Signer, error) {
}
}
+// GeneratePrivateKeyWithAlgorithm is exactly like [GenerateKeyWithAlgorithm]
+// but wraps the returned key in a [*keys.PrivateKey] for convenience.
+func GeneratePrivateKeyWithAlgorithm(alg Algorithm) (*keys.PrivateKey, error) {
+ key, err := GenerateKeyWithAlgorithm(alg)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ privateKey, err := keys.NewSoftwarePrivateKey(key)
+ return privateKey, trace.Wrap(err)
+}
+
func generateRSA2048() (*rsa.PrivateKey, error) {
- key, err := native.GenerateRSAPrivateKey()
+ key, err := internalrsa.GenerateKey()
return key, trace.Wrap(err)
}
diff --git a/lib/devicetrust/challenge/challenge_test.go b/lib/devicetrust/challenge/challenge_test.go
index 01e25c014b4c0..e78443420ed5d 100644
--- a/lib/devicetrust/challenge/challenge_test.go
+++ b/lib/devicetrust/challenge/challenge_test.go
@@ -17,72 +17,43 @@
package challenge_test
import (
- "crypto"
- "crypto/ecdsa"
- "crypto/ed25519"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/rsa"
"testing"
+ "github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/devicetrust/challenge"
)
func TestSignAndVerify(t *testing.T) {
- ecKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatalf("GenerateKey failed: %v", err)
- }
- rsaKey, err := rsa.GenerateKey(rand.Reader, 2048 /* bits */)
- if err != nil {
- t.Fatalf("GenerateKey failed: %v", err)
- }
- edPub, edPriv, err := ed25519.GenerateKey(rand.Reader)
- if err != nil {
- t.Fatalf("GenerateKey failed: %v", err)
- }
+ for _, algo := range []cryptosuites.Algorithm{
+ cryptosuites.RSA2048,
+ cryptosuites.ECDSAP256,
+ cryptosuites.Ed25519,
+ } {
+ t.Run(algo.String(), func(t *testing.T) {
+ t.Parallel()
- tests := []struct {
- name string
- signer crypto.Signer
- pubKey crypto.PublicKey
- }{
- {
- name: "ecdsa key",
- signer: ecKey,
- pubKey: ecKey.Public(),
- },
- {
- name: "rsa key",
- signer: rsaKey,
- pubKey: rsaKey.Public(),
- },
- {
- name: "ed25519 key",
- signer: edPriv,
- pubKey: edPub,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
chal, err := challenge.New()
if err != nil {
t.Fatalf("New failed: %v", err)
}
- sig, err := challenge.Sign(chal, test.signer)
+ signer, err := cryptosuites.GenerateKeyWithAlgorithm(algo)
+ require.NoError(t, err)
+ sig, err := challenge.Sign(chal, signer)
if err != nil {
t.Fatalf("Sign failed: %v", err)
}
// Verify correct challenge signature.
- if err := challenge.Verify(chal, sig, test.pubKey); err != nil {
+ if err := challenge.Verify(chal, sig, signer.Public()); err != nil {
t.Errorf("Verify returned err=%v, want nil", err)
}
// Verify bad challenge signature.
sig = []byte("invalid sig")
- if err := challenge.Verify(chal, sig, test.pubKey); err == nil {
+ if err := challenge.Verify(chal, sig, signer.Public()); err == nil {
t.Error("Verify returned nil err, want non-nil")
}
})
diff --git a/lib/gcp/token_validator_test.go b/lib/gcp/token_validator_test.go
index 48e352743f39b..7dcc139f3e61c 100644
--- a/lib/gcp/token_validator_test.go
+++ b/lib/gcp/token_validator_test.go
@@ -20,8 +20,7 @@ package gcp
import (
"context"
- "crypto/rand"
- "crypto/rsa"
+ "crypto"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -32,17 +31,20 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
type fakeIDP struct {
- t *testing.T
- signer jose.Signer
- privateKey *rsa.PrivateKey
- server *httptest.Server
+ t *testing.T
+ signer jose.Signer
+ publicKey crypto.PublicKey
+ server *httptest.Server
}
func newFakeIDP(t *testing.T) *fakeIDP {
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ // GCP uses RSA, prefer to test with it.
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
signer, err := jose.NewSigner(
@@ -52,9 +54,9 @@ func newFakeIDP(t *testing.T) *fakeIDP {
require.NoError(t, err)
f := &fakeIDP{
- signer: signer,
- privateKey: privateKey,
- t: t,
+ signer: signer,
+ publicKey: privateKey.Public(),
+ t: t,
}
providerMux := http.NewServeMux()
@@ -106,7 +108,7 @@ func (f *fakeIDP) handleJWKSEndpoint(w http.ResponseWriter, r *http.Request) {
jwks := jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
- Key: &f.privateKey.PublicKey,
+ Key: f.publicKey,
},
},
}
diff --git a/lib/githubactions/token_validator_test.go b/lib/githubactions/token_validator_test.go
index 1d7ab775af963..d79475597f321 100644
--- a/lib/githubactions/token_validator_test.go
+++ b/lib/githubactions/token_validator_test.go
@@ -20,8 +20,7 @@ package githubactions
import (
"context"
- "crypto/rand"
- "crypto/rsa"
+ "crypto"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -32,19 +31,22 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
type fakeIDP struct {
t *testing.T
signer jose.Signer
- privateKey *rsa.PrivateKey
+ publicKey crypto.PublicKey
server *httptest.Server
entepriseSlug string
ghesMode bool
}
func newFakeIDP(t *testing.T, ghesMode bool, enterpriseSlug string) *fakeIDP {
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ // Github uses RSA2048, prefer to test with it.
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
signer, err := jose.NewSigner(
@@ -56,7 +58,7 @@ func newFakeIDP(t *testing.T, ghesMode bool, enterpriseSlug string) *fakeIDP {
f := &fakeIDP{
signer: signer,
ghesMode: ghesMode,
- privateKey: privateKey,
+ publicKey: privateKey.Public(),
t: t,
entepriseSlug: enterpriseSlug,
}
@@ -142,7 +144,7 @@ func (f *fakeIDP) handleJWKSEndpoint(w http.ResponseWriter, r *http.Request) {
jwks := jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
- Key: &f.privateKey.PublicKey,
+ Key: f.publicKey,
},
},
}
diff --git a/lib/gitlab/token_validator_test.go b/lib/gitlab/token_validator_test.go
index 13a194b1ead01..d6163b2e0702b 100644
--- a/lib/gitlab/token_validator_test.go
+++ b/lib/gitlab/token_validator_test.go
@@ -20,8 +20,7 @@ package gitlab
import (
"context"
- "crypto/rand"
- "crypto/rsa"
+ "crypto"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -35,18 +34,19 @@ import (
"github.com/stretchr/testify/require"
"github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/services"
)
type fakeIDP struct {
- t *testing.T
- signer jose.Signer
- privateKey *rsa.PrivateKey
- server *httptest.Server
+ t *testing.T
+ signer jose.Signer
+ publicKey crypto.PublicKey
+ server *httptest.Server
}
func newFakeIDP(t *testing.T) *fakeIDP {
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
signer, err := jose.NewSigner(
@@ -56,9 +56,9 @@ func newFakeIDP(t *testing.T) *fakeIDP {
require.NoError(t, err)
f := &fakeIDP{
- signer: signer,
- privateKey: privateKey,
- t: t,
+ signer: signer,
+ publicKey: privateKey.Public(),
+ t: t,
}
providerMux := http.NewServeMux()
@@ -112,7 +112,7 @@ func (f *fakeIDP) handleJWKSEndpoint(w http.ResponseWriter, r *http.Request) {
jwks := jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
- Key: &f.privateKey.PublicKey,
+ Key: f.publicKey,
},
},
}
diff --git a/lib/integrations/awsoidc/eice_sendsshpublickey.go b/lib/integrations/awsoidc/eice_sendsshpublickey.go
index f4b74009e2c0b..40b0978f43b09 100644
--- a/lib/integrations/awsoidc/eice_sendsshpublickey.go
+++ b/lib/integrations/awsoidc/eice_sendsshpublickey.go
@@ -24,8 +24,6 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect"
"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
-
- "github.com/gravitational/teleport/lib/auth/native"
)
// EICESendSSHPublicKeyClient describes the required methods to send an SSH Public Key to
@@ -62,6 +60,9 @@ type SendSSHPublicKeyToEC2Request struct {
// EC2SSHLoginUser is the OS user to use when the user wants SSH access.
EC2SSHLoginUser string
+
+ // PublicKey is the SSH public key to send.
+ PublicKey ssh.PublicKey
}
// CheckAndSetDefaults checks if the required fields are present.
@@ -74,55 +75,37 @@ func (r *SendSSHPublicKeyToEC2Request) CheckAndSetDefaults() error {
return trace.BadParameter("ec2 ssh login user is required")
}
+ if r.PublicKey == nil {
+ return trace.BadParameter("SSH public key is required")
+ }
+
return nil
}
// SendSSHPublicKeyToEC2 sends an SSH Public Key to a target EC2 Instance.
// This key will be removed by AWS after 60 seconds and can only be used to authenticate the EC2SSHLoginUser.
// An [ssh.Signer] is then returned and can be used to access the host.
-func SendSSHPublicKeyToEC2(ctx context.Context, clt EICESendSSHPublicKeyClient, req SendSSHPublicKeyToEC2Request) (ssh.Signer, error) {
+func SendSSHPublicKeyToEC2(ctx context.Context, clt EICESendSSHPublicKeyClient, req SendSSHPublicKeyToEC2Request) error {
if err := req.CheckAndSetDefaults(); err != nil {
- return nil, trace.Wrap(err)
+ return trace.Wrap(err)
}
-
- sshSigner, err := sendSSHPublicKey(ctx, clt, req)
- if err != nil {
- return nil, trace.Wrap(err)
+ if err := sendSSHPublicKey(ctx, clt, req); err != nil {
+ return trace.Wrap(err)
}
-
- return sshSigner, nil
+ return nil
}
// sendSSHPublicKey creates a new Private Key and uploads the Public to the ec2 instance.
// This key will be removed by AWS after 60 seconds and can only be used to authenticate the EC2SSHLoginUser.
// More information: https://docs.aws.amazon.com/ec2-instance-connect/latest/APIReference/API_SendSSHPublicKey.html
-func sendSSHPublicKey(ctx context.Context, clt EICESendSSHPublicKeyClient, req SendSSHPublicKeyToEC2Request) (ssh.Signer, error) {
- pubKey, privKey, err := native.GenerateEICEKey()
- if err != nil {
- return nil, trace.Wrap(err)
- }
-
- publicKey, err := ssh.NewPublicKey(pubKey)
- if err != nil {
- return nil, trace.Wrap(err)
- }
-
- pubKeySSH := string(ssh.MarshalAuthorizedKey(publicKey))
- _, err = clt.SendSSHPublicKey(ctx,
+func sendSSHPublicKey(ctx context.Context, clt EICESendSSHPublicKeyClient, req SendSSHPublicKeyToEC2Request) error {
+ pubKeySSH := string(ssh.MarshalAuthorizedKey(req.PublicKey))
+ _, err := clt.SendSSHPublicKey(ctx,
&ec2instanceconnect.SendSSHPublicKeyInput{
InstanceId: &req.InstanceID,
InstanceOSUser: &req.EC2SSHLoginUser,
SSHPublicKey: &pubKeySSH,
},
)
- if err != nil {
- return nil, trace.Wrap(err)
- }
-
- sshSigner, err := ssh.NewSignerFromKey(privKey)
- if err != nil {
- return nil, trace.Wrap(err)
- }
-
- return sshSigner, nil
+ return trace.Wrap(err)
}
diff --git a/lib/integrations/awsoidc/eice_sendsshpublickey_test.go b/lib/integrations/awsoidc/eice_sendsshpublickey_test.go
index 67d3fa2bdadb5..2402cec117fff 100644
--- a/lib/integrations/awsoidc/eice_sendsshpublickey_test.go
+++ b/lib/integrations/awsoidc/eice_sendsshpublickey_test.go
@@ -27,6 +27,8 @@ import (
"github.com/gravitational/trace"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
func TestSendSSHPublicKeyRequest(t *testing.T) {
@@ -91,15 +93,19 @@ func TestSendSSHPublicKeyToEC2(t *testing.T) {
m := &mockSendSSHPublicKeyClient{}
- sshSigner, err := SendSSHPublicKeyToEC2(ctx, m, SendSSHPublicKeyToEC2Request{
+ key, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
+ require.NoError(t, err)
+ sshSigner, err := ssh.NewSignerFromSigner(key)
+ require.NoError(t, err)
+
+ err = SendSSHPublicKeyToEC2(ctx, m, SendSSHPublicKeyToEC2Request{
InstanceID: "id-123",
EC2SSHLoginUser: "root",
+ PublicKey: sshSigner.PublicKey(),
})
require.NoError(t, err)
- require.NotNil(t, sshSigner)
sshPublicKeyFromSigner := string(ssh.MarshalAuthorizedKey(sshSigner.PublicKey()))
-
require.Equal(t, sshPublicKeyFromSigner, m.sshKeySent)
require.Equal(t, "root", m.sshForUserSent)
}
diff --git a/lib/kubernetestoken/token_validator_test.go b/lib/kubernetestoken/token_validator_test.go
index 10368606e4284..51df225370c22 100644
--- a/lib/kubernetestoken/token_validator_test.go
+++ b/lib/kubernetestoken/token_validator_test.go
@@ -20,8 +20,6 @@ package kubernetestoken
import (
"context"
- "crypto/rand"
- "crypto/rsa"
"encoding/json"
"testing"
"time"
@@ -40,6 +38,7 @@ import (
ctest "k8s.io/client-go/testing"
"github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
var userGroups = []string{"system:serviceaccounts", "system:serviceaccounts:namespace", "system:authenticated"}
@@ -286,10 +285,10 @@ func Test_kubernetesSupportsBoundTokens(t *testing.T) {
}
func testSigner(t *testing.T) ([]byte, jose.Signer) {
- key, err := rsa.GenerateKey(rand.Reader, 2048)
+ key, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
signer, err := jose.NewSigner(
- jose.SigningKey{Algorithm: jose.RS256, Key: key},
+ jose.SigningKey{Algorithm: jose.ES256, Key: key},
(&jose.SignerOptions{}).
WithType("JWT").
WithHeader("kid", "foo"),
@@ -300,7 +299,7 @@ func testSigner(t *testing.T) ([]byte, jose.Signer) {
{
Key: key.Public(),
Use: "sig",
- Algorithm: string(jose.RS256),
+ Algorithm: string(jose.ES256),
KeyID: "foo",
},
}}
diff --git a/lib/auth/native/boring.go b/lib/modules/boring.go
similarity index 98%
rename from lib/auth/native/boring.go
rename to lib/modules/boring.go
index 0c4a8dfc30ede..afc7588f8306d 100644
--- a/lib/auth/native/boring.go
+++ b/lib/modules/boring.go
@@ -16,7 +16,7 @@
//go:build boringcrypto
-package native
+package modules
import "crypto/boring"
diff --git a/lib/modules/modules.go b/lib/modules/modules.go
index 69cb6704f8c9c..a93b359c3ac09 100644
--- a/lib/modules/modules.go
+++ b/lib/modules/modules.go
@@ -37,7 +37,6 @@ import (
"github.com/gravitational/teleport/api/types/accesslist"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/entitlements"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/automaticupgrades"
"github.com/gravitational/teleport/lib/tlsca"
)
@@ -407,7 +406,7 @@ func (p *defaultModules) SetFeatures(f Features) {
}
func (p *defaultModules) IsBoringBinary() bool {
- return native.IsBoringBinary()
+ return IsBoringBinary()
}
// AttestHardwareKey attests a hardware key.
diff --git a/lib/auth/native/notboring.go b/lib/modules/notboring.go
similarity index 85%
rename from lib/auth/native/notboring.go
rename to lib/modules/notboring.go
index 3fa57fb55e5cb..36cecbce41d72 100644
--- a/lib/auth/native/notboring.go
+++ b/lib/modules/notboring.go
@@ -16,12 +16,9 @@
//go:build !boringcrypto
-package native
+package modules
// IsBoringBinary checks if the binary was compiled with BoringCrypto.
-//
-// The boringcrypto GOEXPERIMENT always sets the boringcrypto build tag, so if
-// this is compiled in, we're not using BoringCrypto.
func IsBoringBinary() bool {
return false
}
diff --git a/lib/multiplexer/multiplexer_test.go b/lib/multiplexer/multiplexer_test.go
index 588d98a4da082..8a1d8c0cc4b79 100644
--- a/lib/multiplexer/multiplexer_test.go
+++ b/lib/multiplexer/multiplexer_test.go
@@ -20,8 +20,6 @@ package multiplexer
import (
"context"
- "crypto/rand"
- "crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
@@ -45,10 +43,9 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
- "github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/keys"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/httplib"
"github.com/gravitational/teleport/lib/jwt"
@@ -66,7 +63,7 @@ func TestMain(m *testing.M) {
// TestMux tests multiplexing protocols
// using the same listener.
func TestMux(t *testing.T) {
- _, signer, err := cert.CreateCertificate("foo", ssh.HostCert)
+ _, signer, err := cert.CreateTestEd25519Certificate("foo", ssh.HostCert)
require.NoError(t, err)
// TestMux tests basic use case of multiplexing TLS
@@ -736,22 +733,22 @@ func TestMux(t *testing.T) {
certPool.AppendCertsFromPEM(caCert)
// Sign server certificate.
- serverRSAKey, err := native.GenerateRSAPrivateKey()
+ serverKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
serverPEM, err := ca.GenerateCertificate(tlsca.CertificateRequest{
Subject: pkix.Name{CommonName: "localhost"},
- PublicKey: serverRSAKey.Public(),
+ PublicKey: serverKey.Public(),
NotAfter: time.Now().Add(time.Hour),
DNSNames: []string{"127.0.0.1"},
})
require.NoError(t, err)
- serverKeyPEM, err := keys.MarshalPrivateKey(serverRSAKey)
+ serverKeyPEM, err := keys.MarshalPrivateKey(serverKey)
require.NoError(t, err)
serverCert, err := tls.X509KeyPair(serverPEM, serverKeyPEM)
require.NoError(t, err)
// Sign client certificate with database access identity.
- clientRSAKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ clientKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
subject, err := (&tlsca.Identity{
Username: "alice",
@@ -763,11 +760,11 @@ func TestMux(t *testing.T) {
require.NoError(t, err)
clientPEM, err := ca.GenerateCertificate(tlsca.CertificateRequest{
Subject: subject,
- PublicKey: clientRSAKey.Public(),
+ PublicKey: clientKey.Public(),
NotAfter: time.Now().Add(time.Hour),
})
require.NoError(t, err)
- clientKeyPEM, err := keys.MarshalPrivateKey(clientRSAKey)
+ clientKeyPEM, err := keys.MarshalPrivateKey(clientKey)
require.NoError(t, err)
clientCert, err := tls.X509KeyPair(clientPEM, clientKeyPEM)
require.NoError(t, err)
@@ -1179,7 +1176,7 @@ func getTestCertCAsGetterAndSigner(t testing.TB, clusterName string) ([]byte, Ce
mockCAGetter := func(ctx context.Context, id types.CertAuthID, loadKeys bool) (types.CertAuthority, error) {
return ca, nil
}
- proxyPriv, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ proxyPriv, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
// Create host identity with role "Proxy"
diff --git a/lib/proxy/peer/helpers_test.go b/lib/proxy/peer/helpers_test.go
index 647ffbcea0277..f9a7b562c5fff 100644
--- a/lib/proxy/peer/helpers_test.go
+++ b/lib/proxy/peer/helpers_test.go
@@ -23,7 +23,6 @@ import (
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
- "encoding/pem"
"net"
"sync/atomic"
"testing"
@@ -37,8 +36,9 @@ import (
clientapi "github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
apiutils "github.com/gravitational/teleport/api/utils"
+ "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/lib/auth/authclient"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/tlsca"
@@ -156,7 +156,7 @@ func certFromIdentity(t *testing.T, ca *tlsca.CertAuthority, ident tlsca.Identit
subj, err := ident.Subject()
require.NoError(t, err)
- privateKey, err := native.GenerateRSAPrivateKey()
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
clock := clockwork.NewRealClock()
@@ -171,7 +171,8 @@ func certFromIdentity(t *testing.T, ca *tlsca.CertAuthority, ident tlsca.Identit
certBytes, err := ca.GenerateCertificate(request)
require.NoError(t, err)
- keyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
+ keyPEM, err := keys.MarshalPrivateKey(privateKey)
+ require.NoError(t, err)
cert, err := tls.X509KeyPair(certBytes, keyPEM)
require.NoError(t, err)
diff --git a/lib/reversetunnel/cache.go b/lib/reversetunnel/cache.go
index 2087ddd218684..afcbd9355153c 100644
--- a/lib/reversetunnel/cache.go
+++ b/lib/reversetunnel/cache.go
@@ -32,7 +32,6 @@ import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/sshutils"
"github.com/gravitational/teleport/lib/auth/authclient"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/utils"
@@ -94,12 +93,12 @@ func (c *certificateCache) generateHostCert(ctx context.Context, principals []st
}
if _, isRSA := hostKey.Public().(*rsa.PublicKey); isRSA {
- // Ensure the native package is precomputing RSA keys if we ever
- // generate one. [native.PrecomputeKeys] is idempotent.
+ // Start precomputing RSA keys if we ever generate one.
+ // [cryptosuites.PrecomputeRSAKeys] is idempotent.
// Doing this lazily easily handles changing signature algorithm suites
// and won't start precomputing keys if they are never needed (a major
// benefit in tests).
- native.PrecomputeKeys()
+ cryptosuites.PrecomputeRSAKeys()
}
sshPub, err := ssh.NewPublicKey(hostKey.Public())
diff --git a/lib/service/certreloader_test.go b/lib/service/certreloader_test.go
index e6b5faeb14172..0c40c91831687 100644
--- a/lib/service/certreloader_test.go
+++ b/lib/service/certreloader_test.go
@@ -30,7 +30,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/gravitational/teleport/lib/service/servicecfg"
- "github.com/gravitational/teleport/lib/utils"
+ "github.com/gravitational/teleport/lib/tlsca"
)
func TestCertReloader(t *testing.T) {
@@ -121,7 +121,7 @@ func TestCertReloader(t *testing.T) {
// Update c0 key, and partially update c0 cert.
key, crt := newCertKeyPair(t)
write(t, certs[0].PrivateKey, key)
- write(t, certs[0].Certificate, crt[0:1024])
+ write(t, certs[0].Certificate, crt[0:len(crt)/2])
},
certsReloadErrorAssert: require.Error,
certsAssert: func(t *testing.T, before []tls.Certificate, after []tls.Certificate) {
@@ -225,7 +225,7 @@ func newCertKeyPair(t *testing.T) ([]byte, []byte) {
Organization: []string{"teleport"},
CommonName: "teleport",
}
- key, crt, err := utils.GenerateSelfSignedSigningCert(entity, nil, time.Hour)
+ key, crt, err := tlsca.GenerateSelfSignedCA(entity, nil, time.Hour)
require.NoError(t, err)
return key, crt
}
diff --git a/lib/services/authority.go b/lib/services/authority.go
index b529c0c417920..74dec10149712 100644
--- a/lib/services/authority.go
+++ b/lib/services/authority.go
@@ -325,7 +325,7 @@ func (c HostCertParams) Check() error {
type UserCertParams struct {
// CASigner is the signer that will sign the public key of the user with the CA private key
CASigner ssh.Signer
- // PublicUserKey is the public key of the user
+ // PublicUserKey is the public key of the user in SSH authorized_keys format.
PublicUserKey []byte
// TTL defines how long a certificate is valid for
TTL time.Duration
diff --git a/lib/spacelift/token_validator_test.go b/lib/spacelift/token_validator_test.go
index 22c4379c9c08e..551b90d37f10e 100644
--- a/lib/spacelift/token_validator_test.go
+++ b/lib/spacelift/token_validator_test.go
@@ -20,8 +20,7 @@ package spacelift
import (
"context"
- "crypto/rand"
- "crypto/rsa"
+ "crypto"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -33,17 +32,20 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
type fakeIDP struct {
- t *testing.T
- signer jose.Signer
- privateKey *rsa.PrivateKey
- server *httptest.Server
+ t *testing.T
+ signer jose.Signer
+ publicKey crypto.PublicKey
+ server *httptest.Server
}
func newFakeIDP(t *testing.T) *fakeIDP {
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ // Spacelift uses RSA, prefer to test with it.
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
signer, err := jose.NewSigner(
@@ -53,9 +55,9 @@ func newFakeIDP(t *testing.T) *fakeIDP {
require.NoError(t, err)
f := &fakeIDP{
- signer: signer,
- privateKey: privateKey,
- t: t,
+ signer: signer,
+ publicKey: privateKey.Public(),
+ t: t,
}
providerMux := http.NewServeMux()
@@ -121,7 +123,7 @@ func (f *fakeIDP) handleJWKSEndpoint(w http.ResponseWriter, r *http.Request) {
jwks := jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
- Key: &f.privateKey.PublicKey,
+ Key: f.publicKey,
},
},
}
diff --git a/lib/srv/alpnproxy/helpers_test.go b/lib/srv/alpnproxy/helpers_test.go
index 19b0bebcee004..b4e9df20e83f0 100644
--- a/lib/srv/alpnproxy/helpers_test.go
+++ b/lib/srv/alpnproxy/helpers_test.go
@@ -20,12 +20,9 @@ package alpnproxy
import (
"context"
- "crypto/rand"
- "crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
- "encoding/pem"
"fmt"
"io"
"net"
@@ -39,8 +36,10 @@ import (
"github.com/stretchr/testify/require"
"github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/srv/alpnproxy/common"
"github.com/gravitational/teleport/lib/tlsca"
@@ -196,7 +195,7 @@ func mustGenCertSignedWithCA(t *testing.T, ca *tlsca.CertAuthority, opts ...sign
subj, err := options.identity.Subject()
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
tlsCert, err := ca.GenerateCertificate(tlsca.CertificateRequest{
@@ -208,8 +207,8 @@ func mustGenCertSignedWithCA(t *testing.T, ca *tlsca.CertAuthority, opts ...sign
})
require.NoError(t, err)
- keyRaw := x509.MarshalPKCS1PrivateKey(privateKey)
- keyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyRaw})
+ keyPEM, err := keys.MarshalPrivateKey(privateKey)
+ require.NoError(t, err)
cert, err := tls.X509KeyPair(tlsCert, keyPEM)
require.NoError(t, err)
leaf, err := utils.TLSCertLeaf(cert)
diff --git a/lib/srv/app/server_test.go b/lib/srv/app/server_test.go
index 32932340f4d84..ee9c01accf1fb 100644
--- a/lib/srv/app/server_test.go
+++ b/lib/srv/app/server_test.go
@@ -55,7 +55,6 @@ import (
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/authz"
"github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/events"
@@ -73,7 +72,7 @@ import (
func TestMain(m *testing.M) {
utils.InitLoggerForTests()
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
modules.SetInsecureTestMode(true)
os.Exit(m.Run())
}
diff --git a/lib/srv/authhandlers_test.go b/lib/srv/authhandlers_test.go
index 750ebaf522770..78856817654a9 100644
--- a/lib/srv/authhandlers_test.go
+++ b/lib/srv/authhandlers_test.go
@@ -32,8 +32,8 @@ import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/wrappers"
"github.com/gravitational/teleport/api/utils/sshutils"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/auth/testauthority"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/events/eventstest"
"github.com/gravitational/teleport/lib/services"
)
@@ -139,8 +139,7 @@ func TestRBAC(t *testing.T) {
}
// create User CA
- userTA := testauthority.New()
- userCAPriv, err := userTA.GeneratePrivateKey()
+ userCAPriv, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
userCA, err := types.NewCertAuthority(types.CertAuthoritySpecV2{
Type: types.UserCA,
@@ -211,7 +210,7 @@ func TestRBAC(t *testing.T) {
caSigner, err := ssh.NewSignerFromKey(userCAPriv)
require.NoError(t, err)
keygen := testauthority.New()
- privateKey, err := native.GeneratePrivateKey()
+ privateKey, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
c, err := keygen.GenerateUserCert(services.UserCertParams{
@@ -243,8 +242,7 @@ func TestRBACJoinMFA(t *testing.T) {
const username = "testuser"
// create User CA
- userTA := testauthority.New()
- userCAPriv, err := userTA.GeneratePrivateKey()
+ userCAPriv, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
userCA, err := types.NewCertAuthority(types.CertAuthoritySpecV2{
Type: types.UserCA,
@@ -381,15 +379,15 @@ func TestRBACJoinMFA(t *testing.T) {
accessPoint.authPref = tt.authPref
// create SSH certificate
- caSigner, err := ssh.NewSignerFromKey(userCAPriv)
+ caSigner, err := ssh.NewSignerFromSigner(userCAPriv.Signer)
require.NoError(t, err)
- keygen := testauthority.New()
- privateKey, err := native.GeneratePrivateKey()
+ privateKey, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
+ keygen := testauthority.New()
c, err := keygen.GenerateUserCert(services.UserCertParams{
CASigner: caSigner,
- PublicUserKey: ssh.MarshalAuthorizedKey(privateKey.SSHPublicKey()),
+ PublicUserKey: privateKey.MarshalSSHPublicKey(),
Username: username,
AllowedLogins: []string{username},
Traits: wrappers.Traits{
diff --git a/lib/srv/db/access_test.go b/lib/srv/db/access_test.go
index 30d4ef22c172a..37848ea294c8e 100644
--- a/lib/srv/db/access_test.go
+++ b/lib/srv/db/access_test.go
@@ -60,10 +60,10 @@ import (
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/authz"
clients "github.com/gravitational/teleport/lib/cloud"
"github.com/gravitational/teleport/lib/cloud/mocks"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
libevents "github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/events/eventstest"
@@ -101,7 +101,7 @@ import (
func TestMain(m *testing.M) {
utils.InitLoggerForTests()
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
modules.SetInsecureTestMode(true)
registerTestSnowflakeEngine()
registerTestElasticsearchEngine()
diff --git a/lib/srv/forward/sshserver.go b/lib/srv/forward/sshserver.go
index 8fd276932becf..7b2cf1b83fd3b 100644
--- a/lib/srv/forward/sshserver.go
+++ b/lib/srv/forward/sshserver.go
@@ -46,6 +46,7 @@ import (
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/bpf"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/integrations/awsoidc"
"github.com/gravitational/teleport/lib/service/servicecfg"
@@ -698,16 +699,27 @@ func (s *Server) sendSSHPublicKeyToTarget(ctx context.Context) (ssh.Signer, erro
return nil, trace.BadParameter("failed to create an aws client to send ssh public key: %v", err)
}
- sshSigner, err := awsoidc.SendSSHPublicKeyToEC2(ctx, sendSSHClient, awsoidc.SendSSHPublicKeyToEC2Request{
+ sshKey, err := cryptosuites.GenerateKey(ctx,
+ cryptosuites.GetCurrentSuiteFromAuthPreference(s.GetAccessPoint()),
+ cryptosuites.EC2InstanceConnect)
+ if err != nil {
+ return nil, trace.Wrap(err, "generating SSH key")
+ }
+ sshSigner, err := ssh.NewSignerFromSigner(sshKey)
+ if err != nil {
+ return nil, trace.Wrap(err, "creating SSH signer")
+ }
+
+ if err := awsoidc.SendSSHPublicKeyToEC2(ctx, sendSSHClient, awsoidc.SendSSHPublicKeyToEC2Request{
InstanceID: awsInfo.InstanceID,
EC2SSHLoginUser: s.identityContext.Login,
- })
- if err != nil {
+ PublicKey: sshSigner.PublicKey(),
+ }); err != nil {
return nil, trace.BadParameter("send ssh public key failed for instance %s: %v", awsInfo.InstanceID, err)
}
// This is the SSH Signer that the client must use to connect to the EC2.
- // This signer generates trusted keys, because the public key was sent to the target EC2 host.
+ // This signer is trusted because the public key was sent to the target EC2 host.
return sshSigner, nil
}
diff --git a/lib/srv/forward/sshserver_test.go b/lib/srv/forward/sshserver_test.go
index c4f4700f8b65c..98e409e63b692 100644
--- a/lib/srv/forward/sshserver_test.go
+++ b/lib/srv/forward/sshserver_test.go
@@ -20,6 +20,7 @@ package forward
import (
"context"
+ "crypto/ed25519"
"crypto/rand"
"errors"
"os/user"
@@ -30,7 +31,9 @@ import (
"golang.org/x/crypto/ssh"
"github.com/gravitational/teleport"
+ "github.com/gravitational/teleport/api/utils/keys"
apisshutils "github.com/gravitational/teleport/api/utils/sshutils"
+ "github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/srv"
"github.com/gravitational/teleport/lib/sshutils"
"github.com/gravitational/teleport/lib/utils"
@@ -53,7 +56,7 @@ func TestSignersWithSHA1Fallback(t *testing.T) {
assertSHA1Signer := func(t *testing.T, signer ssh.Signer) {
require.Equal(t, ssh.CertAlgoRSAv01, signer.PublicKey().Type())
- // We should not be able to case the signer to ssh.AlgorithmSigner.
+ // We should not be able to cast the signer to ssh.AlgorithmSigner.
// Otherwise, x/crypto will use SHA-2-512 for signing.
_, ok := signer.(ssh.AlgorithmSigner)
require.False(t, ok)
@@ -70,13 +73,15 @@ func TestSignersWithSHA1Fallback(t *testing.T) {
want func(t *testing.T, got []ssh.Signer)
}{
{
- name: "simple",
+ name: "RSA host certificate",
signersCb: func(t *testing.T) []ssh.Signer {
- signer, err := apisshutils.MakeTestSSHCA()
+ caSigner, err := apisshutils.MakeTestSSHCA()
require.NoError(t, err)
- cert, err := apisshutils.MakeRealHostCert(signer)
+ hostKey, err := keys.ParsePrivateKey(fixtures.PEMBytes["rsa"])
require.NoError(t, err)
- return []ssh.Signer{cert}
+ hostCert, err := apisshutils.MakeRealHostCertWithKey(hostKey.Signer, caSigner)
+ require.NoError(t, err)
+ return []ssh.Signer{hostCert}
},
want: func(t *testing.T, signers []ssh.Signer) {
// We expect 2 certificates, order matters.
@@ -86,11 +91,13 @@ func TestSignersWithSHA1Fallback(t *testing.T) {
},
},
{
- name: "public key only",
+ name: "RSA host public key",
signersCb: func(t *testing.T) []ssh.Signer {
- signer, err := apisshutils.MakeTestSSHCA()
+ hostKey, err := keys.ParsePrivateKey(fixtures.PEMBytes["rsa"])
+ require.NoError(t, err)
+ hostSigner, err := ssh.NewSignerFromSigner(hostKey.Signer)
require.NoError(t, err)
- return []ssh.Signer{signer}
+ return []ssh.Signer{hostSigner}
},
want: func(t *testing.T, signers []ssh.Signer) {
// public key should not be copied
@@ -98,6 +105,34 @@ func TestSignersWithSHA1Fallback(t *testing.T) {
require.Equal(t, ssh.KeyAlgoRSA, signers[0].PublicKey().Type())
},
},
+ {
+ name: "Ed25519 host certificate",
+ signersCb: func(t *testing.T) []ssh.Signer {
+ caSigner, err := apisshutils.MakeTestSSHCA()
+ require.NoError(t, err)
+ hostCert, err := apisshutils.MakeRealHostCert(caSigner)
+ require.NoError(t, err)
+ return []ssh.Signer{hostCert}
+ },
+ want: func(t *testing.T, signers []ssh.Signer) {
+ require.Len(t, signers, 1)
+ require.Equal(t, ssh.CertAlgoED25519v01, signers[0].PublicKey().Type())
+ },
+ },
+ {
+ name: "Ed25519 host key",
+ signersCb: func(t *testing.T) []ssh.Signer {
+ _, hostKey, err := ed25519.GenerateKey(rand.Reader)
+ require.NoError(t, err)
+ hostSigner, err := ssh.NewSignerFromSigner(hostKey)
+ require.NoError(t, err)
+ return []ssh.Signer{hostSigner}
+ },
+ want: func(t *testing.T, signers []ssh.Signer) {
+ require.Len(t, signers, 1)
+ require.Equal(t, ssh.KeyAlgoED25519, signers[0].PublicKey().Type())
+ },
+ },
}
for _, tt := range tests {
diff --git a/lib/srv/transport/transportv1/transport_test.go b/lib/srv/transport/transportv1/transport_test.go
index 22a5a82797092..e45dc31194d47 100644
--- a/lib/srv/transport/transportv1/transport_test.go
+++ b/lib/srv/transport/transportv1/transport_test.go
@@ -20,10 +20,6 @@ package transportv1
import (
"context"
- "crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "encoding/pem"
"errors"
"fmt"
"io"
@@ -48,6 +44,7 @@ import (
streamutils "github.com/gravitational/teleport/api/utils/grpc/stream"
"github.com/gravitational/teleport/lib/agentless"
"github.com/gravitational/teleport/lib/authz"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/teleagent"
"github.com/gravitational/teleport/lib/utils"
@@ -834,13 +831,11 @@ func (s *sshServer) Stop() error {
}
func generateSigner(t *testing.T, keyring agent.Agent) ssh.Signer {
- private, err := rsa.GenerateKey(rand.Reader, 2048)
+ private, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
- block := &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: x509.MarshalPKCS1PrivateKey(private),
- }
+ signer, err := ssh.NewSignerFromSigner(private)
+ require.NoError(t, err)
require.NoError(t, keyring.Add(agent.AddedKey{
PrivateKey: private,
@@ -848,10 +843,6 @@ func generateSigner(t *testing.T, keyring agent.Agent) ssh.Signer {
LifetimeSecs: math.MaxUint32,
}))
- privatePEM := pem.EncodeToMemory(block)
- signer, err := ssh.ParsePrivateKey(privatePEM)
- require.NoError(t, err)
-
return signer
}
diff --git a/lib/sshutils/server_test.go b/lib/sshutils/server_test.go
index 704164f3d003b..7b95d3ced55c0 100644
--- a/lib/sshutils/server_test.go
+++ b/lib/sshutils/server_test.go
@@ -43,7 +43,7 @@ func TestMain(m *testing.M) {
func TestStartStop(t *testing.T) {
t.Parallel()
- _, signer, err := cert.CreateCertificate("foo", ssh.HostCert)
+ _, signer, err := cert.CreateTestEd25519Certificate("foo", ssh.HostCert)
require.NoError(t, err)
called := false
@@ -95,7 +95,7 @@ func TestStartStop(t *testing.T) {
func TestShutdown(t *testing.T) {
t.Parallel()
- _, signer, err := cert.CreateCertificate("foo", ssh.HostCert)
+ _, signer, err := cert.CreateTestEd25519Certificate("foo", ssh.HostCert)
require.NoError(t, err)
closeContext, cancel := context.WithCancel(context.TODO())
@@ -151,7 +151,7 @@ func TestShutdown(t *testing.T) {
func TestConfigureCiphers(t *testing.T) {
t.Parallel()
- _, signer, err := cert.CreateCertificate("foo", ssh.HostCert)
+ _, signer, err := cert.CreateTestEd25519Certificate("foo", ssh.HostCert)
require.NoError(t, err)
fn := NewChanHandlerFunc(func(_ context.Context, _ *ConnectionContext, nch ssh.NewChannel) {
@@ -200,13 +200,13 @@ func TestConfigureCiphers(t *testing.T) {
func TestHostSignerFIPS(t *testing.T) {
t.Parallel()
- _, signer, err := cert.CreateCertificate("foo", ssh.HostCert)
+ _, signer, err := cert.CreateTestRSACertificate("foo", ssh.HostCert)
require.NoError(t, err)
- _, ellipticSigner, err := cert.CreateEllipticCertificate("foo", ssh.HostCert)
+ _, ellipticSigner, err := cert.CreateTestECDSACertificate("foo", ssh.HostCert)
require.NoError(t, err)
- _, ed25519Signer, err := cert.CreateEd25519Certificate("foo", ssh.HostCert)
+ _, ed25519Signer, err := cert.CreateTestEd25519Certificate("foo", ssh.HostCert)
require.NoError(t, err)
fn := NewChanHandlerFunc(func(_ context.Context, _ *ConnectionContext, nch ssh.NewChannel) {
@@ -286,10 +286,10 @@ func pass(need string) PasswordFunc {
func TestDynamicHostSigners(t *testing.T) {
t.Parallel()
- certFoo, signerFoo, err := cert.CreateCertificate("foo", ssh.HostCert)
+ certFoo, signerFoo, err := cert.CreateTestEd25519Certificate("foo", ssh.HostCert)
require.NoError(t, err)
- certBar, signerBar, err := cert.CreateCertificate("bar", ssh.HostCert)
+ certBar, signerBar, err := cert.CreateTestEd25519Certificate("bar", ssh.HostCert)
require.NoError(t, err)
var activeSigner atomic.Pointer[ssh.Signer]
diff --git a/lib/tbot/tbot_test.go b/lib/tbot/tbot_test.go
index 4104c9b95d705..0a4659246c1ba 100644
--- a/lib/tbot/tbot_test.go
+++ b/lib/tbot/tbot_test.go
@@ -50,7 +50,7 @@ import (
"github.com/gravitational/teleport/api/utils/sshutils"
"github.com/gravitational/teleport/integration/helpers"
"github.com/gravitational/teleport/lib/auth/authclient"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/service"
"github.com/gravitational/teleport/lib/service/servicecfg"
@@ -68,7 +68,7 @@ import (
func TestMain(m *testing.M) {
utils.InitLoggerForTests()
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
os.Exit(m.Run())
}
diff --git a/lib/terraformcloud/token_validator_test.go b/lib/terraformcloud/token_validator_test.go
index c879cfae73715..75541d77ec2e0 100644
--- a/lib/terraformcloud/token_validator_test.go
+++ b/lib/terraformcloud/token_validator_test.go
@@ -20,8 +20,7 @@ package terraformcloud
import (
"context"
- "crypto/rand"
- "crypto/rsa"
+ "crypto"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -32,18 +31,21 @@ import (
"github.com/go-jose/go-jose/v3/jwt"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
type fakeIDP struct {
- t *testing.T
- signer jose.Signer
- privateKey *rsa.PrivateKey
- server *httptest.Server
- audience string
+ t *testing.T
+ signer jose.Signer
+ publicKey crypto.PublicKey
+ server *httptest.Server
+ audience string
}
func newFakeIDP(t *testing.T, audience string) *fakeIDP {
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ // Terraform Cloud uses RSA, prefer to test with it.
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
signer, err := jose.NewSigner(
@@ -53,10 +55,10 @@ func newFakeIDP(t *testing.T, audience string) *fakeIDP {
require.NoError(t, err)
f := &fakeIDP{
- signer: signer,
- privateKey: privateKey,
- t: t,
- audience: audience,
+ signer: signer,
+ publicKey: privateKey.Public(),
+ t: t,
+ audience: audience,
}
providerMux := http.NewServeMux()
@@ -119,7 +121,7 @@ func (f *fakeIDP) handleJWKSEndpoint(w http.ResponseWriter, r *http.Request) {
jwks := jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
- Key: &f.privateKey.PublicKey,
+ Key: f.publicKey,
},
},
}
diff --git a/lib/tlsca/ca_test.go b/lib/tlsca/ca_test.go
index d84dc20fdc71c..91b4db336e173 100644
--- a/lib/tlsca/ca_test.go
+++ b/lib/tlsca/ca_test.go
@@ -19,8 +19,6 @@
package tlsca
import (
- "crypto/rand"
- "crypto/rsa"
"crypto/tls"
"crypto/x509/pkix"
"encoding/asn1"
@@ -36,9 +34,9 @@ import (
"github.com/stretchr/testify/require"
"github.com/gravitational/teleport"
- "github.com/gravitational/teleport/api/constants"
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/api/utils/keys"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/fixtures"
)
@@ -86,7 +84,7 @@ func TestPrincipals(t *testing.T) {
ca, err := test.createFunc()
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
hostnames := []string{"localhost", "example.com"}
@@ -122,7 +120,7 @@ func TestRenewableIdentity(t *testing.T) {
ca, err := FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
identity := Identity{
@@ -159,7 +157,7 @@ func TestKubeExtensions(t *testing.T) {
ca, err := FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
expires := clock.Now().Add(time.Hour)
@@ -209,7 +207,7 @@ func TestDatabaseExtensions(t *testing.T) {
ca, err := FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
expires := clock.Now().Add(time.Hour)
@@ -254,7 +252,7 @@ func TestAzureExtensions(t *testing.T) {
ca, err := FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
expires := clock.Now().Add(time.Hour)
@@ -360,7 +358,7 @@ func TestGCPExtensions(t *testing.T) {
ca, err := FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
expires := clock.Now().Add(time.Hour)
diff --git a/lib/tpm/tpm_simulator_test.go b/lib/tpm/tpm_simulator_test.go
index a71fce746569d..c84ab6d9b61ca 100644
--- a/lib/tpm/tpm_simulator_test.go
+++ b/lib/tpm/tpm_simulator_test.go
@@ -106,6 +106,7 @@ func TestWithSimulator(t *testing.T) {
NotBefore: time.Now().Add(-time.Hour),
NotAfter: time.Now().Add(time.Hour),
}
+ //nolint:forbidigo // Generating large RSA key allowed for TPM simulator.
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
require.NoError(t, err)
caBytes, err := x509.CreateCertificate(
diff --git a/lib/utils/cert/certs.go b/lib/utils/cert/certs.go
index cad4d986cb64d..47de43a21a42f 100644
--- a/lib/utils/cert/certs.go
+++ b/lib/utils/cert/certs.go
@@ -19,85 +19,40 @@
package cert
import (
- "crypto"
- "crypto/ecdsa"
- "crypto/ed25519"
- "crypto/elliptic"
"crypto/rand"
"time"
"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
- "github.com/gravitational/teleport/lib/auth/native"
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
-// CreateCertificate creates a valid 2048-bit RSA certificate.
-func CreateCertificate(principal string, certType uint32) (*ssh.Certificate, ssh.Signer, error) {
- // Create RSA key for CA and certificate to be signed by CA.
- caKey, err := native.GenerateRSAPrivateKey()
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
- key, err := native.GenerateRSAPrivateKey()
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- cert, certSigner, err := createCertificate(principal, certType, caKey, key)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- return cert, certSigner, nil
+// CreateTestRSACertificate creates a valid 2048-bit RSA certificate.
+func CreateTestRSACertificate(principal string, certType uint32) (*ssh.Certificate, ssh.Signer, error) {
+ return createCertificate(principal, certType, cryptosuites.RSA2048)
}
-// CreateEllipticCertificate creates a valid ECDSA P-256 certificate.
-func CreateEllipticCertificate(principal string, certType uint32) (*ssh.Certificate, ssh.Signer, error) {
- // Create ECDSA key for CA and certificate to be signed by CA.
- caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- cert, certSigner, err := createCertificate(principal, certType, caKey, key)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- return cert, certSigner, nil
+// CreateTestECDSACertificate creates a valid ECDSA P-256 certificate.
+func CreateTestECDSACertificate(principal string, certType uint32) (*ssh.Certificate, ssh.Signer, error) {
+ return createCertificate(principal, certType, cryptosuites.ECDSAP256)
}
-// CreateEd25519Certificate creates an Ed25519 certificate which should be
+// CreateTestEd25519Certificate creates an Ed25519 certificate which should be
// rejected in FIPS mode.
-func CreateEd25519Certificate(principal string, certType uint32) (*ssh.Certificate, ssh.Signer, error) {
- // Create Ed25519 key for CA and certificate to be signed by CA.
- _, caKey, err := ed25519.GenerateKey(rand.Reader)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
- _, key, err := ed25519.GenerateKey(rand.Reader)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- cert, certSigner, err := createCertificate(principal, certType, caKey, key)
- if err != nil {
- return nil, nil, trace.Wrap(err)
- }
-
- return cert, certSigner, nil
+func CreateTestEd25519Certificate(principal string, certType uint32) (*ssh.Certificate, ssh.Signer, error) {
+ return createCertificate(principal, certType, cryptosuites.Ed25519)
}
// createCertificate creates a SSH certificate for the given key signed by the
// given CA key. This function exists here to allow easy key generation for
// some of the more core packages like "sshutils".
-func createCertificate(principal string, certType uint32, caKey crypto.Signer, key crypto.Signer) (*ssh.Certificate, ssh.Signer, error) {
+func createCertificate(principal string, certType uint32, algo cryptosuites.Algorithm) (*ssh.Certificate, ssh.Signer, error) {
// Create CA.
+ caKey, err := cryptosuites.GenerateKeyWithAlgorithm(algo)
+ if err != nil {
+ return nil, nil, trace.Wrap(err)
+ }
caPublicKey, err := ssh.NewPublicKey(caKey.Public())
if err != nil {
return nil, nil, trace.Wrap(err)
@@ -108,6 +63,10 @@ func createCertificate(principal string, certType uint32, caKey crypto.Signer, k
}
// Create key.
+ key, err := cryptosuites.GenerateKeyWithAlgorithm(algo)
+ if err != nil {
+ return nil, nil, trace.Wrap(err)
+ }
publicKey, err := ssh.NewPublicKey(key.Public())
if err != nil {
return nil, nil, trace.Wrap(err)
diff --git a/lib/utils/certs.go b/lib/utils/certs.go
index c2f3b96c5b482..88244491bb95c 100644
--- a/lib/utils/certs.go
+++ b/lib/utils/certs.go
@@ -30,9 +30,9 @@ import (
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
- "github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/api/utils/tlsutils"
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
// ParseKeyStorePEM parses signing key store from PEM encoded key pair
@@ -62,16 +62,24 @@ type KeyStore struct {
cert []byte
}
+// GetKeyPair implements goxmldsig.X509KeyPair.
func (ks *KeyStore) GetKeyPair() (*rsa.PrivateKey, []byte, error) {
return ks.privateKey, ks.cert, nil
}
-// GenerateSelfSignedSigningCert generates self-signed certificate used for digital signatures
-func GenerateSelfSignedSigningCert(entity pkix.Name, dnsNames []string, ttl time.Duration) ([]byte, []byte, error) {
- priv, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+// GenerateSelfSignedSigningCert is an alias of GenerateRSASelfSignedSigningCert
+// used due to references in teleport.e.
+var GenerateSelfSignedSigningCert = GenerateRSASelfSignedSigningCert
+
+// GenerateRSASelfSignedSigningCert generates an RSA self-signed certificate used
+// for digital signatures.
+// This should only be used for the SAML implementation and tests.
+func GenerateRSASelfSignedSigningCert(entity pkix.Name, dnsNames []string, ttl time.Duration) ([]byte, []byte, error) {
+ priv, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
if err != nil {
return nil, nil, trace.Wrap(err)
}
+ rsaPriv := priv.(*rsa.PrivateKey)
// to account for clock skew
notBefore := time.Now().Add(-2 * time.Minute)
notAfter := notBefore.Add(ttl)
@@ -93,12 +101,12 @@ func GenerateSelfSignedSigningCert(entity pkix.Name, dnsNames []string, ttl time
DNSNames: dnsNames,
}
- derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &rsaPriv.PublicKey, rsaPriv)
if err != nil {
return nil, nil, trace.Wrap(err)
}
- keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
+ keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rsaPriv)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
return keyPEM, certPEM, nil
diff --git a/lib/utils/chconn_test.go b/lib/utils/chconn_test.go
index 7a42fe0f663d2..44a3ae314dee7 100644
--- a/lib/utils/chconn_test.go
+++ b/lib/utils/chconn_test.go
@@ -19,8 +19,6 @@
package utils
import (
- "crypto/rand"
- "crypto/rsa"
"io"
"net"
"os"
@@ -30,9 +28,8 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
- "github.com/gravitational/teleport/api/constants"
- "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/api/utils/sshutils"
+ "github.com/gravitational/teleport/lib/cryptosuites"
)
// TestChConn validates that reads from the channel connection can be
@@ -92,13 +89,10 @@ func startSSHServer(t *testing.T, listener net.Listener, sshConnCh chan<- sshCon
require.NoError(t, err)
t.Cleanup(func() { nConn.Close() })
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
- private, err := keys.MarshalPrivateKey(privateKey)
- require.NoError(t, err)
-
- signer, err := ssh.ParsePrivateKey(private)
+ signer, err := ssh.NewSignerFromSigner(privateKey)
require.NoError(t, err)
config := &ssh.ServerConfig{NoClientAuth: true}
diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go
index ad16a9c658dc8..5e3fea922d245 100644
--- a/lib/web/apiserver_test.go
+++ b/lib/web/apiserver_test.go
@@ -103,7 +103,6 @@ import (
"github.com/gravitational/teleport/lib/auth/authclient"
tlsutils "github.com/gravitational/teleport/lib/auth/keygen"
"github.com/gravitational/teleport/lib/auth/mocku2f"
- "github.com/gravitational/teleport/lib/auth/native"
"github.com/gravitational/teleport/lib/auth/state"
"github.com/gravitational/teleport/lib/auth/testauthority"
wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
@@ -180,7 +179,7 @@ func TestMain(m *testing.M) {
srv.RunAndExit(os.Args[1])
return
}
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
// Otherwise run tests as normal.
code := m.Run()
diff --git a/tool/tbot/kube_test.go b/tool/tbot/kube_test.go
index 09a29f6c38c9e..c0f2a45c4ec76 100644
--- a/tool/tbot/kube_test.go
+++ b/tool/tbot/kube_test.go
@@ -19,8 +19,6 @@
package main
import (
- "crypto/rand"
- "crypto/rsa"
"crypto/x509/pkix"
"encoding/json"
"testing"
@@ -30,9 +28,9 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
- "github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/identityfile"
"github.com/gravitational/teleport/api/utils/keys"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/tlsca"
)
@@ -42,7 +40,7 @@ func TestGetKubeCredentialData(t *testing.T) {
ca, err := tlsca.FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.ECDSAP256)
require.NoError(t, err)
clock := clockwork.NewFakeClock()
diff --git a/tool/tctl/common/admin_action_test.go b/tool/tctl/common/admin_action_test.go
index 199e1901e0c52..4fcdd8661d522 100644
--- a/tool/tctl/common/admin_action_test.go
+++ b/tool/tctl/common/admin_action_test.go
@@ -40,7 +40,6 @@ import (
"github.com/gravitational/teleport/api/mfa"
"github.com/gravitational/teleport/api/types"
apiutils "github.com/gravitational/teleport/api/utils"
- "github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
@@ -453,11 +452,7 @@ func (s *adminActionTestSuite) testUserGroups(t *testing.T) {
func (s *adminActionTestSuite) testCertAuthority(t *testing.T) {
ctx := context.Background()
- sshSigner, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.Ed25519)
- require.NoError(t, err)
- sshKey, err := keys.NewSoftwarePrivateKey(sshSigner)
- require.NoError(t, err)
- sshKeyPEM, err := sshKey.MarshalSSHPrivateKey()
+ sshKey, err := cryptosuites.GeneratePrivateKeyWithAlgorithm(cryptosuites.Ed25519)
require.NoError(t, err)
tlsKey, cert, err := tlsca.GenerateSelfSignedCA(pkix.Name{CommonName: "Host"}, nil, time.Minute)
@@ -468,9 +463,8 @@ func (s *adminActionTestSuite) testCertAuthority(t *testing.T) {
ClusterName: "clustername",
ActiveKeys: types.CAKeySet{
SSH: []*types.SSHKeyPair{{
- PrivateKey: sshKeyPEM,
- PrivateKeyType: types.PrivateKeyType_RAW,
- PublicKey: sshKey.MarshalSSHPublicKey(),
+ PrivateKey: sshKey.PrivateKeyPEM(),
+ PublicKey: sshKey.MarshalSSHPublicKey(),
}},
TLS: []*types.TLSKeyPair{{
Cert: cert,
diff --git a/tool/tsh/common/db_test.go b/tool/tsh/common/db_test.go
index 7ae5ba046f8b8..5502102ab2459 100644
--- a/tool/tsh/common/db_test.go
+++ b/tool/tsh/common/db_test.go
@@ -21,8 +21,6 @@ package common
import (
"bytes"
"context"
- "crypto/rand"
- "crypto/rsa"
"encoding/pem"
"fmt"
"os"
@@ -42,6 +40,7 @@ import (
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/client"
+ "github.com/gravitational/teleport/lib/cryptosuites"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/modules"
@@ -908,7 +907,7 @@ func TestDBInfoHasChanged(t *testing.T) {
ca, err := tlsca.FromKeys([]byte(fixtures.TLSCACertPEM), []byte(fixtures.TLSCAKeyPEM))
require.NoError(t, err)
- privateKey, err := rsa.GenerateKey(rand.Reader, constants.RSAKeySize)
+ privateKey, err := cryptosuites.GenerateKeyWithAlgorithm(cryptosuites.RSA2048)
require.NoError(t, err)
for _, tc := range tests {
diff --git a/tool/tsh/common/tsh_test.go b/tool/tsh/common/tsh_test.go
index 609c8a827033b..b4d1af2e35cf6 100644
--- a/tool/tsh/common/tsh_test.go
+++ b/tool/tsh/common/tsh_test.go
@@ -76,7 +76,6 @@ import (
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/auth/mocku2f"
- "github.com/gravitational/teleport/lib/auth/native"
wancli "github.com/gravitational/teleport/lib/auth/webauthncli"
wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
"github.com/gravitational/teleport/lib/backend"
@@ -127,7 +126,7 @@ func TestMain(m *testing.M) {
modules.SetInsecureTestMode(true)
utils.InitLoggerForTests()
- native.PrecomputeTestKeys(m)
+ cryptosuites.PrecomputeRSATestKeys(m)
os.Exit(m.Run())
}