對稱(DES/AES)與非對稱(RSA/SSL/數字證書)加密介紹及實際應用

本文不對具體的算法作深刻研究,只是講解各類安全算法的原理和使用場景。html


1、數據校驗算法

數據校驗,是爲保護數據的完整性,用一種指定的算法對原始數據計算出的一個校驗值。當接收方用一樣的算法再算一次校驗值,若是兩次校驗值同樣,表示數據完整。android

一、奇偶校驗git

          能檢測出信息傳輸過程中的一位誤碼。出現錯誤不能檢測出錯誤,只能要求重發。算法

二、 CRC循環冗餘校驗數組

         經過增長若干冗餘位,能夠檢測出傳輸過程當中的錯誤。檢錯和糾錯能力強,在通訊領域運用較普遍。瀏覽器

三、MD5校驗安全

          MD5算法是一種信息摘要算法,是經過哈希映射的原理獲得一個大文件簡短的MD5值。該算法是一種不可逆算法,也就是說開發者不能經過MD5值獲得原始文件的數據。這裏有一種可能性,不一樣的數據文件獲得相同的MD5值,可是這種狀況通常開發過程中都不予考慮(數據碰撞)。服務器

四、 SHA網絡

       SHA(Secure Hash Algorithm)是由美國專門制定密碼算法的標準機構——美國國家標準技術研究院(NIST)制定的,SHA系列算法的摘要長度分別爲:SHA爲20字節(160位)、SHA256爲32字節(256位)、 SHA384爲48字節(384位)、SHA512爲64字節(512位),因爲它產生的數據摘要的長度更長,所以更難以發生碰撞,所以也更爲安全,它是將來數據摘要算法的發展方向。因爲SHA系列算法的數據摘要長度較長,所以其運算速度與MD5相比,也相對較慢。dom

      同MD5算法相同,他也是一種不可逆的算法


2、對稱加密算法

  • 一、Base64 編解碼

     該算法只能稱爲一種校驗,是對原始的數據進行了一個編碼的過程。 有編碼就有解碼,該過程是一個可逆的。該算法安全性較差,能夠很輕鬆的經過解碼將密文轉換爲明文,從而獲取信息。

  • 二、DES 數據加密算法

       是對稱加密算法領域中的典型算法,如今認爲是一種不安全的加密算法,由於如今已經有用窮舉法攻破DES密碼的報道了。儘管如此,該加密算法仍是運用很是廣泛,是一種標準的加密算法。3DES是DES的增強版本。

      DES加密的祕鑰是 56位,而3DES加密算法的祕鑰是 112位或者168位。3DES加密處理速度較慢、密鑰計算時間較長、加密效率不高。

  • 三、AES 數據加密算法(推薦使用)

Advanced Encryption Standard ,高級數據加密標準,AES算法能夠有效抵制針對DES的攻擊算法。

密鑰創建時間短、靈敏性好、內存需求低、安全性高

DES/3DES/AES 三種加密算法的對好比下:

image

  • 四、異或加密

異或運算中,若是某個字符(或數值)x 與 一個數值m 進行異或運算獲得y,則再用y 與 m 進行異或運算就能夠還原爲 x ,所以應用這個原理能夠實現數據的加密解密功能。

這種加密算法較簡單,只是簡單的將明文轉換爲不易看出的密文,破解的複雜度徹底取決於祕鑰的長度。


3、非對稱加密算法

      公開密鑰加密,又稱 asymmetric cryptography (非對稱加密),即存在兩把不一樣的密鑰,分別稱爲公鑰 Pu 和私鑰 Pr,公鑰一般用來加密明文 M,只有私鑰才能解密密文 C,若是用 E 和 D 分別表示加密和解密算法,那麼有:

C = E(M,Pu);   // 加密公式,M爲明文,C爲密文,

M = D(C,Pr);   // 解密公式

 image 

