0

My nginx backend server supports the following ciphers:

ssl_ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256" 

I allow the client to upload their own SSL certificate and key and I want to validate that it matches one of the configured ciphers. Otherwise they lose access to the server when I restart nginx config with the newly uploaded certificate. When I use openssl x509 I get an output with something like

Signature Algorithm: ecdsa-with-SHA256 

How can I use python or bash code to take this string and figure out if it's valid for my nginx config?

3
  • 1
    See also SSL certificates and cipher suites correspondence Commented Feb 22, 2024 at 14:51
  • 1
    WRT Signature Algorithm: ecdsa-with-SHA256 - this pertains to how the leaf certificate is signed by the next certificate up in the chain. It has nothing to do with the signature by the cert over the TLS handshake. The good news is that you support several TLS 1.3 cipher suites. These can be used with certificates containing either RSA public keys or ECDH public keys. So, you should be fine with either type, as long as the client supports TLS 1.3. Commented Feb 22, 2024 at 19:45
  • @mti2935: 1.3 can use a cert containing RSA (classic or PSS) or ECDSA or EdDSA key, but it can never use an ECDH or XDH (or FFDH) key from a cert, they are always ephemeral. Also specifying 1.3 suites in nginx ssl_ciphers is ineffective; OpenSSL will ignore them and use its default -- which happens to be the same as this directive would have specified. Commented Mar 11, 2024 at 0:34

2 Answers 2

1

Update your ciphersuites, instead

It seems you are facing a problem that you have caused by yourself by not supporting ECDSA for TLS 1.2. Instead of trying to figure out how to validate the certificated provided are RSA certificates you could update your ciphersuites to support both type of certificates by adding the corresponding ECDSA alternatives:

RSA ECDSA
DHE-RSA-AES256-GCM-SHA384 DHE-ECDSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256 DHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-GCM-SHA256

Resulting:

ssl_ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-ECDSA-AES256-GCM-SHA384:DHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256"

Or switch to the recommendations from RFC9325, 4.2:

IANA name from RFC OpenSSL name for Nginx
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ECDHE-RSA-AES128-GCM-SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ECDHE-RSA-AES256-GCM-SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ECDHE-ECDSA-AES128-GCM-SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ECDHE-ECDSA-AES256-GCM-SHA384

Resulting:

ssl_ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384"

With either you would not have the problem in the first place.

If you validate, validate for all possible problems

You wrote your concern is:

Otherwise they lose access to the server when I restart Nginx config with the newly uploaded certificate.

This could happen for a number of other reasons:

  • The files are corrupted or not certificate and key altogether.
  • The client could have uploaded the key in place of the certificate and vice versa.
  • The key might not match the certificate.

And if HTTP Strict Transport Security (HSTS) was enabled:

  • The certificate does not match the hostname.
  • The certificate is not signed by a trusted CA.

In order to test all possibilities at once you could use an actual connection to test the certificate the same way a browser would do. You could use a staging environment with the updated configuration and try to make a connection using, e.g., curl --hsts --fail (HSTS since 7.77.0) or wget (supports HSTS).

