基本上就是标题所说的,jruby-openssl
不支持密码,而且我遇到了生产问题。我需要其中之一:
ECDHE-RSA-AES256-GCM-SHA384 TLS1.2
ECDHE-RSA-AES256-SHA384 TLS1.2
ECDHE-RSA-AES256-CBC-SHA TLS1.2
ECDHE-ECDSA-AES256-SHA384 TLS1.2
ECDHE-ECDSA-AES256-SHA TLS1.2
ECDH-RSA-AES256-SHA384 TLS1.2
ECDH-ECDSA-AES256-SHA384 TLS1.2
ECDH-RSA-AES256-SHA TLS1.2
ECDH-ECDSA-AES256-SHA TLS1.2
从所有这些 - 1 由 MRI Ruby AES256-SHA256 支持(根据 OpenSSL 命名法(,但 MRI Ruby 不是一个选项。还。
我一直在玩的基本脚本是:
uri = URI.parse(ds_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.ssl_version = :"TLSv1_2"
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # OpenSSL::SSL::VERIFY_PEER, OpenSSL::SSL::VERIFY_NONE
http.cert = client_cert
http.key = client_key
http.ca_file = ds_cert_file
http.ciphers = OpenSSL::SSL::SSLContext.new.ciphers.map do |c|
c[0].gsub("-", "+")
end
puts http.ciphers.inspect
resp = http.post(uri.request_uri, http_body, 'Content-Type' => 'application/xml; charset=utf-8')
resp.body
但它只会导致"套接字关闭"错误,只使用这个惊人的单行代码的变体,我设法查明了问题 - 缺乏兼容的密码。
由于 JRuby 的 Manticore HTTP 客户端似乎使用不同的加密适配器来BouncyCastle
我也尝试了那个,但这个客户端刚刚开始将我拖入有趣的 Java 错误的虫洞,例如
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
manticore 实现的代码类似:
client = Manticore::Client.new(socket_timeout: 5, ssl: {
ca_file: "ca.pem",
client_cert: 'cert.pem',
client_key: 'key.pem'
}) do |http_client_builder, request_builder|
binding.pry
end
rv = client.post(ds_url)
rv.body
它会导致上述错误,然后事情会变得更热:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
在这一点上,我暂时放弃了这种方法。Manticore确实打开了一些API让你玩org.apache.http.impl.client.HttpClientBuilder
但Java-fu很快就让我的眼睛变得水汪汪的。
在这一点上,我甚至想遵循"从JRuby调用Java"的荣耀,了解Java HTTP库的生态系统等等,但这不是我的强项,我时间紧迫。
有没有一个善良和知识渊博的灵魂可以提供帮助?我正在寻找其中之一:
- 让螳螂工作
- 一个Java 8包装器,接受证书/密钥作为字符串并发送HTTP请求+一种从Ruby调用它的方法
- 我缺少其他选项吗?
最后,经过大量的研究和懊恼,我们编写了一个 Java 库来发送 HTTP 请求并公开了这个特定用例的相关参数。为 JRuby 编写 Java 通常是两全其美的,但在这种情况下 - 需求如此简单 - 它非常轻松。
以下是最后红宝石面的样子:
java_import "com.mycompany.http.HttpClient"
java_import "com.mycompany.http.SSLOptions"
#
# ...
#
ssl_options = SSLOptions.createFromStrings client_cert, client_key, ca_cert
rv = HttpClient.create(url, ssl_options, 60000, "changeit", "changeit").send(request)
if rv.responseSuccess
# log.merge(response: rv.responseSuccess.payload)
rv.responseSuccess.payload
else
raise rv.responseFailure.cause
end