Android實踐:Https不再疑惑
阿新 • • 發佈:2019-01-03
近期由於公司的工作需要,需要將原有的http介面切換到https,故做了如下學習和整理。本文先簡要說明https協議原理,然後https協議在瀏覽器和App的實踐兩方面進行講述;
一、https協議原理
1.要理解https是什麼,我們必須應該理解如下幾個關鍵詞,和它們之間的關係:
http:超文字傳輸協議,廣泛用於從WWW伺服器傳輸超文字到本地瀏覽器的傳輸協議;
SSL/TLS:最廣泛的密碼通訊方案,綜合運用了對稱密碼、訊息認證碼、公鑰密碼、數字簽名、偽隨機數生成密碼等密碼技術;
https:在SSL/TLS之上承載HTTP,將兩種協議進行疊加;
2.在繼續講解https之前,我們得先了解下幾個密碼學套件,對於比較好理解的對稱密碼和非對稱密碼就不進行詳細的講解了:
單項雜湊函式:根據任意長度的訊息計算出固定長度的雜湊值,來確定檔案的完整性;
訊息認證碼:是一種金鑰相關聯的單向雜湊函式。要計算MAC必須持有共享祕鑰,訊息變化MAC值就會不一致,故驗證身份和完整性;
數字簽名:反用金鑰對,使用自己私鑰加密生成簽名,驗證方用你的公鑰能解密即可驗證加密方是你,故能驗證身份和完整性;
公鑰證書:認證機構通過電話、郵件或本人確認後,使用機構的私鑰對你的公鑰進行簽名,保證了你的公鑰的正確性;
3.完成基本密碼套件的學習,接下來我們繼續介紹https。由上可知https的核心在於SSL/TLS,讓主要解決了如下接個問題:
機密性:資訊傳輸過程中的被第三方竊聽—採用對稱密碼加密,偽隨機數生成器金鑰,公鑰密碼或Diffe-Hellman進行公鑰交換;
完整性:資訊傳輸過程中被中間人篡改—採用單向雜湊函的訊息認證碼進行完整性驗證;
認證性:資訊傳輸的對方身份是否合法—對公鑰加上數字簽名所生成的證書,對通訊物件進行認證;
4.在https的進行通訊的過程中,它是如何有序的運用上面的密碼學套件的呢?如下:
該部分是基於TLS1.0進行說明,TLS協議是由“TLS記錄協議”和“TLS握手協議”這兩層協議疊加而成:
1.握手協議:除加密之外的各種工作,分為4個子協議:握手協議、密碼規格變更協議、警告協議和應用資料協議;
握手子協議:負責在客戶端和伺服器之間協商決定密碼演算法和共享祕鑰;
密碼規格變更協議:負責向通訊物件傳達變更密碼方式的訊號;
警告協議:負責在發生錯誤的時候將錯誤傳達給對方;
應用資料協議:將TLS上面承載的應用資料傳達給通訊物件的協議;
2.記錄協議:位於TLS握手協議的下層,負責使用對稱密碼對訊息進行壓縮、加密以及資料的認證;
訊息被分割成多個較短的片段,然後對每個片段進行壓縮;
壓縮片段會被加上訊息認證碼,保證完整性,並進行資料的認證,可以識別出篡改。為了防止重放攻擊,在計算訊息認證碼時加上了片段的編號;
經過壓縮的片段在加上訊息認證碼會一起通過對稱密碼進行加密;
經過加密的資料再加上由資料型別、版本號、壓縮後的長度組成的報頭就是最終的報文資料;
經過以上的大概講解,相信大家對https有了更深入的認識,並且也能更好的理解為什麼在實踐https的時候要生成各種金鑰和信任庫了。
二、https協議實踐
理解上面的相關原理後,我們就開始實現HttpsServlet來模擬簡單登入介面,然後通過瀏覽器和app的訪問該https介面;
1.服務端http實現
我們首先實現服務端http協議的get和post通訊,專案的結構和主要實現程式碼如下:
HttpsServlet.java:
一、https協議原理
1.要理解https是什麼,我們必須應該理解如下幾個關鍵詞,和它們之間的關係:
http:超文字傳輸協議,廣泛用於從WWW伺服器傳輸超文字到本地瀏覽器的傳輸協議;
SSL/TLS:最廣泛的密碼通訊方案,綜合運用了對稱密碼、訊息認證碼、公鑰密碼、數字簽名、偽隨機數生成密碼等密碼技術;
https:在SSL/TLS之上承載HTTP,將兩種協議進行疊加;
2.在繼續講解https之前,我們得先了解下幾個密碼學套件,對於比較好理解的對稱密碼和非對稱密碼就不進行詳細的講解了:
單項雜湊函式:根據任意長度的訊息計算出固定長度的雜湊值,來確定檔案的完整性;
訊息認證碼:是一種金鑰相關聯的單向雜湊函式。要計算MAC必須持有共享祕鑰,訊息變化MAC值就會不一致,故驗證身份和完整性;
數字簽名:反用金鑰對,使用自己私鑰加密生成簽名,驗證方用你的公鑰能解密即可驗證加密方是你,故能驗證身份和完整性;
公鑰證書:認證機構通過電話、郵件或本人確認後,使用機構的私鑰對你的公鑰進行簽名,保證了你的公鑰的正確性;
3.完成基本密碼套件的學習,接下來我們繼續介紹https。由上可知https的核心在於SSL/TLS,讓主要解決了如下接個問題:
機密性:資訊傳輸過程中的被第三方竊聽—採用對稱密碼加密,偽隨機數生成器金鑰,公鑰密碼或Diffe-Hellman進行公鑰交換;
完整性:資訊傳輸過程中被中間人篡改—採用單向雜湊函的訊息認證碼進行完整性驗證;
認證性:資訊傳輸的對方身份是否合法—對公鑰加上數字簽名所生成的證書,對通訊物件進行認證;
4.在https的進行通訊的過程中,它是如何有序的運用上面的密碼學套件的呢?如下:
該部分是基於TLS1.0進行說明,TLS協議是由“TLS記錄協議”和“TLS握手協議”這兩層協議疊加而成:
1.握手協議:除加密之外的各種工作,分為4個子協議:握手協議、密碼規格變更協議、警告協議和應用資料協議;
握手子協議:負責在客戶端和伺服器之間協商決定密碼演算法和共享祕鑰;
密碼規格變更協議:負責向通訊物件傳達變更密碼方式的訊號;
警告協議:負責在發生錯誤的時候將錯誤傳達給對方;
應用資料協議:將TLS上面承載的應用資料傳達給通訊物件的協議;
2.記錄協議:位於TLS握手協議的下層,負責使用對稱密碼對訊息進行壓縮、加密以及資料的認證;
訊息被分割成多個較短的片段,然後對每個片段進行壓縮;
壓縮片段會被加上訊息認證碼,保證完整性,並進行資料的認證,可以識別出篡改。為了防止重放攻擊,在計算訊息認證碼時加上了片段的編號;
經過壓縮的片段在加上訊息認證碼會一起通過對稱密碼進行加密;
經過加密的資料再加上由資料型別、版本號、壓縮後的長度組成的報頭就是最終的報文資料;
經過以上的大概講解,相信大家對https有了更深入的認識,並且也能更好的理解為什麼在實踐https的時候要生成各種金鑰和信任庫了。
二、https協議實踐
理解上面的相關原理後,我們就開始實現HttpsServlet來模擬簡單登入介面,然後通過瀏覽器和app的訪問該https介面;
1.服務端http實現
我們首先實現服務端http協議的get和post通訊,專案的結構和主要實現程式碼如下:
HttpsServlet.java:
- publicclass HttpsServlet extends HttpServlet {
- @Override
- protectedvoid doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- System.out.println("doPost");
- doLoginRequest(req, resp);
- }
- @Override
- protectedvoid doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- System.out.println("doGet");
- doLoginRequest(req, resp);
- }
- //實現簡單的登入邏輯
- privatevoid doLoginRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- PrintStream printStream = new PrintStream(resp.getOutputStream());
- HttpsResponse httpsResponse = new HttpsResponse();
- String userName = req.getParameter("userName");
- String passWord = req.getParameter("passWord");
- if ("123".equals(userName) && "123".equals(passWord)) {
- httpsResponse.setCode("000");
- httpsResponse.setMessage("login success!");
- } else {
- httpsResponse.setCode("004");
- httpsResponse.setMessage("login faild!");
- }
- printStream.println(JSON.toJSONString(httpsResponse));
- }
- }
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- <servlet>
- <servlet-name>HttpsServlet</servlet-name>
- <servlet-class>main.com.chengxiang.servlet.HttpsServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>HttpsServlet</servlet-name>
- <url-pattern>/HttpsServlet</url-pattern>
- </servlet-mapping>
- </web-app>
實現客戶端登入的get和post請求,專案目錄結構如下:
NextActivity.java:
- publicclass NextActivity extends AppCompatActivity {
- private EditText userNameEditText;
- private EditText passWorldEditText;
- private Button loginButton;
- private TextView responseTextView;
- private Handler handler = new Handler() {
- @Override
- publicvoid handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case1:
- Bundle bundle = msg.getData();
- HttpsResponse httpsResponse = (HttpsResponse) bundle.getSerializable("result");
- responseTextView.setText(httpsResponse.toString());
- break;
- }
- }
- };
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_next);
- userNameEditText = (EditText) findViewById(R.id.next_username_edittext);
- passWorldEditText = (EditText) findViewById(R.id.next_password_password);
- loginButton = (Button) findViewById(R.id.next_login_button);
- responseTextView = (TextView) findViewById(R.id.next_response_text);
- assert loginButton != null;
- loginButton.setOnClickListener(new View.OnClickListener() {
- @Override
- publicvoid onClick(View v) {
- responseTextView.setText("");
- final String userName = u