package com.ymwk.icvp.pki.service.impl; import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.crypto.Cipher; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.Base64; @Component @Slf4j public class CryptoService { private final String masterKey = "12345678901234567890123456789012"; // 32字节的主密钥 private static final String ALGORITHM = "AES/GCM/NoPadding"; private static final int GCM_IV_LENGTH = 12; private static final int GCM_TAG_LENGTH = 128; /** * AES-GCM加密 */ public String encrypt(String plaintext) throws Exception { byte[] iv = new byte[GCM_IV_LENGTH]; SecureRandom random = new SecureRandom(); random.nextBytes(iv); Cipher cipher = Cipher.getInstance(ALGORITHM); SecretKeySpec keySpec = new SecretKeySpec( masterKey.getBytes(StandardCharsets.UTF_8), "AES" ); GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec); byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); // 将IV和密文合并(Base64编码) byte[] combined = new byte[iv.length + ciphertext.length]; System.arraycopy(iv, 0, combined, 0, iv.length); System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length); return Base64.getEncoder().encodeToString(combined); } /** * AES-GCM解密 */ public String decrypt(String ciphertextBase64) throws Exception { byte[] combined = Base64.getDecoder().decode(ciphertextBase64); // 提取IV和密文 byte[] iv = new byte[GCM_IV_LENGTH]; byte[] ciphertext = new byte[combined.length - GCM_IV_LENGTH]; System.arraycopy(combined, 0, iv, 0, GCM_IV_LENGTH); System.arraycopy(combined, GCM_IV_LENGTH, ciphertext, 0, ciphertext.length); Cipher cipher = Cipher.getInstance(ALGORITHM); SecretKeySpec keySpec = new SecretKeySpec( masterKey.getBytes(StandardCharsets.UTF_8), "AES" ); GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec); byte[] plaintext = cipher.doFinal(ciphertext); return new String(plaintext, StandardCharsets.UTF_8); } }