Android安全加密:Https編程

Android安全加密專題文章索引

  1. Android安全加密:對稱加密
  2. Android安全加密:非對稱加密
  3. Android安全加密:消息摘要Message Digest
  4. Android安全加密:數(shù)字簽名和數(shù)字證書
  5. Android安全加密:Https編程

概述

SSL(Secure Sockets Layer 安全套接層),為網(wǎng)景公司(Netscape)所研發(fā)产徊,用以保障在Internet 上數(shù)據(jù)傳輸之安全纹因,利用數(shù)據(jù)加密(Encryption)技術(shù),可確保數(shù)據(jù)在網(wǎng)絡(luò)上之傳輸過程中不會被截取及竊聽昼扛。一般通用之規(guī)格為40 bit 之安全標(biāo)準(zhǔn),美國則已推出128 bit 之更高安全標(biāo)準(zhǔn)欲诺,但限制出境抄谐。只要3.0 版本以上之I.E.或Netscape 瀏覽器即可支持SSL。

TLS(Transport Layer Security 傳輸層安全)扰法,用于在兩個通信應(yīng)用程序之間提供保密性和數(shù)據(jù)完整性蛹含。TLS 是SSL 的標(biāo)準(zhǔn)化后的產(chǎn)物,有1.0 塞颁,1.1 浦箱,1.2 三個版本,默認(rèn)使用1.0祠锣。TLS1.0 和SSL3.0 幾乎沒
有區(qū)別酷窥,事實上我們現(xiàn)在用的都是TLS,但因為歷史上習(xí)慣了SSL 這個稱呼伴网。

SSL 通信簡單圖示:

這里寫圖片描述

SSL 通信詳細(xì)圖示:

這里寫圖片描述

當(dāng)請求使用自簽名證書的網(wǎng)站數(shù)據(jù)時蓬推,例如請求12306 的客運服務(wù)頁面:https://kyfw.12306.cn/otn/,則會報下面的錯誤澡腾,原因是客戶端的根認(rèn)證機(jī)構(gòu)不能識別該證書錯誤信息:unable to find valid certification path to requested target

解決方案1

一個證書可不可信沸伏,是由TrustManager 決定的,所以我們只需要自定義一個什么都不做的TrustManager即可动分,服務(wù)器出示的所有證書都不做校驗毅糟,一律放行。

public static void main(String[] args) throws Exception {
//協(xié)議傳輸層安全TLS(transport layer secure)
SSLContext sslContext = SSLContext.getInstance("TLS");
//創(chuàng)建信任管理器(TrustManager 負(fù)責(zé)校驗證書是否可信)
TrustManager[] tm = new TrustManager[]{new EmptyX509TrustManager()};
//使用自定義的信任管理器初始化SSL 上下文對象
sslContext.init(null, tm, null);
//設(shè)置全局的SSLSocketFactory 工廠(對所有ssl 鏈接都產(chǎn)生影響)
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{
 @Override
 public void checkClientTrusted(X509Certificate[] chain, String authType)
 throws CertificateException {
 }

 @Override
 public void checkServerTrusted(X509Certificate[] chain, String authType)
 throws CertificateException {
 }
 
 @Override
 public X509Certificate[] getAcceptedIssuers() {
 return null;
 }
}

解決方案2

12306 服務(wù)器出示的證書是中鐵集團(tuán)SRCA 給他頒發(fā)的,所以SRCA 的證書是能夠識別12306 的證書的玛瘸,所以只需要把SRCA 證書導(dǎo)入系統(tǒng)的KeyStore 里蜕青,之后交給TrustManagerFactory 進(jìn)行初始化,則可把SRCA 添加至根證書認(rèn)證機(jī)構(gòu)糊渊,之后校驗的時候右核,SRCA 對12306 證書校驗時就能通過認(rèn)證。

這種解決方案有兩種使用方式:一是直接使用SRCA.cer 文件渺绒,二是使用改文件的RFC 格式數(shù)據(jù)贺喝,將其寫在代碼里菱鸥。

//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 {
 // 使用傳輸層安全協(xié)議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,用來導(dǎo)入證書
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
//參數(shù)null 表示使用系統(tǒng)默認(rèn)keystore躏鱼,也可使用其他keystore(需事先將srca.cer 證書導(dǎo)入
keystore 里)
keyStore.load(null);
//通過流創(chuàng)建一個證書
Certificate certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(certInputStream);
// 把srca.cer 這個證書導(dǎo)入到KeyStore 里氮采,別名叫做srca
keyStore.setCertificateEntry("srca", certificate);
// 設(shè)置使用keyStore 去進(jìn)行證書校驗
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//用我們設(shè)定好的TrustManager 去做ssl 通信協(xié)議校驗,即證書校驗
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

