在用Android平台上使用SSL,第一步就是產生認證。
1、認證的產生
1.1產生伺服器端的認證
keytool -genkey -alias test -keystore test.jks
1.2 將keystore中的cert匯出來,用來產生用戶端的驗證認證
keytool -exportcert -alias test -file test.cert -keystore test.jks
1.3 產生Android平台的認證
因為Android 要求要BC認證,而Java的keytool本身不提供BKS格式,因此要自己手動設定。個人在配置的過程到了檔案正在使用中,儲存失敗的情況,我的做法是將檔案備份一下,用unlocker刪除後將修改好備份放到原位置就好了。
1.3.1 下載 bcprov-ext-jdk15on-146.jar
可以選擇到官網,也可以到我上傳好的檔案去下載,注意,用最新的149版本的會有認證版本號碼不對的異常,改用146的則沒有這個問題
1.3.2 配置bcprov
在 jdk_home\jre\lib\security\目錄中找到 java.security 在內容增加一行(數字可以自己定義)
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
1.3.3 產生android平台的認證
keytool -importcert -keystore test.bks -file test.cert -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
2、編寫伺服器代碼(代碼資源在這裡)
主要代碼(代碼不是我原寫的,作者已經在注釋中標註了,工程檔案在這裡)
import java.io.BufferedInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketAddress;import java.security.KeyManagementException;import java.security.KeyStore;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.UnrecoverableKeyException;import java.security.cert.CertificateException;import javax.net.ServerSocketFactory;import javax.net.ssl.KeyManager;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;/** * @author draem0507@gmail.com * @TODO java線程開發之四 SSL加密 * 開發步驟 * 1.產生服務端密鑰 * 2.匯出服務端認證 * 3.產生用戶端密鑰 * 4.程式開發測試 * 關於認證的產生請參考readme.txt * 參考資料:http://chrui.iteye.com/blog/1018778 * @version 1.0 * @date 2013-5-7 23:22:45 * @update 2013-5-8 10:22:45 * @blgos http://www.cnblogs.com/draem0507 */public class Server { private ServerSocket serverSocket; private final static char[] password="1qaz2wsx".toCharArray(); private SSLContext context; private InputStream inputStream; public Server() { inputStream=this.getClass().getResourceAsStream("/test.jks"); initContext(); try { //直接運行會報 javax.net.ssl.SSLException: //ServerSocketFactory factory= SSLServerSocketFactory.getDefault(); ServerSocketFactory factory= context.getServerSocketFactory();// serverSocket = new ServerSocket(10000); serverSocket=factory.createServerSocket(10000); System.out.println("======啟動安全SocektServer成功========="); while (true) { Socket socket = serverSocket.accept(); new ReceiveSocket(socket).start(); } } catch (IOException e) { e.printStackTrace(); } } //ssl 內容物件的初始化 private void initContext() { try { KeyStore store=KeyStore.getInstance("JKS"); store.load(inputStream, password); KeyManagerFactory factory=KeyManagerFactory.getInstance("SunX509"); factory.init(store,password); KeyManager []keyManagers=factory.getKeyManagers(); context=SSLContext.getInstance("SSL"); context.init(keyManagers, null , null); } catch (KeyStoreException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (UnrecoverableKeyException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } } public static void main(String[] args) { new Server(); } private class ReceiveSocket extends Thread { private Socket socket; public ReceiveSocket(Socket socket) { this.socket = socket; } private ObjectInputStream reader; private ObjectOutputStream writer; @Override public void run() { try { reader=new ObjectInputStream(new BufferedInputStream(socket.getInputStream())); //writer=new ObjectOutputStream(socket.getOutputStream()); // 開啟無限迴圈 監控訊息 //java.io.EOFException Object obj= reader.readUTF(); SocketAddress address = socket.getRemoteSocketAddress(); System.out.println(address.toString() + ">\t" + obj);// Object obj= reader.readObject();// if(obj!=null)// {// User user =(User)obj;// System.out.println("id=="+user.getPassword()+"\tname=="+user.getName());// } // while (true) {} } catch (IOException e) { e.printStackTrace(); } finally { if (null != reader) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != writer) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }}
3、Android端代碼
主要是發送資料的代碼
protected Void doInBackground(Void... params) {Log.i(TAG, "doInBackground");try {SSLContext context;KeyStore ts = KeyStore.getInstance("BKS");ts.load(getResources().openRawResource(R.raw.test),"1qaz2wsx".toCharArray());TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");tmf.init(ts);TrustManager[] tm = tmf.getTrustManagers();context = SSLContext.getInstance("SSL");context.init(null, tm, null);SocketFactory factory = context.getSocketFactory();SSLSocket socket = (SSLSocket) factory.createSocket("192.168.70.249", 10000);ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());out.writeUTF(UUID.randomUUID().toString());out.flush();System.out.println("========用戶端發送成功=========");;socket.close();} catch (Exception ex) {ex.printStackTrace();}return null;}
《好了,全文完》
-----感謝http://stackoverflow.com/ -----