From 99132355425343a5a534248f29b64a456c69aa28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deluan=20Quint=C3=A3o?= Date: Fri, 28 Nov 2025 17:08:34 -0500 Subject: [PATCH] fix(server): improve error message for encrypted TLS private keys (#4742) Added TLS certificate validation that detects encrypted (password-protected) private keys and provides a clear error message with instructions on how to decrypt them using openssl. This addresses user confusion when Go's standard library fails with the cryptic 'tls: failed to parse private key' error. Changes: - Added validateTLSCertificates function to validate certs before server start - Added isEncryptedPEM helper to detect both PKCS#8 and legacy encrypted keys - Added comprehensive tests for TLS validation including encrypted key detection - Added integration test that starts server with TLS and verifies HTTPS works - Added test certificates (valid for 100 years) with SAN for localhost Signed-off-by: Deluan --- server/server.go | 75 ++++++++- server/server_test.go | 150 ++++++++++++++++++ server/testdata/test_cert.pem | 23 +++ server/testdata/test_cert_encrypted.pem | 22 +++ server/testdata/test_key.pem | 28 ++++ server/testdata/test_key_encrypted.pem | 30 ++++ server/testdata/test_key_encrypted_legacy.pem | 30 ++++ 7 files changed, 352 insertions(+), 6 deletions(-) create mode 100644 server/testdata/test_cert.pem create mode 100644 server/testdata/test_cert_encrypted.pem create mode 100644 server/testdata/test_key.pem create mode 100644 server/testdata/test_key_encrypted.pem create mode 100644 server/testdata/test_key_encrypted_legacy.pem diff --git a/server/server.go b/server/server.go index 49391e2b6..39475a225 100644 --- a/server/server.go +++ b/server/server.go @@ -1,8 +1,11 @@ package server import ( + "bytes" "cmp" "context" + "crypto/tls" + "encoding/pem" "errors" "fmt" "net" @@ -69,6 +72,13 @@ func (s *Server) Run(ctx context.Context, addr string, port int, tlsCert string, // Determine if TLS is enabled tlsEnabled := tlsCert != "" && tlsKey != "" + // Validate TLS certificates before starting the server + if tlsEnabled { + if err := validateTLSCertificates(tlsCert, tlsKey); err != nil { + return err + } + } + // Create a listener based on the address type (either Unix socket or TCP) var listener net.Listener var err error @@ -89,17 +99,17 @@ func (s *Server) Run(ctx context.Context, addr string, port int, tlsCert string, // Start the server in a new goroutine and send an error signal to errC if there's an error errC := make(chan error) go func() { + var err error if tlsEnabled { // Start the HTTPS server log.Info("Starting server with TLS (HTTPS) enabled", "tlsCert", tlsCert, "tlsKey", tlsKey) - if err := server.ServeTLS(listener, tlsCert, tlsKey); !errors.Is(err, http.ErrServerClosed) { - errC <- err - } + err = server.ServeTLS(listener, tlsCert, tlsKey) } else { // Start the HTTP server - if err := server.Serve(listener); !errors.Is(err, http.ErrServerClosed) { - errC <- err - } + err = server.Serve(listener) + } + if !errors.Is(err, http.ErrServerClosed) { + errC <- err } }() @@ -249,3 +259,56 @@ func AbsoluteURL(r *http.Request, u string, params url.Values) string { } return buildUrl.String() } + +// validateTLSCertificates validates the TLS certificate and key files before starting the server. +// It provides detailed error messages for common issues like encrypted private keys. +func validateTLSCertificates(certFile, keyFile string) error { + // Read the key file to check for encryption + keyData, err := os.ReadFile(keyFile) + if err != nil { + return fmt.Errorf("reading TLS key file: %w", err) + } + + // Parse PEM blocks and check for encryption + block, _ := pem.Decode(keyData) + if block == nil { + return errors.New("TLS key file does not contain a valid PEM block") + } + + // Check for encrypted private key indicators + if isEncryptedPEM(block, keyData) { + return errors.New("TLS private key is encrypted (password-protected). " + + "Navidrome does not support encrypted private keys. " + + "Please decrypt your key using: openssl pkey -in -out ") + } + + // Try to load the certificate pair to validate it + _, err = tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return fmt.Errorf("loading TLS certificate/key pair: %w", err) + } + + return nil +} + +// isEncryptedPEM checks if a PEM block represents an encrypted private key. +func isEncryptedPEM(block *pem.Block, rawData []byte) bool { + // Check for PKCS#8 encrypted format (BEGIN ENCRYPTED PRIVATE KEY) + if block.Type == "ENCRYPTED PRIVATE KEY" { + return true + } + + // Check for legacy encrypted format with Proc-Type header + if block.Headers != nil { + if procType, ok := block.Headers["Proc-Type"]; ok && strings.Contains(procType, "ENCRYPTED") { + return true + } + } + + // Also check raw data for DEK-Info header (in case pem.Decode doesn't parse headers correctly) + if bytes.Contains(rawData, []byte("DEK-Info:")) || bytes.Contains(rawData, []byte("Proc-Type: 4,ENCRYPTED")) { + return true + } + + return false +} diff --git a/server/server_test.go b/server/server_test.go index f9a43a802..5ca03bf7e 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -1,13 +1,20 @@ package server import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" "io/fs" "net/http" "net/url" "os" "path/filepath" + "time" "github.com/navidrome/navidrome/conf" + "github.com/navidrome/navidrome/conf/configtest" + "github.com/navidrome/navidrome/tests" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -107,3 +114,146 @@ var _ = Describe("createUnixSocketFile", func() { }) }) }) + +var _ = Describe("TLS support", func() { + Describe("validateTLSCertificates", func() { + const testDataDir = "server/testdata" + + When("certificate and key are valid and unencrypted", func() { + It("returns nil", func() { + certFile := filepath.Join(testDataDir, "test_cert.pem") + keyFile := filepath.Join(testDataDir, "test_key.pem") + err := validateTLSCertificates(certFile, keyFile) + Expect(err).ToNot(HaveOccurred()) + }) + }) + + When("private key is encrypted with PKCS#8 format", func() { + It("returns an error with helpful message", func() { + certFile := filepath.Join(testDataDir, "test_cert_encrypted.pem") + keyFile := filepath.Join(testDataDir, "test_key_encrypted.pem") + err := validateTLSCertificates(certFile, keyFile) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("encrypted")) + Expect(err.Error()).To(ContainSubstring("openssl")) + }) + }) + + When("private key is encrypted with legacy format (Proc-Type header)", func() { + It("returns an error with helpful message", func() { + certFile := filepath.Join(testDataDir, "test_cert.pem") + keyFile := filepath.Join(testDataDir, "test_key_encrypted_legacy.pem") + err := validateTLSCertificates(certFile, keyFile) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("encrypted")) + Expect(err.Error()).To(ContainSubstring("openssl")) + }) + }) + + When("key file does not exist", func() { + It("returns an error", func() { + certFile := filepath.Join(testDataDir, "test_cert.pem") + keyFile := filepath.Join(testDataDir, "nonexistent.pem") + err := validateTLSCertificates(certFile, keyFile) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("reading TLS key file")) + }) + }) + + When("key file does not contain valid PEM", func() { + It("returns an error", func() { + // Create a temp file with invalid PEM content + tmpFile, err := os.CreateTemp("", "invalid_key*.pem") + Expect(err).ToNot(HaveOccurred()) + DeferCleanup(func() { + _ = os.Remove(tmpFile.Name()) + }) + _, err = tmpFile.WriteString("not a valid PEM file") + Expect(err).ToNot(HaveOccurred()) + _ = tmpFile.Close() + + certFile := filepath.Join(testDataDir, "test_cert.pem") + err = validateTLSCertificates(certFile, tmpFile.Name()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("valid PEM block")) + }) + }) + + When("certificate file does not exist", func() { + It("returns an error from tls.LoadX509KeyPair", func() { + certFile := filepath.Join(testDataDir, "nonexistent_cert.pem") + keyFile := filepath.Join(testDataDir, "test_key.pem") + err := validateTLSCertificates(certFile, keyFile) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("loading TLS certificate/key pair")) + }) + }) + }) + + Describe("Server TLS", func() { + const testDataDir = "server/testdata" + + When("server is started with valid TLS certificates", func() { + It("accepts HTTPS connections", func() { + DeferCleanup(configtest.SetupConfig()) + + // Create server with mock dependencies + ds := &tests.MockDataStore{} + server := New(ds, nil, nil) + + // Load the test certificate to create a trusted CA pool + certFile := filepath.Join(testDataDir, "test_cert.pem") + keyFile := filepath.Join(testDataDir, "test_key.pem") + caCert, err := os.ReadFile(certFile) + Expect(err).ToNot(HaveOccurred()) + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + // Create an HTTPS client that trusts our test certificate + httpClient := &http.Client{ + Timeout: 5 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + MinVersion: tls.VersionTLS12, + }, + }, + } + + // Start the server in a goroutine + ctx, cancel := context.WithCancel(GinkgoT().Context()) + defer cancel() + + errChan := make(chan error, 1) + go func() { + errChan <- server.Run(ctx, "127.0.0.1", 14534, certFile, keyFile) + }() + + Eventually(func() error { + // Make an HTTPS request to the server + resp, err := httpClient.Get("https://127.0.0.1:14534/ping") + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + return nil + }, 2*time.Second, 100*time.Millisecond).Should(Succeed()) + + // Stop the server + cancel() + + // Wait for server to stop (with timeout) + select { + case <-errChan: + // Server stopped + case <-time.After(2 * time.Second): + Fail("Server did not stop in time") + } + }) + }) + }) +}) diff --git a/server/testdata/test_cert.pem b/server/testdata/test_cert.pem new file mode 100644 index 000000000..1dfa573d6 --- /dev/null +++ b/server/testdata/test_cert.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIUXqdUxUOo8kmsDe71iTR+Vr7btP8wDQYJKoZIhvcNAQEL +BQAwYjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3Qx +EjAQBgNVBAoMCU5hdmlkcm9tZTENMAsGA1UECwwEVGVzdDESMBAGA1UEAwwJbG9j +YWxob3N0MCAXDTI1MTEyODE5NTkxNVoYDzIxMjUxMTA0MTk1OTE1WjBiMQswCQYD +VQQGEwJVUzENMAsGA1UECAwEVGVzdDENMAsGA1UEBwwEVGVzdDESMBAGA1UECgwJ +TmF2aWRyb21lMQ0wCwYDVQQLDARUZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkB/TQgl5ei5KRSHt5OJim8rKS +MzRlkK4BjSEM4D9ESbebdpEVjX48QuBYACrCvgvVp7mQGF5anl8Hm89trvd8ooVQ +x9IPQQ6gRKM+4gLrt9FHvFGGzZQS8UTQXN5oBi11E+8/Vs47HLUNXC2TRtRLCMyK +LYXQIXbhdp9anImlt+IHUxIQUchK6Zkld/gCm56X1bbzN/Zq91PQLpx2FZ0eZTjN +KaNgztLa+K/BDnTuk3iTTs9GEp6VCvqQE/6fk/UN/tkk2dLwKIFvPVR/YeAhVdz/ +OHC4L3B36QN3+VQ2yDjsp1PVAPX07UnzXO3Oj7uGYnMQxwprGMEubm3nADDxAgMB +AAGjbzBtMB0GA1UdDgQWBBRAZHUVuLyzc0CfuZR9ApqMbawIqzAfBgNVHSMEGDAW +gBRAZHUVuLyzc0CfuZR9ApqMbawIqzAPBgNVHRMBAf8EBTADAQH/MBoGA1UdEQQT +MBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAmDLXcPx9LNHs +GxQIE6Q5BXbVO7c8qrWmJf5FK5VWaifNZ9U+IBi+VlB4jCLK/OkwsviN/jOnwRYx +owjq0QG0YdRT4uD9fEMrAj+EwbnrQYZQvT0yGEWA+KW5TW08wt+/qnGJDwEgbjYJ +HTdICVMhs/e8Ex48fAgO8WSsdTDekOrhuwzIfeJ1LU4ZptLsD2ePFxuzutdIuW51 +/mspQGsjXqZ1qnLsavLXh/lds2g602rTpYBNZVjV9WiOvaQS8vviOxBN6f+9vgRz +a8SEbHqBG6jeyVqVZ7MjxcYxaIkxeBwMyMwgb+wwDfVXo2FZzX2TVeB7ZppI+IKv +TXYurWPYsQ== +-----END CERTIFICATE----- diff --git a/server/testdata/test_cert_encrypted.pem b/server/testdata/test_cert_encrypted.pem new file mode 100644 index 000000000..6f8de623a --- /dev/null +++ b/server/testdata/test_cert_encrypted.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDpzCCAo+gAwIBAgIUEa7gEJYwJqYEJjTY7otQ+oUyELwwDQYJKoZIhvcNAQEL +BQAwYjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3Qx +EjAQBgNVBAoMCU5hdmlkcm9tZTENMAsGA1UECwwEVGVzdDESMBAGA1UEAwwJbG9j +YWxob3N0MCAXDTI1MTEyODE5NTI0OVoYDzIxMjUxMTA0MTk1MjQ5WjBiMQswCQYD +VQQGEwJVUzENMAsGA1UECAwEVGVzdDENMAsGA1UEBwwEVGVzdDESMBAGA1UECgwJ +TmF2aWRyb21lMQ0wCwYDVQQLDARUZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBHgqJ1d9EnNxqoSZ6xXrIz/mV +Y0nWJW16/qIAvCdovSeTZhG9iqG8dUqcuu2BdD9MMHndJ2oFn3iD8EJR92dH8KBA +8xOmtZ0BEEWgXPBivywZVd1ChIflEWj6m5wwLNjb57SPpUiwaLxBQB8ByEaAAZE/ +bLqvHI3vW/4s5apky17SPIqmkmqEYlRcg97tlRXsPuwoAVM9cvLMMEqtIR1CB/72 +gboY2Gi2r/plLF/Rg3Dom6QljMWi57XXWJFwGYSXaZuM0gvn04e3oLu+1E+WMoq/ +9rExWij2DlsmXd/RiScliFp6R4H84wQUyqrAUNytvgRO+oVnRjEA0l3oCYdRAgMB +AAGjUzBRMB0GA1UdDgQWBBQQKpB1UaKm98FnBdl8uKdRscrVTzAfBgNVHSMEGDAW +gBQQKpB1UaKm98FnBdl8uKdRscrVTzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBP07l+2LmpFtcxqMGmsiNYwFuHpQCxJd4YRZHjLX7O+oJExMgR +2yP4mpMKurgKOv7unTDLwvjQRa6ZTYJCsYtvC6hbyqlGc7AfNTu6DKz8r35/2/V5 +hPsG5lNb91HhvHE839mLAvpi02LoFH2Sr8BR7s6qxfNKYcP8PUOJQXltJ6yAa8YJ +syeXQQ3RIyGsJANeaC06S3UdkBM5H5BLfIHnHu3GybJjwL51va4WCdHe8QV6GI0g +RDiThDVkBSXAr136vnMdlrYCxMoxY56itJ0zbYg2ELQKU9o1w/ZJQo9uvmy9jCoZ +Hy1L5a2vUDbsdONdvRkYZRHqMpG4bdD8D3j2 +-----END CERTIFICATE----- diff --git a/server/testdata/test_key.pem b/server/testdata/test_key.pem new file mode 100644 index 000000000..bac61f4a4 --- /dev/null +++ b/server/testdata/test_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkB/TQgl5ei5KR +SHt5OJim8rKSMzRlkK4BjSEM4D9ESbebdpEVjX48QuBYACrCvgvVp7mQGF5anl8H +m89trvd8ooVQx9IPQQ6gRKM+4gLrt9FHvFGGzZQS8UTQXN5oBi11E+8/Vs47HLUN +XC2TRtRLCMyKLYXQIXbhdp9anImlt+IHUxIQUchK6Zkld/gCm56X1bbzN/Zq91PQ +Lpx2FZ0eZTjNKaNgztLa+K/BDnTuk3iTTs9GEp6VCvqQE/6fk/UN/tkk2dLwKIFv +PVR/YeAhVdz/OHC4L3B36QN3+VQ2yDjsp1PVAPX07UnzXO3Oj7uGYnMQxwprGMEu +bm3nADDxAgMBAAECggEABqJFvesP2v4FEvgd+kSWM+ZL34rPmy3zQ5/MDuPA20ep +89EjQ/5hdRl1TknPcOnTu7PZVuENa9fM2xdrl7GEU9eU0bQLJE/KwiOUgJYObS8V +eTO+DlghHXUBhfXDjux1CS+htOuTUqOyFNS+CR9Lta8o6ou1xjmcP7kW78i17mxF +TuH5SZlS8W9PFLXHCInbMtqGFaT2ss09kvoPk2FDvHfxEdy6M9tKkguz02g+4bqI +aAMp2N7AOfmRpC0HvVa1ZfZo5Z8/KMoNcIm3pV9DEVM369J9EzhnMNpkGben90aT +FqO2JNsy52wmXFZUc9xe8uPdfDahALCkBGncLyLNmQKBgQDZREjocjdzOoPSlCdx +mRNe9suHz2FpUpsHCPOCotG63hFVKpah/ZvpHSsQx5rXs/mawDTmzGY9GQiBrSvg +OhfHIyT3NOhVaNcMxTqJX7rs7OG8D0MBacD9ASSeZ89MUn8q1EHZr5qxLtXl5Ikw +mHtiGRdiKGFFrG9H0zncbGhy7QKBgQDBRhQ9RAasTdmUiNQly9GVFkXto4T/9UHx +rVU44htCI2IVZUMTGlNfclfxpByDrzyA56rMzN9SAkiIp4nPpMDs5hayXaaPoojs +CPzV7r2OjemZ6CTeQ1ODImRL8L/E3jJSgWd6YYoHSQ5hjEX4yT6ft0u0tZUfdMKd +VENWIJ/hlQKBgQCo2hXjeOi5R8+tN3EUKwhP9HOnX7dv+D/9jqpZa5qdpPpJeyjI +SmYCHKYci1Q+sWOaLiiu+km20B65UVFZGSzjmd+fs+GghzMifKGKo/iNK2ggFKhZ +j8vplRrVdQ45XZ/xNDbdLEmHzEN2QE+Skd7KFYADzCgU0vdFFdbRBPuD3QKBgGIq +fQctMRJ9LCE0akSURGwr9vKflmMHKCpfdqTAu0WZgS0K1Mm0GlqlUiPKzizYaauz +f14sRNV7kWnPZsDPlqn8p9SKmpnj3RW97uWeMCtiyx6/+VHm8ljts/GaY1zT2s1r +KqrPNfNDWQmU3MljNeqbh9lOTWK/xEVy0gzB31MNAoGAQNWrZvVdAbL95XW6STUu +JmQlqJTlluuqS0Rrd/uVEQwW0Vd1dZjRQcFAFiSiCQWTbtId5gFZd6hiIQl53Xz0 +5cd+9mcyA/TaoCJYbMOFYsKbZMCBhefsovJlVQXedqJrIY6BdeGlet4GTAH5Qyl0 +ytEIUnvn5YmmbI7PDz80XpU= +-----END PRIVATE KEY----- diff --git a/server/testdata/test_key_encrypted.pem b/server/testdata/test_key_encrypted.pem new file mode 100644 index 000000000..0ac715890 --- /dev/null +++ b/server/testdata/test_key_encrypted.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQPH9PYzryCI3smm81 +J8rm+QICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEI+9XxNfKSiMYIVB +UfcGfncEggTQVw7tPslGy3mlofCNnhBSnMViv9kj6M11smD6Y8vHG0k9Kq+6g+Dx +mQE9ILrSZBzM0uS3y484u+vkdqlT4KehhjIx0IiezurOcM45UdTAwLFLPzeEDlHI +lOWQ3gOTB3J5AxiUQOa6QsDIM7AZilidQG0BxQYWyRBA5B8evJwJoAvdzzA9wGSm +2YdNm3tA6rU5U8cVG+qTJP9pjbtRx0medC/CBZdxGkrWBQH+aySfahJdU8X1JI2e +SY4WJRw1rLCow+DnHjZS/IVHFJivJSRYvnvw8fwjOMVtkf+dAVctKlb1Fj9X+RdG +T1sq3i6zwFLE/RRz4qM4DKZ6UaD9wRFLow8FmNWVuJJiPgCLx2rrNMe32quS/kQP +iOsXAUeA/Yg1fdMCJORxl0nWDmLYcNtBghCmS1lyk+t+AKWwJudrds5tQQe8ha2t +Q41is+tDKwGDC1wt4WXJvBhgAJzuqFtr30H0M1eBhwwDdaDd9v0Zr3r8V49WZM2c +i3qkwPPYkQD+pOcR12xBV8ptvDxaUl7RGlVqnEWHagT51BaIaXQ9teUrG6UPt8o2 +LELJXF6CiwkbN6Y9sYx5XiKrIGxVhlQSZ1nB3XSFRHbu6e7VHPjnVwUeeg87J2Am +MEwqDzPU5sjKRn84+M91Y4uFAIeinaOJAQ0/tZVrf1iSeCMQyMUhW/8m7JPfG19F +NbJSPRXQuKmYKbWfXcMW2UFbp0zDs7s7p4zzbfde9IbVdq/o2nv3ZrNbrLak6O7y +FVt9q/xG4Tty6hSK6xtqtNZWcmfiMcTlk1Qcz2STvScbXtqgcgR6WUZfkLuzi09I +EDYFnzU5JNSY3U3VTv2hAPeU4xjTNM6kjF7L9JFGvdjH8Ko9UdxG9RZMd8xhBM/n +hxdzdVba4bDDz2z+0A2blSObrPrNsKr/3ZbnfuUiSs5NmqmUOifZ1t1PqGGO2Y5S +/cDKtrPk226hGomsUBfHtiIJPG1VRl4UaZiduqK3GGhtF491KU1mAfYzueok3TPq +JhLtLDIvEaFgmOmitFzROI/ifm6s4ssUvcvtbjwJumbjkU38OxYZFwbhwbe268G2 +vgspJamlEGJNdGDzrCFQlA2+A9kazCttztikfh5QGV6WFfkc3Bt1XTPL51vtliQy +MS2gUnJUY2fuYCfz8rxLH1kQmyYsHQz5rUYyBkeDffrG9MzarmzSJXR63FRzVMf1 +LQ7BSzei7dF6+J4KVCxjbGWF3GUGmGeOP5g5vJ3xb3YPJNJLT4Vai103pay59TGP +tESM2Vn0gJEvYApi707noFH5uFTW1cp7lloF41ddIUkL/QO7j+sjvBww+4DqBB7J +BmvLMnswa23yw9egYRG5jOXyCgIr+1rnNcph1HGJsvxvgJ2gwwo5NKCG8SC6LcZQ +fbDjX+ssmobLE3ktN03FZPMp32/ciexzuZoamfyiPXh7xE++ckifNEKJlNhx+kCG +mSR2wh+UGigQkgp/JxOzl6C4fhUbrEZr17oBqGim2p8h+GE0zD5JSHcn1rP86gGU +8JG/ilG4I8uMxUwhGj7amrWXUlJBd1by7e1EAL+utCo14/Tx3otB9/JtqY+lm9Ey +1ptPhMRQxvDNWrCmYM2kyrGghdNfEMir6GKDWI6PY9cwAFv/PLOxr1c= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/server/testdata/test_key_encrypted_legacy.pem b/server/testdata/test_key_encrypted_legacy.pem new file mode 100644 index 000000000..4b9215cdf --- /dev/null +++ b/server/testdata/test_key_encrypted_legacy.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,3C969050EAB73F121B7F0E6B75C42525 + +V6pSaAsrn9CQNo4p88QshJLbg8zkQJEom81dPbYSVqQSZa9YlPtpLZ9YtuLj/Ay0 +TScEKIj/gzQ32wNl6nhcSNIL9yy+X11r5gNv1kIHkecf+EbDW20VOiJsfD+6LUyW +hA96AIbPOwc76iCuvsKHPKU9MlEmjGipmk/C2RQLHCZJ3WkiDRgCM8KQ7vKhfACT +w908yj4cB1e/P0JPq8t/3F7kPJ+6SVM1vMEffHl0otQR3rAyrK8QikwJ0K9qX62d +cqchTVlEyyZBYovR8DrRRUDbsXS5j1ZmX3NQpvTSTFowr+33fMrY+4Oz8sdR4yx1 +CQc0A0sHHxSEIr2xu4KzczwOYVJN8PVdU0pgvFj9KEm66N6EY5CSFIBHyO/ycOt9 +U+wpkRjf3zS6ZaUU0NKdOcop4YX33i99/tZF2RNR1i7ETLYph+/LCf09286Bi3u/ +UCCuWedyECPdz0c6j0s27Fdfc/HEK90OEzeWh/fc+H2gJZhqJYK9V47HPTQNNMnB +U1a6FsJlrKE3E6nfSnTLxrSx9m/XTV7HV+HkgX+q8VhN7Q2VHUqkPzE7ZOPYpZ+A +dQzsm1TmEMxym6osYqFzQScXR1NZasrV2MTQ2J16dUgCdGAM2YMUD9JaoJR+u77M +WAjYzDiRg84rLr/KbJPAwHbsfo2KpiapJGSBBEDhz4W1/LOrFhsjaqIMSy4yZDGm +1KqXGHIlqmuHI7v4fD8vuzhj7GUujRx85HSZWakE/uc6s5WrhkSeVKYJWPfpsxTv +dT3oLOGJ+nRzWxM3aFtuJghX0nIGdKxT4EAUNXz0/vLT3OP1QCZR+oELrriFzmtj ++O30bGH2SAFZEQJ/uTQg6celoNh89IzH4DJkcn67hqpX6mUiU9CrIr/eR9C/en8Q +smTbbC1C1pDUaCwR26Z+zgM90amh4yfOFKK2geO2Kj+TmwFHUvi6ZnSzMzCvty3t ++wdIrUtf55Lw51JCpLGl70mg4b/zBj5hqBkU2YvAAnz/htjfH/wrD6ZAF1TCdlRO +gyODrJjGRnLd/v0XLk0wp+RkAjBcSlRlkUvZY5BtugL7dIdwiNGGQPcOni9IVeG0 +6vDUEQnDOLYDj4d/JcckTLuHdrP+SW+0RQl2HK5+/w1hScGXN4O48gccu7yR/MN8 +DmpCg5rD/nq8sxJosmSt07GrN36KppYt8LCXQbSg3NG2Ad715caS2C+0Qtdm5MPD +rM1UyTXQYSJXgUN9yZS/pmzlguCywnnvsBPU6j3ljZwcoD41QJ/1OU09/W6sIMQR +IAiM35JHiLJiccFgxSE1qx5F1UZqX4P47jF0Wzi/sE/DYXg5qw2DoauqXNzqnumH +71UDGK1V6wQIV7UCZDa0WUfFzu470XpuFb8VmMOuHSQxkZESc9cz8k/ueAuO438Q +jnlkF1Ge2EEPuaK2zeaTj/lGyYA1AUfHRRgt/EMUQSBntmhlpnwVPYTVvYtHO2N5 +wp7/y39KirnlTl99i3XiOJ4WF4gIU2IaSlqMo4+e/A32h2JFi9QfNyfItXe6Fm1X +d0j2XGHzwMfHEFKdWyrgtVZwc38/1d6xWYAhs02b2basV/0AQhFTaKf5Z268eBNJ +-----END RSA PRIVATE KEY-----