1
  • There are no DHE-ECDSA ciphersuites for TLS1.2 (or lower), and the API used by nginx ssl_ciphers (OpenSSL's SSL[_CTX]_set_cipher_list) does not apply to TLS1.3 suites, so both of these are ignored. Commented Mar 11, 2024 at 0:28
1

See my comment above on why this may be a non-issue if you are using TLS 1.3.

If you still feel you need an automated way to analyze a certificate, this short Python script might help:

from cryptography import x509 from cryptography.hazmat.backends import default_backend with open('eccert.pem', 'rb') as file: certificate=file.read() certDecoded = x509.load_pem_x509_certificate(certificate, default_backend()) print(certDecoded.subject) print(certDecoded.public_key()) 

If you place the file eccert.pem in the same directory, you'll see that the script produces the following when run, indicating that the certificate contains an EC public key:

<cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey object at 0x7f6539a63df0>

If you run the script against rsacert.pem instead, you'll see that it produces the following, indicating that the certificate contains an RSA public key:

<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x7f6539a63f40>

Copied below are both pem files.

eccert.pem

-----BEGIN CERTIFICATE----- MIIDsjCCAzigAwIBAgISBDJmXL6n06M8cOTXFDbs+kqzMAoGCCqGSM49BAMDMDIx CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF MTAeFw0yNDAxMTUwNTE4NDlaFw0yNDA0MTQwNTE4NDhaMBwxGjAYBgNVBAMTEXN0 YWNrZXhjaGFuZ2UuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqAjRWWwJ RSCyerqocxzh0395qLgCsnhjUAdPeICBf/J6Cu5yWFEmRXokOYlh2kACMIvPslS5 RgdPgp6iK9nwxqOCAkIwggI+MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggr BgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUMH5X1YCS COQsDJDBONPhwUb5Q0UwHwYDVR0jBBgwFoAUWvPtK/w2wjd5uVIw6lRvz1XLLqww VQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vZTEuby5sZW5jci5v cmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9lMS5pLmxlbmNyLm9yZy8wSwYDVR0RBEQw QoIYKi5tZXRhLnN0YWNrZXhjaGFuZ2UuY29tghMqLnN0YWNrZXhjaGFuZ2UuY29t ghFzdGFja2V4Y2hhbmdlLmNvbTATBgNVHSAEDDAKMAgGBmeBDAECATCCAQQGCisG AQQB1nkCBAIEgfUEgfIA8AB2AKLiv9Ye3i8vB6DWTm03p9xlQ7DGtS6i2reK+Jpt 9RfYAAABjQvFztsAAAQDAEcwRQIgQMs3VNVQgjyAOxCFo+84k4xycmuyDWtIpm1k yluXCGkCIQD5cw9glnZBovkrRwYd/LMymZeSBP3jaFXi117VlVi05gB2AO7N0GTV 2xrOxVy3nbTNE6Iyh0Z8vOzew1FIWUZxH7WbAAABjQvFzq8AAAQDAEcwRQIhAONp YR6UgoB+CR29CxL+Y8fdp6Q7GYb3cC/rH22+CKWsAiATEfGRPFXNltwIDmdvU9+F t2FIXtzJAPZbvCp8DQfr5zAKBggqhkjOPQQDAwNoADBlAjB8PA5ZqHFgziw8qTwI cNmwHLFpNFMzk6Cry9qdkVqyPNXFiaUe2gq0ZgRzGoOqv+gCMQDnMSjnETYxNMNF QUZRsXiRlm5FWR/tv4CM2kJ7szFDw1yautMV8+dJDjbC/n0dxgs= -----END CERTIFICATE----- 

rsacert.pem

-----BEGIN CERTIFICATE----- MIIHrjCCBpagAwIBAgIQPTiQEKFXQA/z/MDIBIrKazANBgkqhkiG9w0BAQsFADCB lTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMT0wOwYDVQQD EzRTZWN0aWdvIFJTQSBPcmdhbml6YXRpb24gVmFsaWRhdGlvbiBTZWN1cmUgU2Vy dmVyIENBMB4XDTIzMTEwMjAwMDAwMFoXDTI0MTEwMTIzNTk1OVowSjELMAkGA1UE BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAoTCmVCYXksIEluYy4x ETAPBgNVBAMTCGViYXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAqQT6wNkzfTtFjfQtwKEeM4mpmHRqcDWATSq+bW/xtj879V5gsNd0lvWd8SWI OUgR+6csWerleRMCHg6ZKojIF+THc+nvdV6WJVKQwOmRtm745lGMlxjuJmACNMN9 21INIxhmcY4kDcAig5CEOD+jGg0ajqqx7wG2xiWEp0t1we5ypgGiiJPp1FVETiXN yklnkPkzFF8sLDBdVQHDGnBzYEVm/HUwatxFB09HyDqegsK7phiTVm77M2CG1/KR 4KFmunLtN1qqnZ0SquKyJzibimKf6UGuWHd3u548VtIUg3UigXuqLb04ZToidbi1 05KanEowHL1uXF1WyVV2ccgkFwIDAQABo4IEQjCCBD4wHwYDVR0jBBgwFoAUF9nW JSdn+THCSUPZMDZEjGypT+swHQYDVR0OBBYEFDqQtqCnnA6X6MzznbmVGKac3mV8 MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUF BwMBBggrBgEFBQcDAjBKBgNVHSAEQzBBMDUGDCsGAQQBsjEBAgEDBDAlMCMGCCsG AQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgIwWgYDVR0f BFMwUTBPoE2gS4ZJaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBT3Jn YW5pemF0aW9uVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBigYIKwYBBQUH AQEEfjB8MFUGCCsGAQUFBzAChklodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3Rp Z29SU0FPcmdhbml6YXRpb25WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCMG CCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTCCAX0GCisGAQQB1nkC BAIEggFtBIIBaQFnAHYAdv+IPwq2+5VRwmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQA AAGLkj6m4wAABAMARzBFAiEAw3JysbrSb8ZALyx99vWRNT6p3ADzrUYVrkf8pJJu NbYCIHlVObN/vnoYfidhO/ZSOie8vjr3ruCrxUXKn8tEEhusAHYAPxdLT9ciR1iU HWUchL4NEu2QN38fhWrrwb8ohez4ZG4AAAGLkj6nEgAABAMARzBFAiEA9xY3dmYP Iepjpg4uPuka5rucAA9XDQtgX5AaPo9irc0CIF2cSAxf1RMHDenJEbZ/nsWcIAFJ wBJhM28AF2ExZLUMAHUA7s3QZNXbGs7FXLedtM0TojKHRny87N7DUUhZRnEftZsA AAGLkj6nEQAABAMARjBEAiBHnn1aJMAUfj/+wLCKqudzqHFvcM6JOgsCXqiwl3bC EQIgLTU1YRbmG8v9ifFUGqIOwBUNV+Ra2+kKcy4H6LE4f/YwggEHBgNVHREEgf8w gfyCCGViYXkuY29tggxiZWZyLmViYXkuYmWCDGJlbmwuZWJheS5iZYIMY2Fmci5l YmF5LmNhgghlLWJheS5pdIIHZWJheS5hdIIHZWJheS5iZYIHZWJheS5jYYIHZWJh eS5jaIIKZWJheS5jby51a4ILZWJheS5jb20uYXWCC2ViYXkuY29tLmhrggtlYmF5 LmNvbS5teYILZWJheS5jb20uc2eCB2ViYXkuZGWCB2ViYXkuZXOCB2ViYXkuZnKC B2ViYXkuaWWCB2ViYXkuaW6CB2ViYXkuaXSCB2ViYXkubmyCB2ViYXkucGiCB2Vi YXkucGyCB2ViYXkudXMwDQYJKoZIhvcNAQELBQADggEBAJW/U2cRX2UQsyz8iRTI 3actxYUVPtu42+1/V26KmgYOHuYJXWBNSJ+FpIwDJbbYzPzNKX1/uZThLt/erOBV NB2u9TG1wyg5xG+aYefyRSy9OEipTZ42mSlxzoeOCrZ0u8fLraFUlDnyuTRzYdX6 gu38/N7VLWvGWDUksEQaapklGU2pvduxSJ6mIxdS6RXinKB9eYFynePpQdBrS0aA gO22gX652iv4wXlQOjyfbF2b6RSOFyUFbshaEKoDzNCZ7fyzcNvjjGRsdu2TkeTz wIjVTcfltSJFJ3AsmZHPM4QWzt56ihmyJoCjUCGDCyAgM7x7K39HMockrfDQ1b6P RvY= -----END CERTIFICATE----- 
1
  • Thanks for the kind response. Your python code is kind of close to what I wanted but I still can't achieve my goal. What I want is basically a machine that take a certificate and a list of cipher suites in the format I show in the original question and returns True/False depending on the certificate matching one of the suites Commented Apr 4, 2024 at 13:58

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.