ntrepid8 / ex_crypto

Wrapper around the Erlang crypto module for Elixir.
MIT License
144 stars 48 forks source link

problem with AES-256-CBC private key #21

Open daniel-deluca opened 6 years ago

daniel-deluca commented 6 years ago

Hi there, I've found your very useful Elixir lib but I'm facing with an issue when I'm using AES-256-CBC private keys

Test case that fails: test/ex_public_key_test.exs insert at line : 32 "-aes256",

so instead of

# generate a passphrase protected RSA private key with openssl
    System.cmd("openssl", [
      "genrsa",
      "-out",
      rsa_secure_private_key_path,
      "-passout",
      "pass:#{rand_string}",
      "2048"
    ])

we have now

# generate a passphrase protected RSA private key with openssl
    System.cmd("openssl", [
      "genrsa",
      "-aes256",
      "-out",
      rsa_secure_private_key_path,
      "-passout",
      "pass:#{rand_string}",
      "2048"
    ])

and the test mix test test/ex_public_key_test.exs:79 fails

  1) test read secure RSA keys (ExPublicKeyTest)
     test/ex_public_key_test.exs:79
     ** (CaseClauseError) no case clause matching: {:error, %FunctionClauseError{args: nil, arity: 4, clauses: nil, function: :decode, kind: nil, module: :pubkey_pbe}, [{:pubkey_pbe, :decode, [<<43, 180, 39, 134, 179, 160, 115, 204, 207, 162, 100, 17, 226, 84, 197, 254, 3, 10, 68, 212, 144, 49, 120, 150, 239, 201, 223, 214, 213, 157, 39, 151, 17, 109, 42, 106, 193, 217, 176, 117, 244, 187, ...>>, 'KLvk', 'AES-256-CBC', <<246, 36, 62, 81, 225, 191, 64, 102, 55, 197, 38, 121, 69, 244, 140, 46>>], [file: 'pubkey_pbe.erl', line: 59]}, {:public_key, :do_pem_entry_decode, 2, [file: 'public_key.erl', line: 1103]}, {ExPublicKey, :load_pem_entry, 2, [file: 'lib/ex_public_key.ex', line: 128]}, {ExPublicKey, :load_pem_entry, 2, [file: 'lib/ex_public_key.ex', line: 122]}, {ExPublicKey, :loads, 2, [file: 'lib/ex_public_key.ex', line: 94]}, {ExPublicKey, :loads!, 2, [file: 'lib/ex_public_key.ex', line: 107]}, {ExPublicKeyTest, :"test read secure RSA keys", 1, [file: 'test/ex_public_key_test.exs', line: 81]}, {ExUnit.Runner, :exec_test, 1, [file: 'lib/ex_unit/runner.ex', line: 306]}, {:timer, :tc, 1, [file: 'timer.erl', line: 166]}, {ExUnit.Runner, :"-spawn_test/3-fun-1-", 4, [file: 'lib/ex_unit/runner.ex', line: 245]}]}
     code: secure_rsa_priv_key = ExPublicKey.loads!(secure_priv_key_string, context[:passphrase])
     stacktrace:
       (ex_crypto) lib/ex_public_key.ex:107: ExPublicKey.loads!/2
       test/ex_public_key_test.exs:81: (test)

if you replace "-aes256" with "-aes128" . test/ex_public_key_test.exs is OK

Any idea? Many thanks in advance Daniel

ntrepid8 commented 6 years ago

Interesting, what versions of Elixir, Erlang, and OpenSSL are you using?

daniel-deluca commented 6 years ago

Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Elixir 1.6.0 (compiled with OTP 20)

Erlang : 20.2.2

LibreSSL 2.2.7

ntrepid8 commented 6 years ago

Does the openssl command run on your system with the same arguments and not produce the error?

daniel-deluca commented 6 years ago

