Using OpenSSL for making a network TLS server

Hi, Ruby EventMachine has some issues in its TLS implementation (coded
in C++ using OpenSSL) as noted in
https://github.com/eventmachine/eventmachine/issues/266.

I've been suggested by the author of the project to make a TLS stack
on pure Ruby (by using OpenSSL) and I want to start with it. I'd like
to ask some very basic questions so I can investigate how to achieve
it:

- Imagine that a Ruby server receives a TLS connection from a client.
I assume that my server must implement the TLS handshake protocol at
pure Ruby level, this is, OpenSSL will not help me with this, am I
right?

- Once such TLS handshake is started, I could receive a certificate
from the client, such certificate must be parsed "manually" at Ruby
level in the server (OpenSSL will not help me with this),am I right?

- I must also send my certificate(s) to the peer (again at Ruby level).

- After previous steps, I expect that TLS connection is done so I will
receive data from the client. And I should process/decrypt such data
by using some OpenSSL::XXXXXXX instance and method, am I right?

- And in case I reply data to the client, I must first encrypt the
data using some OpenSSL::XXXXXXXX instance and method, and then send
the generated data to the client, am I right?

Thanks a lot for any input that helps me starting with this stuff.

···

--
Iñaki Baz Castillo
<ibc@aliax.net>

Ruby's OpenSSL library has an SSLServer class that will do exactly what
you're asking. Here is just some quick example code (most of the code is
just building a self-signed cert, you could just as easily load this from a
file):

require 'openssl'
require 'socket'

tcp_server = TCPServer.new 8080

ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new 2048
ctx.cert = OpenSSL::X509::Certificate.new
ctx.cert.subject = OpenSSL::X509::Name.new [['CN', 'localhost']]
ctx.cert.issuer = ctx.cert.subject
ctx.cert.public_key = ctx.key
ctx.cert.not_before = Time.now
ctx.cert.not_after = Time.now + 60 * 60 * 24
ctx.cert.sign ctx.key, OpenSSL::Digest::SHA1.new

server = OpenSSL::SSL::SSLServer.new tcp_server, ctx
socket = server.accept
puts socket.gets

With anything having to do with crypto I would highly recommend not trying
to create the solution yourself (it is far to easy to screw up). Instead
you should take time to review existing solutions that have been "battle
hardened."

···

On Fri, Dec 2, 2011 at 4:22 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

Hi, Ruby EventMachine has some issues in its TLS implementation (coded
in C++ using OpenSSL) as noted in
Issues · eventmachine/eventmachine · GitHub.

I've been suggested by the author of the project to make a TLS stack
on pure Ruby (by using OpenSSL) and I want to start with it. I'd like
to ask some very basic questions so I can investigate how to achieve
it:

- Imagine that a Ruby server receives a TLS connection from a client.
I assume that my server must implement the TLS handshake protocol at
pure Ruby level, this is, OpenSSL will not help me with this, am I
right?

- Once such TLS handshake is started, I could receive a certificate
from the client, such certificate must be parsed "manually" at Ruby
level in the server (OpenSSL will not help me with this),am I right?

- I must also send my certificate(s) to the peer (again at Ruby level).

- After previous steps, I expect that TLS connection is done so I will
receive data from the client. And I should process/decrypt such data
by using some OpenSSL::XXXXXXX instance and method, am I right?

- And in case I reply data to the client, I must first encrypt the
data using some OpenSSL::XXXXXXXX instance and method, and then send
the generated data to the client, am I right?

Thanks a lot for any input that helps me starting with this stuff.

--
Iñaki Baz Castillo
<ibc@aliax.net>

--
John Downey

Really thanks a lot.

···

2011/12/2 John Downey <jdowney@gmail.com>:

Ruby's OpenSSL library has an SSLServer class that will do exactly what
you're asking. Here is just some quick example code (most of the code is
just building a self-signed cert, you could just as easily load this from a
file):

require 'openssl'
require 'socket'

tcp_server = TCPServer.new 8080

ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new 2048
ctx.cert = OpenSSL::X509::Certificate.new
ctx.cert.subject = OpenSSL::X509::Name.new [['CN', 'localhost']]
ctx.cert.issuer = ctx.cert.subject
ctx.cert.public_key = ctx.key
ctx.cert.not_before = Time.now
ctx.cert.not_after = Time.now + 60 * 60 * 24
ctx.cert.sign ctx.key, OpenSSL::Digest::SHA1.new

server = OpenSSL::SSL::SSLServer.new tcp_server, ctx
socket = server.accept
puts socket.gets

With anything having to do with crypto I would highly recommend not trying
to create the solution yourself (it is far to easy to screw up). Instead
you should take time to review existing solutions that have been "battle
hardened."

--
Iñaki Baz Castillo
<ibc@aliax.net>

Hi, unfortunatelly the above solution is not valid for me. What I want
to do is using OpenSSL on top of a EventMachine TCP connection.

EventMachine manages all the sockets and connections internally (at
C++ level), and creates an instance of EM::Connection Ruby class for
each TCP connection (a server connection). Such EM::Connection class
provides some callbacks:

···

2011/12/2 Iñaki Baz Castillo <ibc@aliax.net>:

2011/12/2 John Downey <jdowney@gmail.com>:

Ruby's OpenSSL library has an SSLServer class that will do exactly what
you're asking. Here is just some quick example code (most of the code is
just building a self-signed cert, you could just as easily load this from a
file):

require 'openssl'
require 'socket'

tcp_server = TCPServer.new 8080

ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new 2048
ctx.cert = OpenSSL::X509::Certificate.new
ctx.cert.subject = OpenSSL::X509::Name.new [['CN', 'localhost']]
ctx.cert.issuer = ctx.cert.subject
ctx.cert.public_key = ctx.key
ctx.cert.not_before = Time.now
ctx.cert.not_after = Time.now + 60 * 60 * 24
ctx.cert.sign ctx.key, OpenSSL::Digest::SHA1.new

server = OpenSSL::SSL::SSLServer.new tcp_server, ctx
socket = server.accept
puts socket.gets

With anything having to do with crypto I would highly recommend not trying
to create the solution yourself (it is far to easy to screw up). Instead
you should take time to review existing solutions that have been "battle
hardened."

------------------
class MyTcpServer < EM::Connection
  def receive_data data
    puts "data reveiced on this connection: #{data}"
  end
end
------------------

And includes a method "send_data(data)" to send data over the connection.

So I don't have a Ruby Socket instance. Instead I receive the raw TCP
data in that connection. In my case, such TCP data initially contains
the client's SSL handshake, so I need a way to pass such handshake to
a Ruby OpenSSL::XXX instance. I also need a way to encrypt data based
on the SSL handshake and write it into a raw string, so I can call
EM::Connection#send_data(data) over the TLS connection.

Unfortunatelly it seems that Ruby OpenSSL does not provide a mechanism
for that, and it requires passing a real Ruby Socket as argument for
OpenSSL::SSL::SSLSocket and OpenSSL::SSL::SSLServer. Any suggestion
please?

A workaround I'm thinking about is using an intermediary like-socket,
so when I receive TCP data over the EM::Connection#receive_data(data)
method, I send such raw data to the intermediary socket, and
previously I passed such intermediary socket during the initialitation
of the OpenSSL::SSL::SSLSocket instance (so the SSL handshake and
decryption is done by OpenSSL as usual). But I don't know how to
implement this "concept", and I would prefer not to deal with an
"intermediary socket".

Thanks a lot for any suggestion.

--
Iñaki Baz Castillo
<ibc@aliax.net>

Any suggestion about this please? Maybe the only response is that
"there is no way" (hope not) :slight_smile:

Thanks a lot.

···

2011/12/5 Iñaki Baz Castillo <ibc@aliax.net>:

Hi, unfortunatelly the above solution is not valid for me. What I want
to do is using OpenSSL on top of a EventMachine TCP connection.

EventMachine manages all the sockets and connections internally (at
C++ level), and creates an instance of EM::Connection Ruby class for
each TCP connection (a server connection). Such EM::Connection class
provides some callbacks:

------------------
class MyTcpServer < EM::Connection
def receive_data data
puts "data reveiced on this connection: #{data}"
end
end
------------------

And includes a method "send_data(data)" to send data over the connection.

So I don't have a Ruby Socket instance. Instead I receive the raw TCP
data in that connection. In my case, such TCP data initially contains
the client's SSL handshake, so I need a way to pass such handshake to
a Ruby OpenSSL::XXX instance. I also need a way to encrypt data based
on the SSL handshake and write it into a raw string, so I can call
EM::Connection#send_data(data) over the TLS connection.

Unfortunatelly it seems that Ruby OpenSSL does not provide a mechanism
for that, and it requires passing a real Ruby Socket as argument for
OpenSSL::SSL::SSLSocket and OpenSSL::SSL::SSLServer. Any suggestion
please?

A workaround I'm thinking about is using an intermediary like-socket,
so when I receive TCP data over the EM::Connection#receive_data(data)
method, I send such raw data to the intermediary socket, and
previously I passed such intermediary socket during the initialitation
of the OpenSSL::SSL::SSLSocket instance (so the SSL handshake and
decryption is done by OpenSSL as usual). But I don't know how to
implement this "concept", and I would prefer not to deal with an
"intermediary socket".

Thanks a lot for any suggestion.

--
Iñaki Baz Castillo
<ibc@aliax.net>

"Iñaki Baz Castillo" <ibc@aliax.net> wrote in post #1035430:

Any suggestion about this please? Maybe the only response is that
"there is no way" (hope not) :slight_smile:

Definitely don't write a TLS implementation yourself.

You can use a SocketPair (in ruby: Socket.pair) to buffer the
EventMachine data.

http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/26d3538da0410b8b/fdc3c5c6686ceb49?lnk=gst&q=Socket.pair&rnum=2&hl=en&pli=1

···

--
Posted via http://www.ruby-forum.com/\.

Really interesting, thanks a lot, I will use it.

···

2011/12/7 Brian Candler <b.candler@pobox.com>:

Definitely don't write a TLS implementation yourself.

You can use a SocketPair (in ruby: Socket.pair) to buffer the
EventMachine data.

http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/26d3538da0410b8b/fdc3c5c6686ceb49?lnk=gst&q=Socket.pair&rnum=2&hl=en&pli=1

--
Iñaki Baz Castillo
<ibc@aliax.net>