網(wǎng)絡(luò)流量安全測試工具,Google的開源項目:https://github.com/google/nogotofail

Android安全加密專題總結(jié)

以上學(xué)習(xí)所有內(nèi)容茶行,對稱加密躯概、非對稱加密、消息摘要畔师、數(shù)字簽名等知識都是為了理解數(shù)字證書工作原理而作為一個預(yù)備知識娶靡。數(shù)字證書是密碼學(xué)里的終極武器,是人類幾千年歷史總結(jié)的智慧的結(jié)晶看锉,只有在明白了數(shù)字證書工作原理后姿锭,才能理解Https 協(xié)議的安全通訊機(jī)制。最終才能在SSL 開發(fā)過程中得心應(yīng)手伯铣。

另外呻此,對稱加密和消息摘要這兩個知識點是可以單獨拿來使用的。

數(shù)字證書使用到了以上學(xué)習(xí)的所有知識

  • 對稱加密與非對稱加密結(jié)合使用實現(xiàn)了秘鑰交換懂傀,之后通信雙方使用該秘鑰進(jìn)行對稱加密通信趾诗。
  • 消息摘要與非對稱加密實現(xiàn)了數(shù)字簽名,根證書機(jī)構(gòu)對目標(biāo)證書進(jìn)行簽名蹬蚁,在校驗的時候,根證書用公鑰對其進(jìn)行校驗郑兴。若校驗成功犀斋,則說明該證書是受信任的。
  • Keytool 工具可以創(chuàng)建證書情连,之后交給根證書機(jī)構(gòu)認(rèn)證后直接使用自簽名證書叽粹,還可以輸出證書的RFC格式信息等。
  • 數(shù)字簽名技術(shù)實現(xiàn)了身份認(rèn)證與數(shù)據(jù)完整性保證却舀。
  • 加密技術(shù)保證了數(shù)據(jù)的保密性虫几,消息摘要算法保證了數(shù)據(jù)的完整性,對稱加密的高效保證了數(shù)據(jù)處理的可靠性挽拔,數(shù)字簽名技術(shù)保證了操作的不可否認(rèn)性辆脸。

通過以上內(nèi)容的學(xué)習(xí),我們要能掌握以下知識點:

  • 基礎(chǔ)知識:bit 位螃诅、字節(jié)啡氢、字符状囱、字符編碼、進(jìn)制轉(zhuǎn)換倘是、io
  • 知道怎樣在實際開發(fā)里怎樣使用對稱加密解決問題
  • 知道對稱加密亭枷、非對稱加密、消息摘要搀崭、數(shù)字簽名叨粘、數(shù)字證書是為了解決什么問題而出現(xiàn)的
  • 了解SSL 通訊流程
  • 實際開發(fā)里怎樣請求Https 的接口
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瘤睹,隨后出現(xiàn)的幾起案子升敲,更是在濱河造成了極大的恐慌,老刑警劉巖默蚌,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冻晤,死亡現(xiàn)場離奇詭異,居然都是意外死亡绸吸,警方通過查閱死者的電腦和手機(jī)鼻弧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锦茁,“玉大人攘轩,你說我怎么就攤上這事÷肓” “怎么了度帮?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長稿存。 經(jīng)常有香客問我笨篷,道長,這世上最難降的妖魔是什么瓣履? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任率翅,我火速辦了婚禮,結(jié)果婚禮上袖迎,老公的妹妹穿的比我還像新娘冕臭。我一直安慰自己,他們只是感情好燕锥,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布辜贵。 她就那樣靜靜地躺著,像睡著了一般归形。 火紅的嫁衣襯著肌膚如雪托慨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天连霉,我揣著相機(jī)與錄音榴芳,去河邊找鬼嗡靡。 笑死,一個胖子當(dāng)著我的面吹牛窟感,可吹牛的內(nèi)容都是我干的讨彼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼柿祈,長吁一口氣:“原來是場噩夢啊……” “哼哈误!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起躏嚎,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蜜自,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后卢佣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體重荠,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年虚茶,在試婚紗的時候發(fā)現(xiàn)自己被綠了戈鲁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘹叫,死狀恐怖婆殿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情罩扇,我是刑警寧澤婆芦,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站喂饥,受9級特大地震影響消约,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜员帮,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一荆陆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧集侯,春花似錦、人聲如沸帜消。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泡挺。三九已至辈讶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娄猫,已是汗流浹背贱除。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工生闲, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人月幌。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓碍讯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扯躺。 傳聞我的和親對象是個殘疾皇子捉兴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容