1. 程式人生 > >幾種常見的加密演算法及 Java 實現

幾種常見的加密演算法及 Java 實現

介紹

本文主要對加密演算法做個概況性的介紹,然後給出幾種簡單的加密演算法 Java 實現。

1. 演算法種類

  • 單向加密
  • 對稱加密
  • 非對稱加密

1.1 單向加密

即加密之後不能解密,一般用於資料驗證

1) Base64

Base64 編碼是從二進位制到字元的過程,用 64 個字元來表示任意的二進位制資料,常用於在 HTTP 加密,圖片編碼傳輸等。

可列印字元:在ASCII碼中規定,0~31、128 這33個字元屬於控制字元,32~127這95個字元屬於可列印字元

轉換方式:在 HTTP 協議下傳輸二進位制資料時需要將其轉換為字元資料,而網路傳輸只能傳輸可列印字元(95 個),不能轉換的就需要使用 Base64 進行轉換。

轉換方法
- 1 位元組(byte) = 8 位元位(bit)
- Base64 定義了 64 (2^6)個可列印字元表示二進位制的方法,也就是說 6 個 bit 的二進位制資料可以用對應的字元代替表示
- 對於連續多個二進位制資料,每 3 個位元組一組進行轉換,3個位元組 24 bit,然後將其分為 4 部分(3×8 = 4×6),每個部分剛好 6 bit,將 6 bit 二進位制轉換為 Base64 定義的字元即完成轉換
- 例, 6 bit 二進位制是 000000,那麼對應的字元就是 A,如果 6 bit 二進位制是 110011,那麼對應的字元就是 z
- 若二進位制資料位元組數不是 3 的倍數,Base64 就將剩下的二進位制資料補 0 至 3 的倍數,全 0 的用字元 “=” 代替

2) MD5

Message Digest algorithm 5,資訊摘要演算法,MD5
- 一般用於確保資訊的傳輸完整一致性,校驗傳輸的資料是否被修改,一旦原始資訊被修改,生成的 MD5 值將會變得很不同
- 演算法能將任意大小、格式的文字或檔案進行加密從而產生 128 bit(16 位元組)的雜湊值。如同人的指紋,不同文字的 MD5 值是不同的。
- 極端情況:就是不同的字串的 MD5 值一樣,這叫雜湊碰撞。2009 年中科院就已經實現了相應的碰撞演算法,不過 MD5 應用仍然很廣泛
- 一般不可破解,除非使用窮舉法,難度依舊很大

3) SHA 家族

  • 是一個密碼雜湊函式家族,是 FIPS 所認證的安全雜湊演算法
  • 和 MD5 類似,都是對文字進行雜湊,產生一定長度的雜湊值

4) HMAC

Hash Message Authentication Code,雜湊訊息鑑別碼
- 是一種通過特別計算方式之後產生的訊息認證碼(MAC),使用密碼雜湊函式,同時結合一個加密金鑰。它可以用來保證資料的完整性,同時可以用來作某個訊息的身份驗證。

1.2 對稱加密

對稱加密的意思就是資訊收發都有相同的一把鑰匙,訊息的加密解密都用這進行

1)DES

  • Data Encryption Standard,資料加密標準,速度較快,適用於加密大量資料的場合。

2)AES

  • Advanced Encryption Standard,高階加密標準,是下一代的加密演算法標準,速度快,安全級別高;

1.3 非對稱加密

非對稱加密演算法是一種金鑰的保密方法。 非對稱加密演算法需要兩個金鑰:公開金鑰(publickey)和私有金鑰(privatekey)。 公開金鑰與私有金鑰是一對,如果用公開金鑰對資料進行加密,只有用對應的私有金鑰才能解密;如果用私有金鑰對資料進行加密,那麼只有用對應的公開金鑰才能解密。

1)RSA

  • 名稱來源於發明這個演算法的三個人的姓氏組成,演算法大致內容就是對極大整數進行因式分解
  • 這種演算法非常可靠,金鑰越長,它就越難破解。根據已經披露的文獻,目前被破解的最長 RSA金鑰是768個二進位制位。也就是說,長度超過768位的金鑰,還無法破解(至少沒人公開宣佈)。因此可以認為,1024位的RSA金鑰基本安全,2048位的金鑰極其安全。

2)DSA

Digital Signature Algorithm,數字簽名演算法,是一種標準的 DSS(數字簽名標準);

3)ECC

  • Elliptic Curves Cryptography,橢圓曲線密碼編碼學。
  • 一種建立公開金鑰加密的演算法,基於橢圓曲線數學。
  • ECC的主要優勢是在某些情況下它比其他的方法使用更小的金鑰——比如RSA加密演算法——提供相當的或更高等級的安全。ECC的另一個優勢是可以定義群之間的雙線性對映,基於Weil對或是Tate對;雙線性對映已經在密碼學中發現了大量的應用,例如基於身份的加密。不過一個缺點是加密和解密操作的實現比其他機制花費的時間長。

2. 演算法實現(java)

Base64

public static void main(String[] args) {
    try {
        // 編碼
        String encode = Base64.getEncoder().encodeToString("son".getBytes("UTF-8"));
        System.out.println(encode);  // c29u
        // 解碼
        byte[] decode = Base64.getDecoder().decode("c29u");
        System.out.println(new String(decode, "UTF-8"));  // 周杰倫
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

MD5 和 SHA 家族

public static void main(String[] args) {

    String content = "you are my son"; // 原文
    try {
        byte[] a;
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
        a = messageDigest.digest(content.getBytes());
        System.out.println(byte2hex(a)); // 333a9634d8809b5a9e8d280d82553b8fd8d4a911

        messageDigest = MessageDigest.getInstance("SHA-256");
        a = messageDigest.digest(content.getBytes());
        System.out.println(byte2hex(a)); // cdb2c97079d9a1943eea98de4201f5c4f49ecda5af2b364e1c7a5d1ae89688eb

        messageDigest = MessageDigest.getInstance("MD5");
        a = messageDigest.digest(content.getBytes());
        System.out.println(byte2hex(a)); // 6fe6b9a8f8bd29f4f4f1368a0619a7ae

        // 第三方 MD5 演算法。需要新增 jar 包 org.apache.commons.codec.digest.DigestUtils
        String encodeStr=DigestUtils.md5Hex(content);
        System.out.println(encodeStr); // 6fe6b9a8f8bd29f4f4f1368a0619a7ae

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

public static String byte2hex(byte[] b) //二進位制轉字串
{
    String hs = "";
    String stmp = "";
    for (int n = 0; n < b.length; n++) {
        stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
        if (stmp.length() == 1) {
            hs = hs + "0" + stmp;
        } else {
            hs = hs + stmp;
        }
    }
    return hs;
}

總結

  • 現在的加密演算法大部分情況下是為了驗證資料的一致性,例如傳遞一些引數組的時候,簡單的會使用 BASE64 或 MD5 進行加密生成一個簽名。複雜點就是 BASE64 編碼之後再用 對稱金鑰再加密一次,達到比較不容易被人篡改的目的

  • 對於一些支付場景,一般使用 非對稱加密演算法 實現,這樣的場景需要的安全性更高。