SSL/TLS 从 android 到自定义套接字服务器的连接

SSL/TLS connection from android to a Custom Socket Server

已完成使用 gen_tcp(简单套接字)和 Android 用于测试的客户端应用程序的 erlang 中的简单聊天服务器编码。

现在我需要实施 SSL/TLS。

我将连接(发送和接收数据)部分保留在一个模块中,几行代码我可以轻松升级。

我以前没有实施 SSL/TLS 的经验,所以我在这里很困惑(就像很多)。

问题-测试部分(本地主机):

我可以通过以下方式生成自签名证书:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

这导致两个文件,key.pemcert.pem,我的理解是一个是Server证书,另一个是密钥文件但是

  1. 证书颁发机构文件在哪里?我需要生成一个吗?我需要一个吗?
  2. 它们是否足以测试我的应用程序,使其为发布做好准备?
  3. 如何将简单的 android 套接字变成安全套接字? (首选科特林)
  4. 我能否以编程方式信任我的自签名证书(并且只有那个),或者我是否需要将其安装在我的设备(以及任何其他设备,如朋友的设备)上

问题-制作部分:

  1. 我应该在我的服务器上使用我的自签名证书吗?我需要创建一个 CA 吗?使用自签名证书的优缺点?

  2. 我可以永远使用来自 letsencrypt 的免费证书吗?优点和缺点?

最后:

  1. 我也需要客户端证书吗?我需要向 Android 应用提供某种密钥吗?

  2. 我能做些什么来保护我的应用程序免受中间人攻击(或保护我的应用程序不泄露正在 sent/received 进出服务器的内容)例如 THIS TYPE OF ATTACK

既然没有人回答,我会尝试post我对此的看法:

Where is Certificate Authority file? Do i need to generate one? Do i need one?

只要您的 Android(或任何其他)客户端将要使用的唯一服务器是您自己的服务器,您就不需要让 CA 签署您的证书。服务器使用服务器端证书向客户端(例如 Web 浏览器)证明其身份(即证明它确实是它伪装的身份)。因此,只要您的客户端连接到同一主机(它事先拥有的证书),您就不需要任何签名(既不是 CA 也不是自签名)

Are they enough to test my app, to make it ready for a release?

由于您使用了最安全的 RSA(4096 位),我看不到您生成的证书有任何其他改进,所以是的,您可以认为它已准备好发布

How do i turn my simple android socket into a secure socket? (kotlin preferred)

我没用过Kotlin,但是在Java环境下,就这么简单:

import javax.net.ssl.*;
import java.security.*;

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket)factory.createSocket("host", port);

Can i trust my self signed certificate programmatically (and only that one) or do i need to install it on my device (and any other device like a friend's device)

您可以将 cert.pem 添加到密钥库文件中(假设存储类型为 JKS,密码为 passw):

keytool -importcert -file cert.pem -keystore keystore.jks -storetype JKS -alias "alias" -storepass passw

然后将 keystore.jks 放入您的应用程序的 raw 文件夹中,从而使其可以从您的代码中作为 R.raw.keystore 访问:

    KeyStore trusted = KeyStore.getInstance("JKS");
    InputStream in = context.getResources().openRawResource(R.raw.keystore); //open inputstream for keystore file in "raw" folder
    trusted.load(in, "passw".toCharArray());                                 //load the keystore from file (using password specified when certificate was imported into keystore)       
    in.close();                                                              //close inputstream 
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(trusted, "passw".toCharArray());
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");               //configure SSL Context to use TLS v1.2 
    sslContext.init(kmf.getKeyManagers(),null,null);
    SSLSocketFactory factory = sslContext.getSocketFactory();

然后按上述方式使用factory打开安全套接字

SHOULD i use my self signed certificate on my server? Do i need to create a CA? Pros and Cons of using self signed certificate?

查看答案 1

Can i use free certificates like from letsencrypt forever? Pros and Cons?

这完全取决于特定 CA 受到威胁(即签署欺诈性证书)的风险有多大。使用值得信赖的 CA 总是更好,尽管成本更高

Do i need a certificate for Client too? Do i need to provide some sort of key[s] to Android app?

客户端证书只是对最终用户进行身份验证的另一种方式。如果您已经使用密码进行身份验证,则不需要使用客户端证书(您实际上可以添加它以提高安全性,但大多数情况下没有必要,除了有人可能会窃取它)

What can i do to protect my app from MITM (or protect my app from revealing what is being sent/received to and from server) for example THIS TYPE OF ATTACK

好吧,只要设备是原主人的就可以了。如果它被盗并且小偷知道该代理并可能泄露 request/response 内容,则会出现风险。除了用户尽快更改 his/her 密码

之外,我没有想到其他任何事情

接受的答案很好但不完整。

Where is Certificate Authority file? Do i need to generate one? Do i need one?

它是 Public 关键基础设施的一部分。 "public" 这个词在这里很有趣:如果你的服务器除了你之外不会被任何人使用,那么支付第三方 CA 证书就没有多大意义。这些适用于为大量 public 用户部署的域,因此容易受到攻击和漏洞。

SHOULD i use my self signed certificate on my server? Do i need to create a CA? Pros and Cons of using self signed certificate?

现在问题来了:如果你使用第三方 CA 证书,它会花钱,但它可以通过开箱即用的移动设备和浏览器访问 public,即默认SSL 套接字工厂将能够连接到您的域。

如果您选择自签名证书,如果不进行以下更改之一,移动设备或浏览器将无法与您的域完成 SSL 握手(即无法连接):

  • 指示您的套接字工厂
  • 创建一个 recognizes your certificate
  • 的套接字工厂
  • 将您创建的自签名证书添加到客户端设备(mobile/desktop 浏览器)上的已知证书列表中。
  • 使用一种称为 SSL pinning 的技术来测试握手和连接。

Do i need a certificate for Client too? Do i need to provide some sort of key[s] to Android app?

您所说的是双向或 Two-Way SSL validation。这很好但可选。在您的服务器上拥有 public 众所周知的 CA 证书是必要且充分的。

How do i turn my simple android socket into a secure socket?

默认套接字是安全套接字,至少对于任何正常的 TCP/HTTP 库都是如此。您必须更改代码以告诉 套接字工厂忽略 SSL 验证。

Are they enough to test my app, to make it ready for a release?

嗯,这个有点不清楚。您应该使用 SSL pinning 或已知的 CA 证书进行测试,而不是使用自签名证书。如果您只想测试您的应用程序功能,您可以禁用 SSL 验证。据我了解,发布应用程序将需要默认(即安全)套接字工厂,该工厂使用公认的第三方 CA 证书自动管理 SSL 握手。

Can i trust my self signed certificate programmatically (and only that one) or do i need to install it on my device (and any other device like a friend's device)

是的,它可以安装在客户端设备/浏览器上。但是你的服务器只能通过该设备/浏览器进行通信。

最后一点:

如果您使用自签名证书在 Play 商店发布应用,或者禁用或忽略 SSL 验证,您很快就会 receive an email 警告您的应用将被下架。祝你好运。