博客 / 詳情

返回

AES 加密和解密demo

前言

我們數據庫中有一條用户信息的數據,需要給到第三方,那麼在發送這條數據的時候,我們不能直接把用户的姓名、電話號、身份證號等一些信息發給第三方,不能暴露用户的個人信息,這個時候就需要用到數據加密進行傳輸。

什麼是AES

AES(Advanced Encryption Standard,高級加密標準)是一種用於保護電子數據的對稱加密算法。在 HTTPS 協議中使用的 TLS(傳輸層安全協議)就使用了 AES 加密。具體加密流程如下:

image.png

名詞的作用和意義

  • 明文P
    沒有經過加密的數據。
  • 密鑰k
    用來加密明文的密碼,在對稱加密算法中,加密與解密的密鑰是相同的。密鑰為接收方與發送方協商產生,但不可以直接在網絡上傳輸,否則會導致密鑰泄漏,通常是通過非對稱加密算法加密密鑰,然後再通過網絡傳輸給對方,或者直接面對面商量密鑰。密鑰是絕對不可以泄漏的,否則會被攻擊者還原密文,竊取機密數據。
  • AES加密函數
    設AES加密函數為E,則 C = E(K, P),其中P為明文,K為密鑰,C為密文。也就是説,把明文P和密鑰K作為加密函數的參數輸入,則加密函數E會輸出密文C。
  • 密文C *
    經加密函數處理後的數據
  • AES
    設AES解密函數為D,則 P = D(K, C),其中C為密文,K為密鑰,P為明文。也就是説,把密文C和密鑰K作為解密函數的參數輸入,則解密函數會輸出明文P。

為什麼要用 AES 而不用其他加密算法?

  • 安全性高:AES 使用多輪的替換和排列操作,使得密文在很大程度上脱離了原始數據的特徵。
  • 靈活性強:AES 支持多種密鑰長度(128 位、192 位、256 位)。

相比之下,其他加密算法如 DES(Data Encryption Standard,數據加密標準)已經被認為不夠安全,容易被暴力破解;RSA 雖然安全性高,但效率較低且密鑰管理複雜,更多用於密鑰交換和數字簽名。

demo

user實體

@Data
public class User {
    String name;
    int age;
    String contactPhone;
    String idCard;
}

實例化後調用AES進行加密。

User user = new User();
        user.setName("張三");
        user.setAge(18);
        user.setContactPhone("1824783xxxx");
        user.setIdCard("430626xxxxxxxxxxxxxxx");

        String encryptDate = AesService.encrypt(user, "MDEyMzQ1Njc4OWFiY2RlZg==");
        System.out.println(encryptDate);

        String decryptDate = AesService.decrypt(encryptDate, AesService.base64StringToKey("MDEyMzQ1Njc4OWFiY2RlZg=="));
        System.out.println(decryptDate);

最終加密信息為:

TKGywGIVhcLjKil4muBh7ROAp430b7n2TUSKH491PuMwa6Z6RDKQubo9ClNxk+yn5LVTOuPOP9Tt2hGr6/q2X+sxEGqPZvb+Ez4joFKSB/uw5t9AHsAi3BPQlAGSrQJG

解密信息為:

{"name":"張三","age":18,"contactPhone":"1824783xxxx","idCard":"430626xxxxxxxxxxxxxxx"}

encrypt(Object o, String key) 方法。

第一個參數接收一個對象,然後將對象轉換成json字符串。
第二個參數接收加密的密鑰(以Base64編碼的字符串形式)。

public static String encrypt(Object o, String key) {
    return AesService.encrypt(new Gson().toJson(o), AesService.base64StringToKey(key));
}

base64StringToKey(String base64Key) 方法。

將一個Base64編碼的字符串轉換為一個SecretKey對象。

