The minimal setup is not the most secure setup of SSL/TLS/DTLS.
To see relevant version information for ssl, call ssl:versions/0 .
To see all supported cipher suites, call ssl:cipher_suites(all). The available cipher suites for a connection depend on your certificate. Specific cipher suites that you want your connection to use can also be specified. Default is to use the strongest available.
This section shows a small example of how to set up client/server connections using the Erlang shell. The returned value of the sslsocket is abbreviated with [...] as it can be fairly large and is opaque.
The minimal setup is not the most secure setup of SSL/TLS/DTLS.
To set up client/server connections:
Step 1: Start the server side:
1 server> ssl:start(). ok
Step 2: Create an TLS listen socket: (To run DTLS add the option {protocol, dtls})
2 server> {ok, ListenSocket} =
ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]).
{ok,{sslsocket, [...]}} Step 3: Do a transport accept on the TLS listen socket:
3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
{ok,{sslsocket, [...]}} Step 4: Start the client side:
1 client> ssl:start(). ok
To run DTLS add the option {protocol, dtls} to third argument.
2 client> {ok, Socket} = ssl:connect("localhost", 9999, [], infinity).
{ok,{sslsocket, [...]}} Step 5: Do the TLS handshake:
4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).
ok Step 6: Send a message over TLS:
5 server> ssl:send(Socket, "foo"). ok
Step 7: Flush the shell message queue to see that the message was sent on the server side:
3 client> flush().
Shell got {ssl,{sslsocket,[...]},"foo"}
ok To upgrade a TCP/IP connection to an SSL connection, the client and server must agree to do so. The agreement can be accomplished by using a protocol, for example, the one used by HTTP specified in RFC 2817.
To upgrade to an SSL connection:
Step 1: Start the server side:
1 server> ssl:start(). ok
Step 2: Create a normal TCP listen socket:
2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true}]).
{ok, #Port<0.475>} Step 3: Accept client connection:
3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
{ok, #Port<0.476>} Step 4: Start the client side:
1 client> ssl:start(). ok
2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity). Step 5: Ensure active is set to false before trying to upgrade a connection to an SSL connection, otherwise SSL handshake messages can be delivered to the wrong process:
4 server> inet:setopts(Socket, [{active, false}]).
ok Step 6: Do the TLS handshake:
5 server> {ok, TLSSocket} = ssl:handshake(Socket, [{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"}, {keyfile, "key.pem"}]).
{ok,{sslsocket,[...]}} Step 7: Upgrade to an TLS connection. The client and server must agree upon the upgrade. The server must call ssl:handshake/2 before the client calls ssl:connect/3.
3 client>{ok, TLSSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"}, {keyfile, "key.pem"}], infinity).
{ok,{sslsocket,[...]}} Step 8: Send a message over TLS:
4 client> ssl:send(TLSSocket, "foo"). ok
Step 9: Set active true on the TLS socket:
4 server> ssl:setopts(TLSSocket, [{active, true}]).
ok Step 10: Flush the shell message queue to see that the message was sent on the client side:
5 server> flush().
Shell got {ssl,{sslsocket,[...]},"foo"}
ok Fetch default cipher suite list for an TLS/DTLS version. Change default to all to get all possible cipher suites.
1> Default = ssl:cipher_suites(default, 'tlsv1.2').
[#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
mac => aead,prf => sha384}, ....] In OTP 20 it is desirable to remove all cipher suites that uses rsa kexchange (removed from default in 21)
2> NoRSA =
ssl:filter_cipher_suites(Default,
[{key_exchange, fun(rsa) -> false;
(_) -> true end}]).
[...] Pick just a few suites
3> Suites =
ssl:filter_cipher_suites(Default,
[{key_exchange, fun(ecdh_ecdsa) -> true;
(_) -> false end},
{cipher, fun(aes_128_cbc) ->true;
(_) ->false end}]).
[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
mac => sha256,prf => sha256},
#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
prf => default_prf}] Make some particular suites the most preferred, or least preferred by changing prepend to append.
4>ssl:prepend_cipher_suites(Suites, Default).
[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
mac => sha256,prf => sha256},
#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
prf => default_prf},
#{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,
mac => sha384,prf => sha384}, ...] Erlang ssl application is able to use private keys provided by OpenSSL engines using the following mechanism:
1> ssl:start(). ok
Load a crypto engine, should be done once per engine used. For example dynamically load the engine called MyEngine:
2> {ok, EngineRef} =
crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, "/tmp/user/engines/MyEngine"},<<"LOAD">>],[]).
{ok,#Ref<0.2399045421.3028942852.173962>} Create a map with the engine information and the algorithm used by the engine:
3> PrivKey =
#{algorithm => rsa,
engine => EngineRef,
key_id => "id of the private key in Engine"}. Use the map in the ssl key option:
4> {ok, SSLSocket} =
ssl:connect("localhost", 9999,
[{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"},
{key, PrivKey}], infinity). See also crypto documentation
© 2010–2017 Ericsson AB
Licensed under the Apache License, Version 2.0.