Android安全加密:Https编程
Android安全加密專題文章索引
概述
SSL(Secure Sockets Layer 安全套接層),為網景公司(Netscape)所研發,用以保障在Internet 上數據傳輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程中不會被截取及竊聽。一般通用之規格為40 bit 之安全標準,美國則已推出128 bit 之更高安全標準,但限制出境。只要3.0 版本以上之I.E.或Netscape 瀏覽器即可支持SSL。
TLS(Transport Layer Security 傳輸層安全),用于在兩個通信應用程序之間提供保密性和數據完整性。TLS 是SSL 的標準化后的產物,有1.0 ,1.1 ,1.2 三個版本,默認使用1.0。TLS1.0 和SSL3.0 幾乎沒
有區別,事實上我們現在用的都是TLS,但因為歷史上習慣了SSL 這個稱呼。
SSL 通信簡單圖示:
SSL 通信詳細圖示:
當請求使用自簽名證書的網站數據時,例如請求12306 的客運服務頁面:https://kyfw.12306.cn/otn/,則會報下面的錯誤,原因是客戶端的根認證機構不能識別該證書錯誤信息:unable to find valid certification path to requested target
解決方案1
一個證書可不可信,是由TrustManager 決定的,所以我們只需要自定義一個什么都不做的TrustManager即可,服務器出示的所有證書都不做校驗,一律放行。
public static void main(String[] args) throws Exception { //協議傳輸層安全TLS(transport layer secure) SSLContext sslContext = SSLContext.getInstance("TLS"); //創建信任管理器(TrustManager 負責校驗證書是否可信) TrustManager[] tm = new TrustManager[]{new EmptyX509TrustManager()}; //使用自定義的信任管理器初始化SSL 上下文對象 sslContext.init(null, tm, null); //設置全局的SSLSocketFactory 工廠(對所有ssl 鏈接都產生影響) HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());//URL url = new URL("https://www.baidu.com");URL url = new URL("https://kyfw.12306.cn/otn/");HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();InputStream in = conn.getInputStream();System.out.println(Util.inputstream2String(in));}/*** 自定義一個什么都不做的信任管理器,所有證書都不做校驗,一律放行*/private static class EmptyX509TrustManager implements X509TrustManager{@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return null;} }解決方案2
12306 服務器出示的證書是中鐵集團SRCA 給他頒發的,所以SRCA 的證書是能夠識別12306 的證書的,所以只需要把SRCA 證書導入系統的KeyStore 里,之后交給TrustManagerFactory 進行初始化,則可把SRCA 添加至根證書認證機構,之后校驗的時候,SRCA 對12306 證書校驗時就能通過認證。
這種解決方案有兩種使用方式:一是直接使用SRCA.cer 文件,二是使用改文件的RFC 格式數據,將其寫在代碼里。
//12306 證書的RFC 格式(注意要記得手動添加兩個換行符)private static final String CERT_12306_RFC = "-----BEGIN CERTIFICATE-----\n"+ "MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn"+ "BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X"+ "DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp"+ "bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3"+ "DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2"+ "9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6"+ "D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle"+ "tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov"+ "LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt"+ "x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV"+ "23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ"+ "og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A=="+ "-----END CERTIFICATE-----\n";public static void main(String[] args) throws Exception {// 使用傳輸層安全協議TLS(transport layer secure)SSLContext sslContext = SSLContext.getInstance("TLS");//使用SRCA.cer 文件的形式//FileInputStream certInputStream = new FileInputStream(new File("srca.cer")); //也可以通過RFC 字符串的形式使用證書 ByteArrayInputStream certInputStream = new ByteArrayInputStream(CERT_12306_RFC.getBytes()); // 初始化keyStore,用來導入證書 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); //參數null 表示使用系統默認keystore,也可使用其他keystore(需事先將srca.cer 證書導入 keystore 里) keyStore.load(null); //通過流創建一個證書 Certificate certificate = CertificateFactory.getInstance("X.509") .generateCertificate(certInputStream); // 把srca.cer 這個證書導入到KeyStore 里,別名叫做srca keyStore.setCertificateEntry("srca", certificate); // 設置使用keyStore 去進行證書校驗 TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); //用我們設定好的TrustManager 去做ssl 通信協議校驗,即證書校驗 sslContext.init(null, trustManagerFactory.getTrustManagers(), null); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext .getSocketFactory()); URL url = new URL("https://kyfw.12306.cn/otn/"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); InputStream in = conn.getInputStream(); System.out.println(Util.inputstream2String(in)); }Android 里的https 請求:
把scra.cer 文件考到assets 或raw 目錄下,或者直接使用證書的RFC 格式,接下來的做法和java工程代碼一樣
//ByteArrayInputStream in = new ByteArrayInputStream("rfc".getBytes()); CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt")); Certificate ca; try {ca = cf.generateCertificate(caInput);System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); } finally {caInput.close(); } String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca);String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore);SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null);URL url = new URL("https://certs.cac.washington.edu/CAtest/"); HttpsURLConnection urlConnection =(HttpsURLConnection)url.openConnection(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); InputStream in = urlConnection.getInputStream(); copyInputStreamToOutputStream(in, System.out);雙向證書驗證
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null);SSLContext sslContext = SSLContext.getInstance("TLS"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore);//初始化keystore KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); clientKeyStore.load(getAssets().open("client.bks"), "123456".toCharArray());KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, "123456".toCharArray());sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());Nogotofail
網絡流量安全測試工具,Google的開源項目:https://github.com/google/nogotofail
Android安全加密專題總結
以上學習所有內容,對稱加密、非對稱加密、消息摘要、數字簽名等知識都是為了理解數字證書工作原理而作為一個預備知識。數字證書是密碼學里的終極武器,是人類幾千年歷史總結的智慧的結晶,只有在明白了數字證書工作原理后,才能理解Https 協議的安全通訊機制。最終才能在SSL 開發過程中得心應手。
另外,對稱加密和消息摘要這兩個知識點是可以單獨拿來使用的。
數字證書使用到了以上學習的所有知識
- 對稱加密與非對稱加密結合使用實現了秘鑰交換,之后通信雙方使用該秘鑰進行對稱加密通信。
- 消息摘要與非對稱加密實現了數字簽名,根證書機構對目標證書進行簽名,在校驗的時候,根證書用公鑰對其進行校驗。若校驗成功,則說明該證書是受信任的。
- Keytool 工具可以創建證書,之后交給根證書機構認證后直接使用自簽名證書,還可以輸出證書的RFC格式信息等。
- 數字簽名技術實現了身份認證與數據完整性保證。
- 加密技術保證了數據的保密性,消息摘要算法保證了數據的完整性,對稱加密的高效保證了數據處理的可靠性,數字簽名技術保證了操作的不可否認性。
通過以上內容的學習,我們要能掌握以下知識點:
- 基礎知識:bit 位、字節、字符、字符編碼、進制轉換、io
- 知道怎樣在實際開發里怎樣使用對稱加密解決問題
- 知道對稱加密、非對稱加密、消息摘要、數字簽名、數字證書是為了解決什么問題而出現的
- 了解SSL 通訊流程
- 實際開發里怎樣請求Https 的接口
總結
以上是生活随笔為你收集整理的Android安全加密:Https编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android安全加密:消息摘要Mess
- 下一篇: 自定义组合控件:Banner、轮播图、广