傳統的對稱加密需雙方共享相同的密鑰,通訊安全很大程度依賴雙方是否能妥善的管理密鑰。公開密鑰加密發明是密碼學最爲重要的里程碑之一,它從數學的角度保證了通訊安全。公開密鑰加密體系有三大範疇:

  • Encryption/Decryption:即加密與解密,發送方接收方的公鑰加密消息(祕鑰由接收方生成,傳送給發送方)

  • Digital Signature:數字簽名,發送方用公鑰加密消息摘要生成簽名,保證消息的完整性和可靠性

一、RSA加密

這種算法以歐拉函數爲基礎,這裏不具體展開:

這種算法很是可靠,密鑰越長,它就越難破解。根據已經披露的文獻,目前被破解的最長RSA密鑰是768個二進制位。也就是說,長度超過768位的密鑰,還沒法破解(至少沒人公開宣佈,由於大數的因式分解計算量特別大)。所以能夠認爲,1024位的RSA密鑰基本安全,2048位的密鑰極其安全。

具體原理能夠見:公鑰私鑰的生成及加解密過程

http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.htm

https://www.kancloud.cn/kancloud/rsa_algorithm/48488

二、SSL/TLS協議

         具體來講,SSL/TLS 並非一種算法,而是爲了保證通訊安全的一種協議,固然裏面用到了相關加密算法如非對稱加密算法、數字證書、HD祕鑰交換算法等。Https多使用這種協議進行網絡數據的傳輸。


         bg2014092003

經過上述這張圖大體瞭解這種協議的通訊過程。上述過程的目的只是爲了獲取比較安全的Session Key,固然這個Key須要Client Random + Server Random + Permaster secret 三者共同生成,安全性較高。Session key 用於後面通訊對數據進行對稱加密。 雙方得到Session Key 後經過http協議進行數據傳輸,Session Key 用來對http傳輸的內容進行加密。

關於SSL/TLS的詳細講解請參考 阮一峯的博客連接。

http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html

TOTP

TOTP 的全稱是"基於時間的一次性密碼"(Time-based One-time Password)。它是公認的可靠解決方案,已經寫入國際標準 RFC6238

它的步驟以下。

第一步:用戶開啓雙因素認證後,服務器生成一個密鑰。

第二步:服務器提示用戶掃描二維碼(或者使用其餘方式),把密鑰保存到用戶的手機。也就是說,服務器和用戶的手機,如今都有了同一把密鑰。

第四步,服務器也使用密鑰和當前時間戳,生成一個哈希,跟用戶提交的哈希比對。只要二者不一致,就拒絕登陸。

注意,密鑰必須跟手機綁定。一旦用戶更換手機,就必須生成全新的密鑰。

算法原理:

TC = floor((unixtime(now) − unixtime(T0)) / TS)

上面的公式中,TC 表示一個時間計數器,unixtime(now)是當前 Unix 時間戳,unixtime(T0)是約定的起始時間點的時間戳,默認是0,也就是1970年1月1日。TS 則是哈希有效期的時間長度,默認是30秒。所以,上面的公式就變成下面的形式。

TC = floor(unixtime(now) / 30)

因此,只要在 30 秒之內,TC 的值都是同樣的。前提是服務器和手機的時間必須同步。

接下來,就能夠算出哈希了。

TOTP = HASH(SecretKey, TC)

TOTP 有硬件生成器和軟件生成器之分,都是採用上面的算法。


數字簽名過程(防止公鑰被僞造 ):

http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

一、經過公鑰私鑰進行加密通訊,發送方發送的內容只有經過私鑰才能打開,因此保證了發送信息的私密性。

二、第三方能夠把僞造的公鑰給發送方,再截獲發送的信息,經過本身的私鑰解密信息。 這裏Https協議中引入的CA(certificate authority)能夠很好的解決這個問題。證書中心用本身的私鑰爲傳輸的公鑰和一些信息進行加密,發送者能夠經過證書中的公鑰解密證書中的信息,這些信息中包含了須要傳送的公鑰。(暫且認爲證書中的信息都是對的,通常證書中心都是可靠性比較高的機構頒發的)

經過Chrome打開百度網頁的時候,F12建, Security菜單欄能夠看到百度的證書。證書裏面包含:頒發者、頒給者、公鑰、有效期等信息。

