Two-way SSL ticket verification on the Android platform
Environment: SERVER: apache server, openssl.
Clients: PC, java, and android platforms.
Ideas:
1. Perform one-way ssl verification and then two-way ssl verification.
2. PC first, java platform, and android. You don't have to do this. You have to make a choice. I personally want to figure out the entire process and take more steps.
Procedure:
1. An http server is built with apache on the pc, and a self-Signed CA certificate ca. crt is built with openssl. The server certificate server. crt is issued and the client certificate client. crt is issued. (There are many materials for configuring ssl communication in apache + openssl)
2. Install ca. crt, configure the server, enable one-way authentication, and test and verify one-way ssl communication using a browser.
3. Package client. crt and client. key to generate the client. pfx file in pkcs12 format.
4. Configure the server, enable two-way authentication, import the client. pfx file through a browser, and test and verify two-way ssl communication.
Important:
The Java platform recognizes certificate files in jks format by default, but the android platform only recognizes certificate files in bks format. You need to configure the BC library in java. For details, refer to: keystore.
For code reference, refer. (Some items need to be fine-tuned. I hope you can change them by yourself. For some people, there may be some pitfalls. If you have any questions, please leave a message and I will try my best to answer them)
- Public class MySSLSocket extends Activity {
- Private static final int SERVER_PORT = 50030; // port number
- Private static final String SERVER_IP = "218.206.176.146"; // connection IP
- Private static final String CLIENT_KET_PASSWORD = "123456"; // private Key Password
- Private static final String CLIENT_TRUST_PASSWORD = "123456"; // trust the certificate Password
- Private static final String CLIENT_AGREEMENT = "TLS"; // protocol of use
- Private static final String CLIENT_KEY_MANAGER = "X509"; // key manager
- Private static final String CLIENT_TRUST_MANAGER = "X509 ";//
- Private static final String CLIENT_KEY_KEYSTORE = "BKS"; // password library. BouncyCastle password library is used here.
- Private static final String CLIENT_TRUST_KEYSTORE = "BKS ";//
- Private static final String ENCONDING = "UTF-8"; // Character Set
- Private SSLSocket Client_sslSocket;
- Private Log tag;
- Private TextView TV;
- Private Button btn;
- Private Button btn2;
- Private Button btn3;
- Private EditText et;
-
- /** Called when the activity is first created .*/
- @ Override
- Public void onCreate (Bundle savedInstanceState ){
- Super. onCreate (savedInstanceState );
- SetContentView (R. layout. main );
- TV = (TextView) findViewById (R. id. TextView01 );
- Et = (EditText) findViewById (R. id. EditText01 );
- Btn = (Button) findViewById (R. id. Button01 );
- Btn2 = (Button) findViewById (R. id. Button02 );
- Btn3 = (Button) findViewById (R. id. Button03 );
-
- Btn. setOnClickListener (new Button. OnClickListener (){
- @ Override
- Public void onClick (View arg0 ){
- If (null! = Client_sslSocket ){
- GetOut (Client_sslSocket, et. getText (). toString ());
- GetIn (Client_sslSocket );
- Et. setText ("");
- }
- }
- });
- Btn2.setOnClickListener (new Button. OnClickListener (){
- @ Override
- Public void onClick (View arg0 ){
- Try {
- Client_sslSocket.close ();
- Client_sslSocket = null;
- } Catch (IOException e ){
- E. printStackTrace ();
- }
- }
- });
- Btn3.setOnClickListener (new View. OnClickListener (){
- @ Override
- Public void onClick (View arg0 ){
- Init ();
- GetIn (Client_sslSocket );
- }
- });
- }
-
- Public void init (){
- Try {
- // Obtain an SSL SSLContext instance
- SSLContext sslContext = SSLContext. getInstance (CLIENT_AGREEMENT );
- // Obtain the X509 key manager instance of KeyManagerFactory and TrustManagerFactory
- KeyManagerFactory keyManager = KeyManagerFactory. getInstance (CLIENT_KEY_MANAGER );
- TrustManagerFactory trustManager = TrustManagerFactory. getInstance (CLIENT_TRUST_MANAGER );
- // Obtain the BKS password library instance
- KeyStore kks = KeyStore. getInstance (CLIENT_KEY_KEYSTORE );
- KeyStore tks = KeyStore. getInstance (CLIENT_TRUST_KEYSTORE );
- // Add the client to load the certificate and private key, and read the key and trust certificate by reading the resource file
- Kks. load (getBaseContext ()
- . GetResources ()
- . OpenRawResource (R. drawable. kclient), CLIENT_KET_PASSWORD.toCharArray ());
- Tks. load (getBaseContext ()
- . GetResources ()
- . OpenRawResource (R. drawable. lt_client), CLIENT_TRUST_PASSWORD.toCharArray ());
- // Initialize the key manager
- KeyManager. init (kks, CLIENT_KET_PASSWORD.toCharArray ());
- TrustManager. init (tks );
- // Initialize SSLContext
- SslContext. init (keyManager. getKeyManagers (), trustManager. getTrustManagers (), null );
- // Generate SSLSocket
- Client_sslSocket = (SSLSocket) sslContext. getSocketFactory (). createSocket (SERVER_IP, SERVER_PORT );
- } Catch (Exception e ){
- Tag. e ("MySSLSocket", e. getMessage ());
- }
- }
-
- Public void getOut (SSLSocket socket, String message ){
- PrintWriter out;
- Try {
- Out = new PrintWriter (
- New BufferedWriter (
- New OutputStreamWriter (
- Socket. getOutputStream ()
- )
- ), True );
- Out. println (message );
- } Catch (IOException e ){
- E. printStackTrace ();
- }
- }
-
- Public void getIn (SSLSocket socket ){
- BufferedReader in = null;
- String str = null;
- Try {
- In = new BufferedReader (
- New InputStreamReader (
- Socket. getInputStream ()));
- Str = new String (in. readLine (). getBytes (), ENCONDING );
- } Catch (UnsupportedEncodingException e ){
- E. printStackTrace ();
- } Catch (IOException e ){
- E. printStackTrace ();
- }
- New AlertDialog
- . Builder (MySSLSocket. this)
- . SetTitle ("Server Message ")
- . SetNegativeButton ("OK", null)
- . SetIcon (android. R. drawable. ic_menu_agenda)
- . SetMessage (str)
- . Show ();
- }
- }
Unidirectional:
1. Use keytool to import ca. crt to the certificate library ca. bks in bks format to verify the server certificate. The command is as follows:
Keytool-import-alias ca-file ca. crt-keystore ca. bks-storetype BKS-provider org. bouncycastle. jce. provider. BouncyCastleProvider
2. The server is configured with one-way authentication, and ca. bks is placed in the assets or raw of the android project. The corresponding read is in the code
- Kks. load (getBaseContext ()
- . GetResources ()
- . OpenRawResource (R. drawable. kclient), CLIENT_KET_PASSWORD.toCharArray ());
Not necessarily R. drawable. kclient. You can modify and read the file based on your actual situation.
At this point, one-way ssl communication should be OK.
(PS: for operations in 2, you do not have to do this. You can also set the ca. bks is imported to cacerts on the android platform. bks file, and then read authentication from this file, how to import, a lot of online information, such as: http://blog.csdn.net/haijun286972766/article/details/6247675
For problems encountered during debugging, refer:
Generally, it can pass through the simulator, and it will be okay on the real platform.
Note the validity period of the Certificate. You must perform the operation within the validity period of the certificate.
Bidirectional:
Two-way implementation on the basis of one-way, but Mr Cheng can recognize other client certificates on the android platform. This is also a headache. There are very few materials on the Internet to generate client certificates in bks format, which are rarely used for reference.
At this point, it is too frustrating. It is estimated that many of the guys are also getting stuck here. At the beginning, there was no clue that client certificates can be generated on PCs and JAVA platforms, however, it is dumb to switch to the android platform. You cannot use keytool to export the crt certificate generated by other tools to the bks format. You cannot use keytool to generate a new bks certificate;
I tried all the methods I could think about. I was wondering if I was wrong about any details. In theory, I was sure I could do something. Why couldn't I see any implementation? I 've been looking for information for several days, but I haven't made any progress.
Later, I will refer to the foreign documents about using openssl to generate pkcs12. pfx format certificate, and then use the tool portecle to convert to the BKS format. It is used on the android platform. At the beginning, it is a mandatory conversion. If an error occurs, the conversion fails, however, it is no problem to convert the format to jks. You can only find a solution based on the error prompt. After trying a lot, I am confused;
1. Finally, I saw a sentence from the foreign documents. I had an epiphany and used the portecle tool to create a bks-format keystore, and then set the client. the key pair import (import key pair) in pfx and save the bks file. The test is successful. It turns out to be a little bit more.
PS: It should be okay to use portecle for direct conversion, but I have never been successful. It may be that there is a problem with my java environment, and the old prompt is illegal key size.
2. Configure the server for two-way authentication, and put ca. bks to the assets or raw of the android project. The corresponding read is in the code
- Tks. load (getBaseContext ()
- . GetResources ()
- . OpenRawResource (R. drawable. lt_client), CLIENT_TRUST_PASSWORD.toCharArray ());