public static SecretKey base64StringToKey(String base64Key) {
        try {
            // 將base64Key解碼為一個字節數組
            byte[] data = Base64.getDecoder().decode(base64Key); 
            return new SecretKeySpec(data, 0, data.length, "AES");
        } catch (Exception e) {
            throw new KeyFormatException();
        }
    }
  • data:密鑰的字節數據。
  • 0:偏移量,從數據數組的起始位置開始使用。
  • data.length:使用數據數組的全部長度。
  • "AES":表示加密算法。

    encrypt(String input, SecretKey key) 方法。

    將base64Key輸入字符串input進行加密, key則就是密鑰。

    public static String encrypt(String input, SecretKey key) {
      try {
          //創建Cipher對象,並且指定算法為AES
          Cipher cipher = Cipher.getInstance("AES");
          cipher.init(Cipher.ENCRYPT_MODE, key);
          // doFinal執行加密操作
          byte[] cipherText = cipher.doFinal(input.getBytes());
          // 返回密文
          return Base64.getEncoder().encodeToString(cipherText);
      } catch (Exception e) {
          throw new RuntimeException(e);
      }
    }
  • ENCRYPT_MODE 表明是此時是加密模式
  • DECRYPT_MODE 表明此時是解密模式

decrypt(String cipherText, SecretKey key)方法。

解密一個用Base64編碼的密文字符串cipherText, key則就是密鑰

public static String decrypt(String cipherText, SecretKey key) {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            //初始化解密模式
            cipher.init(Cipher.DECRYPT_MODE, key);
            //將cipherText解碼為字節數組
            byte[] plainText = cipher.doFinal(Base64.getDecoder()
                    .decode(cipherText));
            return new String(plainText);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

為什麼得到加密數據後,還要使用base64進行編碼呢?

  • 二進制數據的表示:
    AES生成的數據是二進制數據,這些數據通常包含非打印字符和控制字符。這些字符在許多場景下(例如在 JSON、XML、URL 中)不能直接顯示或傳輸,因為這些格式通常只支持文本字符集(如 ASCII 或 UTF-8)。
  • 避免數據傳輸損壞:
    許多傳輸協議(如 HTTP、SMTP 等)是基於文本的,直接發送或存儲二進制數據可能會導致數據損壞或被截斷,Base64 編碼是一種將二進制數據轉換為文本字符的編碼方式,它只使用 A-Z、a-z、0-9、+、/ 這 64 個字符(以及填充字符 =),所有這些字符都在文本協議和存儲系統中是安全的,因此不會被誤處理。
  • 數據完整性:
    一些傳輸協議可能會對數據做一些自動的修改或處理,例如去掉空格、替換特殊字符等。Base64 編碼保證了數據不會因為這些自動處理而被篡改,確保數據完整性。

例如:

一個簡單的字符串 "Hello, World!",你對它進行 AES 加密後,得到的二進制數據可能是:

[-66, 77, 127, -15, 70, 58, -7, -100, -44, -37, 78, 124, 82, -117, 122, 35]

這些值是二進制數據,無法以字符串形式表示。通過 Base64 編碼後,它們會變成:

vk1/8UY6+ZzU2058Uot6Iw==

這個結果是一個可打印的字符串,可以安全地在各種文本協議和存儲中傳輸和存儲。

所以使用 Base64 編碼來表示加密後的二進制數據是一種常見的做法,它保證了數據在各種應用場景中的兼容性和完整性,簡化了數據的傳輸和存儲。

參考資料:

https://blog.csdn.net/qq_28205153/article/details/55798628

希望這篇文章對你有一定幫助。

user avatar codepencil 頭像 pugongyingxiangyanghua 頭像 mofaboshi 頭像 yihan123 頭像 zhuomoxiansheng_5f1901de6fd23 頭像 notrynosuccess 頭像 643104191 頭像 hailongwang_od 頭像 yangyaya 頭像 kuanrongdebeizi 頭像 yaochujiadejianpan 頭像 meng_nn 頭像
35 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.