Search code examples
ruby-on-railsrubysslopensslnet-http

Use Client Cert and TLS_RSA_WITH_AES_256_CBC_SHA and other cipher suites


I am working on an SSL Handshake with a server that requires TLSv1 and above.

They ciphers they support are:

TLS_RSA_WITH_AES_256_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA

My current connection looks something like this:

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.cert = OpenSSL::X509::Certificate.new(File.read("my.cer"))
http.ca_file = 'their_root.cer'
http.ciphers = ['need-to-figure-out']
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ssl_version = :TLSv1_2
request = Net::HTTP::Post.new(uri.request_uri)
request.body = my_xml
response = http.request(request)

I need to figure out if Ruby supports these ciphers, since I can't find them in the listed ciphers using the puts OpenSSL::Cipher.ciphers method, yet they are required in order to make this connection.

Also, does anyone know what I can change http.ssl_version = :TLSv1_2 to, to make it also allow TLSv3?

EDIT:

Thanks for all your comments. The cipher that works is

proxy_request.ciphers = ["AES256-SHA:AES128-SHA:DES-CBC3-SHA"]

And it shows up in Wireshark like

enter image description here

So thank you very much for that. I'm noticing that I am giving a client "Hello", but I never see a Server Hello in Wireshark, which coincides with the infamous error i'm getting

OpenSSL::SSL::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server hello A
 /Users/me/.rbenv/versions/2.1.6/lib/ruby/2.1.0/net/http.rb:927:in `connect'

Based on my wireshark, does anyone have any Idea what I am doing wrong?

You can see my script more fully in this question. Thanks in advance API Request - OpenSSL::SSL::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server hello A

wireshark


Solution

  • They ciphers they support are:

    TLS_RSA_WITH_AES_256_CBC_SHA
    SSL_RSA_WITH_3DES_EDE_CBC_SHA
    TLS_RSA_WITH_AES_128_CBC_SHA
    

    And:

    http.ciphers = ['need-to-figure-out']
    

    You can map the IANA cipher suite names like TLS_RSA_WITH_AES_128_CBC_SHA, to OpenSSL cipher string names, like AES128-SHA, using the openssl ciphers man page. Its a simple lookup - just search the page for the IANA registry name and you will land on OpenSSL's name eventually.

    I believe the cipher string you should use is:

    http.ciphers = ["AES256-SHA:AES128-SHA:DES-CBC3-SHA"]
    

    ... does anyone know what I can change http.ssl_version = :TLSv1_2 ... to make it also allow TLSv3?

    For this in OpenSSL, you need to set context options. In Ruby, you need to set OpenSSL::SSL::SSL_OP_NO_SSLv2 throughOpenSSL::SSL::SSL_OP_NO_TLSv1_1. That will leave TLS 1.2 and TLS 1.3 (when TLS 1.3 becomes available). Also see How to set TLS context options in Ruby (like OpenSSL::SSL::SSL_OP_NO_SSLv2).

    The TLS_RSA_WITH_* schemes are RSA key transport schemes. TLS 1.3 will not offer them. They have been removed in favor of schemes that provide forward secrecy. Schemes that provide forward secrecy are the Diffie-Hellman ones, like TLS_DHE_* and TLS_ECDHE_*.

    Even the banking industry could not get the IETF to change the decision. Hat's off to the IETF for holding their ground. I think they are a bit too accommodating at times and that often leads to weaker security. But I think they made the right decision in the post-Snowed era, where we have a good idea of the extent of the snooping and spying.