【问题标题】:SSL TCP connection on Android (with cert)Android 上的 SSL TCP 连接(带证书)
【发布时间】:2015-07-04 16:59:07
【问题描述】:

我是 Android 平台的新手,来自 .NET 世界。我需要在我的应用程序中编写一个 TCP/SSL 客户端类,它使用一些 Java 服务器发送/接收文本消息。我还需要在该通信中使用服务器公共证书(.cer 文件)。在 C# 中,我有 SSLStream 类可以完成所有工作,并提供了很多示例。但是对于 Android (Lolipop),我找不到任何关于这个主题的好例子,尤其是没有 http 协议。任何提示将不胜感激。

【问题讨论】:

  • 欢迎来到 SO:SE。请参阅 How to Ask 以了解该网站的运作方式并改进您的帖子。两个cmets...看来您是在没有事先研究的情况下问的,网上有很多关于这个basic主题的教程。

标签: java c# android ssl tcp


【解决方案1】:

以下是在 android 中创建 ssl 连接的基本步骤:

第 1 步: 获取您已经拥有的服务器的公钥(.cert 文件)。

第2步:通过bouncycastle jar创建密钥库

以下是命令:

keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

验证证书是否正确导入密钥库:

keytool -list -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

应该输出整个链:

RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

现在您可以将密钥库作为原始资源复制到您的 Android 应用程序的 res/raw/ 下

第 3 步:

像下面这样创建 HttpsClient 并仅使用此客户端查询您的服务:

public class HttpsClient extends DefaultHttpClient {

    final Context context;

    public HttpsClient(Context context) {
        this.context = context;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory
                .getSocketFactory(), 80));
        // Register for port 443 our SSLSocketFactory with our keystore
        // to the ConnectionManager
        registry.register(new Scheme("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            // Get an instance of the Bouncy Castle KeyStore format
            KeyStore trusted = KeyStore.getInstance("BKS");
            // Get the raw resource, which contains the keystore with
            // your trusted certificates (root and any intermediate certs)
            InputStream in = context.getResources().openRawResource(
                    R.raw.mykeystore);
            try {
                // Initialize the keystore with the provided trusted
                // certificates
                // Also provide the password of the keystore
                trusted.load(in, "mysecret".toCharArray());
            } finally {
                in.close();
            }
            // Pass the keystore to the SSLSocketFactory. The factory is
            // responsible
            // for the verification of the server certificate.
            SSLSocketFactory sf = new SSLSocketFactory(trusted);
            // Hostname verification from certificate
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

上述情况适用于通过 http 的连接,如果您需要在没有 http 的情况下进行连接,则密钥库过程保持不变,您需要使用套接字来打开和关闭连接:

String keyStorePath = "absolute path to your JKS keystore file";
String keyStorePass = "keystore password";

System.setProperty("javax.net.ssl.keyStore", keyStorePath);
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePass);

SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverSocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port_number);

while (true) {
    new ClientThread((SSLSocket) serverSocket.accept()).start();
}

【讨论】:

  • 感谢回答者。但是,我不需要 HTTP 客户端,只需要 TCP/SSL 客户端。
  • 上面的 HttpsClient 客户端仅用于 ssl 连接
  • 我现在。但是,我没有使用 http,因为我的服务器是某种事务服务器(不是 Web),它只使用 tcp/ip 层和顶部的 ssl 来发送/接收纯文本消息。
【解决方案2】:

KOTIOS 答案有效!

对于 SSL 套接字(不是 http)

使用此代码:

        Socket socket = null;
        SSLContext  context = null;
        char[] passphrase = "mysecret".toCharArray();
        try{
            KeyStore keystore =  KeyStore.getInstance("BKS");
            keystore.load(this.getApplication().getResources().openRawResource(R.raw.mykeystore), passphrase);
            TrustManagerFactory   tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            tmf.init(keystore);
            context = SSLContext.getInstance("TLS");
            TrustManager[] trustManagers = tmf.getTrustManagers();
            context.init(null, trustManagers, null);
        }catch (Exception e){
            e.printStackTrace();
        }

        SSLSocketFactory sf = context.getSocketFactory();
        socket = (SSLSocket) sf.createSocket(InetAddress.getByName(IP), DEFAULT_PORT);

并像使用普通套接字一样使用此套接字。

【讨论】:

    猜你喜欢
    • 2014-08-30
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 2019-04-26
    • 2017-03-28
    • 2019-12-11
    • 1970-01-01
    相关资源
    最近更新 更多