从 JRuby 向不支持 JRuby 的 SSL 密码的服务发送 HTTPS 请求
Sending HTTPS requests to a service which doesn't support JRuby's SSL ciphers, from JRuby
基本上就是标题所说的,the ciphers ain't supported in 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
从所有这些 - MRI Ruby AES256-SHA256(根据 OpenSSL 命名法)支持 1,但 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
但它只会导致 'socket closed' 错误,只能玩这个 amazing one-liner 的变体 我设法查明了问题 - 缺少兼容的密码。
因为 the Manticore HTTP client for JRuby 似乎使用了与 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 does open up some apis to let you play with org.apache.http.impl.client.HttpClientBuilder
但是 Java-fu 很快就让我眼睛湿润了。
在这一点上,我什至想追随 "calling Java from JRuby" 的荣耀,了解 Java HTTP 库的 eco-system 等等,但这不是真是我的强项,我时间紧迫。
有没有好心人能帮帮我?我正在寻找其中之一:
- 让 Manticore 工作
- a java 8 包装器,接受 certificates/keys 作为字符串并发送 HTTP 请求 + 一种从 Ruby
调用它的方法
- 我还缺少其他选项吗?
最后,经过大量研究和懊恼,我们编写了一个 Java 库来发送 HTTP 请求并公开该特定用例的相关参数。为 JRuby 编写 Java 通常是两个世界中最糟糕的,但在这种情况下 - 要求非常简单 - 它非常轻松。
ruby 方面的结果如下:
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
基本上就是标题所说的,the ciphers ain't supported in 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
从所有这些 - MRI Ruby AES256-SHA256(根据 OpenSSL 命名法)支持 1,但 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
但它只会导致 'socket closed' 错误,只能玩这个 amazing one-liner 的变体 我设法查明了问题 - 缺少兼容的密码。
因为 the Manticore HTTP client for JRuby 似乎使用了与 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 does open up some apis to let you play with org.apache.http.impl.client.HttpClientBuilder
但是 Java-fu 很快就让我眼睛湿润了。
在这一点上,我什至想追随 "calling Java from JRuby" 的荣耀,了解 Java HTTP 库的 eco-system 等等,但这不是真是我的强项,我时间紧迫。
有没有好心人能帮帮我?我正在寻找其中之一:
- 让 Manticore 工作
- a java 8 包装器,接受 certificates/keys 作为字符串并发送 HTTP 请求 + 一种从 Ruby 调用它的方法
- 我还缺少其他选项吗?
最后,经过大量研究和懊恼,我们编写了一个 Java 库来发送 HTTP 请求并公开该特定用例的相关参数。为 JRuby 编写 Java 通常是两个世界中最糟糕的,但在这种情况下 - 要求非常简单 - 它非常轻松。
ruby 方面的结果如下:
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