java - Raspberry Pi 上的 HTTPS 太慢了。我该怎么办?我应该选择哪种密码?

标签 java ssl youtube-api raspberry-pi apache-httpclient-4.x

问题

使用 YouTube Data Api v3 将视频从我的树莓派上传到 YouTube 速度太慢。我得到的最大速率是 120 KB/s。我希望能够实现高达 1MB/s 的速率。

为什么我认为 SSL 是问题所在

为了将视频上传到 YouTube,我曾经运行一个小的 java 程序,我可以在 Raspberry Pie 上运行一整夜以节省电量。它连接到 YouTube 数据 API v2。我有三个互联网连接,最快的是 LTE 移动连接。有了那个我的旧应用程序可以以 1 兆字节/秒的速度上传(它非常可靠,直到我的 30GB 数据用完为止,这就是为什么我只在紧急情况下使用它) .

现在我已经为我的应用程序创建了一个后续应用程序,它使用 API v3。与 v2 API 相比,现在上传也使用 HTTPS 连接。但是现在我无法以超过 120 KB/s 的速度上传。

经过数小时令人沮丧的调试后,我认为问题出在 SSL 造成的 CPU 负载上。为了验证这一点,我在我的计算机上启动了一个企业级 caugh HTTPS 服务器(通过以太网连接到树莓派):

# create a self signed certificate (answer all the question it asks with default)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 100 -nodes
# Run the server on port 5454:
openssl s_server -accept 5454 -key key.pem -cert cert.pem > /dev/null

我组装了一个使用 Apache HttpClient 4.3 的小型 Java 程序(就像我的应用程序一样)并执行了视频“上传”:

    final ProgressReportingHttpEntity entity = new ProgressReportingHttpEntity(new FileEntity(SOME_VIDEO_FILE, ContentType.APPLICATION_OCTET_STREAM));
    request.setEntity(entity);
    HttpClientBuilder
        .create()
        .setSSLSocketFactory(
            new SSLConnectionSocketFactory(
                    new SSLContextBuilder()
                        .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                        .build(),
                    new AllowAllHostnameVerifier()
            )
        )
        .build().execute(request);

使用此设置,我的笔记本电脑可以向自身传输 60MB/s(12% 的 CPU 用于 Java(我的 i7 的一个内核),8% 用于 OpenSSL)。

树莓派仍然可以传输 1MB/s(这已经足够快了)。然而据我了解this page here ,googleapis-Server 将首选密码 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。因此,我像这样重新启动了本地服务器:

openssl s_server -accept 5454 -key key.pem -cert cert.pem -cipher ECDHE-RSA-AES128-GCM-SHA256 > /dev/null

宾果游戏!我不会得到比 120KB/s 更好的传输速率。

我尝试使用不同的密码,在 apache HTTP 客户端中明确设置支持的密码,例如密码 TLS_DHE_RSA_WITH_AES_128_CBC_SHA 表现非常好,达到了 1.3MB/s。

问题

我该怎么办?哪种密码可以在性能和安全性之间提供良好的平衡?在比较支持的密码图表和盲目猜测后,我认为 TLS_DHE_RSA_WITH_AES_128_CBC_SHA 可能是一个不错的选择,并且会得到 google 的支持。但实际上它看起来不是(在 apache http 客户端中设置此密码可以与我的测试服务器通信,但与 google 中断)。

或者我还能做些什么来加快 SSL 吞吐量?例如。是否有一个 ARM 优化的 SSL 库,我可以以某种方式将其注入(inject) JRE(以防 Java 8 ARM JRE 尚未包含此类内容)?

最佳答案

你一定是在某个时候误读了什么。当您尝试密码 TLS_DHE_RSA_WITH_AES_128_CBC_SHA 时,您可能真的想尝试 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(它们看起来确实很相似)。

像这样初始化您的 http 客户端:

return HttpClientBuilder.create()
        .disableAutomaticRetries()
        .setSSLSocketFactory(
            new SSLConnectionSocketFactory(
                    new SSLContextBuilder().build(),
                    null,
                    new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" },
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
            )
        )
        .build();

根据我的测试,这将足够快,可以在你的树莓派上以 1MB/s 的速度上传。

很遗憾,我不是安全专家,我无法告诉您这个选择对您的安全意味着什么。另外,如果您仅支持单个密码,我不知道它会使您的应用程序变得多么脆弱。

关于java - Raspberry Pi 上的 HTTPS 太慢了。我该怎么办?我应该选择哪种密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25207648/

相关文章:

ios - 使用 YouTube api 在 UITableViewCell 中加载 nextPageToken 缓慢且缓慢?

java - HashMap value() 的问题

java - java中的动态图像生成?

ssl - 无法连接到管理服务器 weblogic 12.2.1

ios - YouTube HTML5 API 回调的时间分辨率是多少?

java - YouTube Java API : Get available video resolutions

java - Log4j:为什么在登录提交给 ExecutorService 的 Callable 时缺少日志条目

java - Java递归查找链表中的 'maximum'字符

http - 在通过 HTTPS 的相互身份验证/双向 ssl 中,每次调用时客户端证书是否每次都传递给服务器?

android - 为 X509TrustManager 实现 checkServerTrusted 的正确方法