openssl genrsa -aes256 -out rsa_secure_private.pem -passout pass:123456 2048 openssl rsa -in rsa_secure_private.pem Enter pass phrase for rsa_secure_private.pem: writing RSA key -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA0HZ70HME/G38kS9axeSqlSk3V9EnJHCbN/f0PLLR1wrjKmtr 7+C1odMb2MuuiF4IKn9mHwH6PvDRNZHtMlbeqKSo/bLlWPySlj7arZHIEA00BFi8 lRr2APn8JRgF39WFr1xxudpCrNP0TtlJAKESAusXum9IUCYGbmuPiatx2SezaOMX Uag/ESZabs0yZWSWaBZWbABfBprkMGaOYpFLbLKioESXt+utcAkuzPTdJ9CuajgX q5bYV2gL2+fsu+G6a65hpafRRLWjkjCpQZBPUCf6xoRtdUCBoy3ecT7zkYmn7b3u HNtpSpBFCwMLruwrXoPj0d0NBilKoIsctsBquQIDAQABAoIBABIj7VxTVgC9dXgQ 3d5QqsN2Jbm/mp9iKS+ypQ9PJFGJQgFj/a2PKV8eptKzzslRHXbNRU63dlZZ0GrP +wshYhjc01PYaHrY58ypRZBLGlTDQV6LdkWnZfbpyhZUQ9aZlxuOeNsKcjjl7OGb qO2kFpQobxUrL+jBllevhnsdbzfNQ2WGTEn+Va1woX+cFyZD5Fw6PtPlKBZF7HMv DK6Lvbx30QOv3w6bgwQtVpqSt9i9B1Vy2vVc+FgJbCKnRMiryz0n9/BBK2xomSp3 k0um/hSRtYIq1GDiYQjipp9wl2TGG0reAAOAvatPhze8APZX1+fJ0OZVOoMeqYt/ XHTMkv0CgYEA70CGc17CLmnGNDxliqZVkSGLPTJ4beFbZuOZXS8VZCEFvps0ztnW QKiSf/KOxmi/R4dR3DrasIX5QaVH+TkEJ/5ga4wg076dLj1rmuz5QfqGc31bAo9L RyRBRSWD7Ti8eEXDd41NOeI4Du6pA5fZPU1qV0LGDROKEUxY9kevx5MCgYEA3w40 m60dHQIgaPr8Yda2j9dqr7rmnOpDireGOrDWylVBuEaPMKxpSzdmZfU6TbbnYgRV OTskIX0NdqwUjWRnsss/R0sUW/GO2UuURc12VxsyBYSrQYYWLi83UMvsRm511HGP aLZlJjP+2/ZpLDW92tN67TKRjYLL5zhp/mLPHAMCgYAr+NL9L0RHHX+lKBiNhAaj 9uNNaxJBN7MB1QDh5H5s+bjBkGsDPXwoRBMw2tas1qGZNuCvtk1tNiJak1MIFheS dikoewepgxYGYpl9TuJ84tuFLFvmu4ldWOd6GuwFVHEnNcM4HMs9wTsGW4zKsUTn BGxv/0DBNH8isMKE+SXwawKBgDGcBzdYmVEKWAsBR4C7MH9tedz7xK7Bq6P+jWwg SKVXsPY7Oz2oGwMPn0at8/m05GF4dTv1W2PXXFc4jpmj6yxo5/oDSNPqNcs+dAvS Vq+o7Mctaql4GRbMiZD+yd4gUzSczTiM2JJWniht9ZZPnZo9zulShezjWlZixbA+ abHhAoGAWIf74mddVbgMhZC6Cql6dGu71NBnM4JpbLmRVUqa38iYCu5tiSdhib1r 7uIlKYNeTpZipr7tzROIxGrNtx4ggY6UeYoo5UOmL68fHK9j4f7oWK8KlgsCmbFE 6BtZJcltYUcP3A6fb1F9rpjsyPOfYEukT74iXm/EU9HWQPR4dvc= -----END RSA PRIVATE KEY-----

ntrepid8 commented 6 years ago

I have an idea what might be going on, I'll check and see, then post back here.

ntrepid8 commented 6 years ago

I think this may be a limitation of the underlying public_key Erlang library. We use this function to decode the PEM entry for the encrypted private key:

I don't see a way to pass it any options to let it know the pem_entry argument is encrypted using AES256. If we wanted to support that option we might need to write a step to decrypt the key first and then pass it in the clear to :public_key.pem_entry_decode/1.

Is that something you would want to take a crack at in a pull-request? If not I might have some time to tackle it in the next week or so.

daniel-deluca commented 6 years ago

I'm not an Erlang specialist and this is not blocking me at the moment, so I can wait.

bdusauso commented 5 years ago

It seems that Erlang implements PKCS#5 v2.0 against RFC-2898. Support for AES-256-CBC was added later in RFC-8018 v2.1.

I don't know exactly at what points they differ but I'm quite sure the Erlang team will take some time to implement it.

So, at this point, I think there's nothing we can do.