Kevin Bader
Kevin Bader

Reputation: 327

Erlang ssl: password option for private key

Context

Using Elixir and Brod (which relies on Erlang's ssl module), I'm trying to connect to a SSL-enabled Kafka broker. This works if, and only if, the private key of the client certificate is not password-protected.

The certificate is created using openssl:

$ openssl req -newkey rsa:2048 -sha256 -passout pass:test1234 -keyout client.key -out client.csr -days $DAYS -subj "$SUBJ"
$ openssl x509 -req -CA ca.crt -CAkey ca.key -in client.csr -out client.crt -days $DAYS -CAserial ca.sr

I verify that the password is set using openssl rsa -noout -text -in certs/client.key.

After that, client.key looks like this:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIttCU1ZmyY2ACAggA
...
6C/BxoJnc6SQODqj+eiZHsCTKQ==
-----END ENCRYPTED PRIVATE KEY-----

..which I suppose is in PEM format, suitable for Erlang's ssl module.

Configuration

Brod passes the SSL options down to Erlang's ssl:connect. I'm passing these options (Elixir syntax):

[
  certfile: "client.crt",
  keyfile: "client.key",
  password: String.to_charlist("test1234"),
  cacertfile: "ca.crt"
]

The Error Message

** (stop) {{{:failed_to_upgrade_to_ssl, {:keyfile, :function_clause}}, [{:brod_sock, :maybe_upgrade_to_ssl, 4, [file: 'src/brod_sock.erl', line: 278]}, {:brod_sock, :do_init, 4, [file: 'src/brod_sock.erl', line: 204]}, {:brod_sock, :init, 5, [file: 'src/brod_sock.erl', line: 176]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}, [localhost: 9193]}
    (brod) src/brod_client.erl:708: :brod_client.start_metadata_socket/5
    (brod) src/brod_client.erl:301: :brod_client.handle_info/2
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

According to The Internet this error means that the private key file could not be parsed/loaded/used. I've tried using a wrong password and it's the exact same message. As noted above, when using a secret key that's not password protected, it works fine.

Ideas

Currently studying the OTP sources, but no luck so far.

Upvotes: 2

Views: 1040

Answers (3)

user2414208
user2414208

Reputation: 435

I had similar problem. It turned out that the private key was encoded using AES-256-CBC, but the public_key library in Erlang/OTP doesn't support it. This is the function call that fails:

** exception error: no function clause matching pubkey_pbe:decode(...,
             "password","AES-256-CBC", ...) (pubkey_pbe.erl, line 59)
 in function  public_key:do_pem_entry_decode/2 (public_key.erl, line 976)

The actual code in Erlang/OTP is at github and we can see that "AES-256-CBC" is not handled.

Upvotes: 2

Kevin Bader
Kevin Bader

Reputation: 327

After investigating some more I found out that the Erlang ssl implementation doesn't play well with the private key created by openssl req -newkey. In the openssl documentation I couldn't find the exact algorithm used by -newkey, but creating the private key beforehand using openssl genrsa -des3 did the trick, so I think the default algorithm is something not supported by Erlang's ssl.

I'm posting this as an answer as it solves my problem, but I'd very much appreciate any additional insights.

Upvotes: 1

abejoe
abejoe

Reputation: 163

This is just a suggestion. I do not have enough reps to provide this in comments. Try giving the password as binary string.

Upvotes: 0

Related Questions