数据加密 — AES-GCM 模式

AES-GCM 模式

推荐用于用户敏感数据加密(如手机号、收货地址)

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
 
public class AesGcmEncryption {
    private static final int GCM_IV_LENGTH = 12;  // 推荐12字节
    private static final int GCM_TAG_LENGTH = 128;  // 认证标签长度
    
    // 加密
    public byte[] encrypt(byte[] data, byte[] key) throws Exception {
        byte[] iv = new byte[GCM_IV_LENGTH];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), spec);
        
        byte[] encrypted = cipher.doFinal(data);
        
        // IV + 密文
        byte[] result = new byte[iv.length + encrypted.length];
        System.arraycopy(iv, 0, result, 0, iv.length);
        System.arraycopy(encrypted, 0, result, iv.length, encrypted.length);
        return result;
    }
    
    // 解密
    public byte[] decrypt(byte[] encryptedData, byte[] key) throws Exception {
        byte[] iv = new byte[GCM_IV_LENGTH];
        byte[] ciphertext = new byte[encryptedData.length - GCM_IV_LENGTH];
        System.arraycopy(encryptedData, 0, iv, 0, GCM_IV_LENGTH);
        System.arraycopy(encryptedData, GCM_IV_LENGTH, ciphertext, 0, ciphertext.length);
        
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), spec);
        
        return cipher.doFinal(ciphertext);
    }
}

AES-GCM 优势

特性说明
加密+认证自带消息认证码(MAC),防止篡改
安全性高防止填充Oracle攻击,比CBC模式更安全
效率高并行加密,性能优于其他模式

IV(初始化向量)要点

  • 唯一性:每个加密操作必须使用唯一IV
  • 随机性:使用SecureRandom生成
  • 存储:IV与密文一起存储(不需要保密)
  • 长度:推荐12字节(96位),兼顾安全性和性能

国密算法支持(SM4)

国内合规要求时使用

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
 
public class SM4Encryption {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    
    public byte[] encryptSM4Gcm(byte[] data, byte[] key, byte[] iv) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/GCM/NoPadding", "BC");
        GCMParameterSpec spec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "SM4"), spec);
        return cipher.doFinal(data);
    }
}

对称加密 vs 非对称加密

概念说明
对称加密加密解密使用相同密钥(AES、SM4)
非对称加密加密解密使用不同密钥(RSA)

面试要点

常见面试问题

Q:为什么推荐AES-GCM而不是CBC?

A:GCM模式自带认证功能,能检测数据是否被篡改,且避免了CBC模式的填充Oracle攻击风险。

参考链接