動態

詳情 返回 返回

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 smalike 頭像 jingdongkeji 頭像 qingzhan 頭像 chongdianqishi 頭像 razyliang 頭像 guixiangyyds 頭像 wmbuke 頭像 yixiyidong 頭像 weidewei 頭像 tanggoahead 頭像 lin494910940 頭像 xiaoxxuejishu 頭像
點贊 68 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.