a) 客戶端向服務器發出加密請求

request

b) 服務器用本身的私鑰加密網頁之後,連同自己的數字證書,一塊兒發送給客戶端

response

c) 客戶端(瀏覽器)的"證書管理器",有"受信任的根證書頒發機構"列表。客戶端會根據這張列表,查看解開數字證書的公鑰是否在列表以內。

camanager


Android端如何使用https發送請求

      網上關於https的使用文章大多數是關於瀏覽器如何經過簽名進行驗證的,瀏覽器會保存各個網站由CA認證中心頒發的數字簽名並進行校驗。那麼問題來了,當客戶端和服務端握手完成後,客戶端如何判斷服務端發送的公鑰和相關信息沒有被第三方篡改(對應c圖)?  其實,客戶端則須要提早將CA證書導入進來,當建立請求時將證書的相關信息添加進去便可完成https請求和驗證。

android端實現https請求具體流程:https://developer.android.com/training/articles/security-ssl

客戶端添加證書實現:

InputStream is = getAssets().open("srca.cer");
private SSLSocketFactory getSslSocketFactory(InputStream... certificates){
        try{
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream certificate : certificates)
            {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

                if (certificate != null)
                    certificate.close();
            }

            SSLContext sslContext = SSLContext.getInstance("TLS");

            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            trustManagerFactory.init(keyStore);
            sslContext.init
                    (
                            null,
                            trustManagerFactory.getTrustManagers(),
                            new SecureRandom()
                    );
            return sslContext.getSocketFactory();
        }catch (Exception e){

        }
        return null;

    }

建立HttpsURLConnection完成後將證書信息設置進去再發送請求:

httpsConn.setSSLSocketFactory(sslSocketFactory);


http網絡請求中的token

      咱們都是知道HTTP協議是無狀態的,這種無狀態意味着程序須要驗證每一次請求,從而辨別客戶端的身份,那麼如何經過只登錄一次就能實現後續已登陸狀態呢?

token


1.用戶登陸校驗,校驗成功後就返回Token給客戶端。

2.客戶端收到數據後保存在客戶端

3.客戶端每次訪問API是攜帶Token到服務器端。

4.服務器端採用filter過濾器校驗。校驗成功則返回請求數據,校驗失敗則返回錯誤碼

那麼這裏有個問題: 服務端怎麼知道攜帶的token就是這個用戶的token而不是僞造的? 後續補充

簽名的實際應用

      如今有三個參數(A、B、C 封裝在一個類Data中)須要傳輸到服務端,那麼如何保證 這三個數據不是別人僞造發送的,能夠在傳這三個數據數據以外再添加一個數據 sign(String類型)。

  客戶端sign的生成算法:

  第一步:對三個參數名稱(與服務端提早約定好傳輸變量的名稱)進行字典排序,拼接成字符串StringA(key1=value1&key2=value2&key3=value3),同時字符串的拼接遵循指定的規則。

  第二步:在stringA最後拼接祕鑰key(只有服務端和客戶端知道,第三方不能得到,這也是簽名的關鍵)獲得finalStringA

  第三部: 對finalStringA 作MD5計算,並將字符數組轉換成16進制的字符串。

    自此sign生成過程結束。

生成根據Data 中A、B、C三個參數的值以及Key 生成了sign以後,將sign值賦給Data中的sign。將Data轉換成JSONObject格式再轉換成字符數組

經過 HttpURLConnection傳送到服務端。服務端經過拿到A、B、C的數值後會本身經過一樣的算法生成sign,若是和客戶端傳送的Sign不同則此次傳送多是第三方僞造的。

  這種簽名就保證了第三方不能僞造數據和服務端進行通訊。(具體的流程以下圖所示)

未命名文件 (26)


可是這裏有個問題,其它人員獲取到了通訊祕鑰secret,則能夠僞造數據,畢竟客戶端的代碼頗有可能被破解的(就算放在native層均可以被破解),可是對於安全等級較低通訊這種加密措施也足夠了。

相關文章
相關標籤/搜索