user3905440
user3905440

Reputation: 115

Safari could not establish secure connection to my localhost

I was using maven+grizzly+jersey to start my own server. I created self signed certificate so that my server can support https. I case you are curious, following is how I generated my certificate

keytool -genkey -keystore ./keystore_server -alias serverKey -dname "CN=localhost, OU=Jersey, O=Sun Microsystem, L=Prague, ST=Czech Republic, C=CZ"
keytool -export -alias serverKey -rfc -keystore ./keystore_server > ./server.cert

I was testing this on my iMac (Running Mavericks) Now, I added the server.cert to the system keychain so that all users can trust this certificate. Also, I change the trust level to "Always Trust".

I get this work in Chrome and Firefox. They asked me to add exception for this certificate, I did and then everything goes fine. However, I have never make Safari(7.0) happy. I always get the error saying that Safari cannot establish secure connection to my localhost.

Does anyone have any idea why it happened? Or is there better way to debug this problem so that I will be able to tell at which step things goes wrong.

Thank you in advance. I really appreciated it.

Upvotes: 2

Views: 3356

Answers (3)

jww
jww

Reputation: 102205

openssl x509 -in server.cert -inform PEM -text -noout

Here is my certificate looks like...

Safari does not provide DSS support (see Wireshark capture below), even though its required per the RFC 2246, Section 9:

9. Mandatory Cipher Suites

   In the absence of an application profile standard specifying
   otherwise, a TLS compliant application MUST implement the cipher
   suite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.

Another problem you might have is the with SecureTransports implementation of ECDHE_ECDSA_*. Its broken for some versions of OS X and iOS. See [openssl.org #3068] [PATCH] Safari broken ECDHE-ECDSA workaround and Apple are, apparently, dicks... from the OpenSSL developer mailing list.


enter image description here

Upvotes: 0

user3905440
user3905440

Reputation: 115

I finally knock this out. This has something to do with how I generate the key store. The key algorithm I was using is DSA, to make Safari and curl happy I have to use RSA. Otherwise, during the SSL negotiation, there will be no common cipher suite.

Upvotes: 1

jww
jww

Reputation: 102205

keytool -genkey -keystore ./keystore_server -alias serverKey -dname "CN=localhost, OU=Jersey, O=Sun Microsystem, L=Prague, ST=Czech Republic, C=CZ"

A DNS in the Common Name is deprecated by both the IETF and CA/Browser forums. Instead, you should place DNS names in the Subject Alternate Name. Put a friendly name in the Common Name, like "Sun Microsystem".

Does anyone have any idea why it happened?

I don't think I've had a problem when the certificate has all the DNS names it needs in the right places. That includes the browsers and libraries like .Net, Cocoa, Java, Python, PERL, and Ruby.

I don't use keytool, but I think this post from Server Fault explains how to use it to generate a certifcate with DNS names in the SAN: Unable to generate certificate with Subject Alternate Name using Java 1.7 keytool utility.

I use OpenSSL to generate a self signed with DNS names in the SAN. To use OpenSSL and invoke the CONF file (the file example-com.conf is shown below):

$ openssl req -config example-com.conf -new -x509 -newkey rsa:2048 \
    -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem

# Self Signed (note the addition of -x509):
#     openssl req -config example-com.conf -new -x509 -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem
# Signing Request (note the lack of -x509):
#     openssl req -config example-com.conf -new -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem
# Print it:
#     openssl x509 -in example-com.cert.pem -text -noout
#     openssl req -in example-com.req.pem -text -noout

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because its presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums.
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = [email protected]

# Section x509_ext is used when generating a self-signed certifcate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier  = keyid,issuer

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
# CA/Browser Baseline Requirements, Appendix (B)(3)(F) makes EKU madatory
# extendedKeyUsage  = serverAuth

# Section req_ext is used when generating a certifcate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
# CA/Browser Baseline Requirements, Appendix (B)(3)(F) makes EKU madatory
# extendedKeyUsage  = serverAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1
# DNS.9     = fe80::1

Upvotes: 0

Related Questions