在Android SSL的TCP连接(带证书)证书、Android、SSL、TCP

2023-09-05 10:41:57 作者:多吃苦是为了,无悔!

我是新的Andr​​oid平台,从.NET世界的未来。我需要在我的应用程序,它与一些Java的服务器发送/接受她的短信写一个TCP / SSL客户端类。我还需要在通信使用的服务器公证书(.cer文件)。在C#中我有一个做所有的工作SSLStream类,大量的实例吧。但是对于Android(棒棒糖)我找不到任何关于这一问题很好的例子,尤其是没有在上面HTTP协议。任何暗示将AP preciated。

I'm new on Android platform, coming from .NET world. I need to write a TCP/SSL client class in my app, which send/recieve text messages with some Java server. I also need to use server public certificate (.cer file) in that communication. In C# I have SSLStream class that do all the job, and a lot of examples for it. However for Android (Lolipop) I cannot find any good examples on this subject, especially without http protocol on top. Any hint would be appreciated.

推荐答案

下面是basially步骤来创建android的SSL连接:

Below is basially steps to create ssl connection in android :

第1步:获取UR服务器(.cert文件),你已经拥有的公共密钥

Step 1 : Get public key of ur server (.cert file), which you already have.

第二步:创建密钥存储通过 BouncyCastle的罐子

下面的命令:

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

验证,如果证书被正确导入密钥库:

Verify if the certificates were imported correctly into the keystore:

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

应该输出整个链条:

Should output the whole chain:

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

现在,你可以在资源在你的Andr​​oid应用程序拷贝密钥库作为原始资源/生/

Now you can copy the keystore as a raw resource in your android app under res/raw/

第三步:

像下面创建HttpsClient和查询你只有这个客户服务:

Create HttpsClient like below and query you service with this client only :

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);
        }
    }
}

上面的情况也是如此为over HTTP连接,如果你需要有没有http连接,密钥库过程是一样的,你需要使用套接字来打开和关闭连接:

The Above Case holds true for connection over http , if you need to have connection without http , the keystore procedure remains the same and you need to use sockets to open and close the connection :

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();
}