Java接口加解密案例

wen java案例 3

本文目录导读:

Java接口加解密案例

  1. AES对称加解密方案
  2. RSA非对称加解密方案
  3. 完整接口示例
  4. 配置文件
  5. 客户端调用示例
  6. 安全建议

我将为您提供Java接口加解密的完整案例,包括对称加密(AES)和非对称加密(RSA)两种方案。

AES对称加解密方案

1 AES工具类

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
/**
 * AES-GCM加密工具类
 * 使用AES-128/256位加密,GCM模式(支持认证)
 */
public class AesUtil {
    private static final String AES = "AES";
    private static final String AES_GCM = "AES/GCM/NoPadding";
    private static final int IV_LENGTH = 12;  // GCM推荐IV长度
    private static final int TAG_LENGTH = 128; // 认证标签长度
    /**
     * 生成AES密钥
     */
    public static String generateKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance(AES);
        keyGen.init(256, new SecureRandom());
        SecretKey secretKey = keyGen.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }
    /**
     * 加密数据
     * @param plainText 明文
     * @param base64Key Base64编码的密钥
     * @return Base64编码的密文(包含IV)
     */
    public static String encrypt(String plainText, String base64Key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES);
        byte[] iv = new byte[IV_LENGTH];
        new SecureRandom().nextBytes(iv);
        Cipher cipher = Cipher.getInstance(AES_GCM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new GCMParameterSpec(TAG_LENGTH, iv));
        byte[] cipherText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        // 将IV和密文拼接返回
        byte[] result = new byte[iv.length + cipherText.length];
        System.arraycopy(iv, 0, result, 0, iv.length);
        System.arraycopy(cipherText, 0, result, iv.length, cipherText.length);
        return Base64.getEncoder().encodeToString(result);
    }
    /**
     * 解密数据
     */
    public static String decrypt(String encryptedData, String base64Key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES);
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
        // 提取IV和密文
        byte[] iv = new byte[IV_LENGTH];
        byte[] cipherText = new byte[encryptedBytes.length - IV_LENGTH];
        System.arraycopy(encryptedBytes, 0, iv, 0, iv.length);
        System.arraycopy(encryptedBytes, iv.length, cipherText, 0, cipherText.length);
        Cipher cipher = Cipher.getInstance(AES_GCM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, new GCMParameterSpec(TAG_LENGTH, iv));
        byte[] plainText = cipher.doFinal(cipherText);
        return new String(plainText, StandardCharsets.UTF_8);
    }
}

2 AES拦截器实现

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.util.stream.Collectors;
/**
 * AES接口加密拦截器
 */
public class AesInterceptor implements HandlerInterceptor {
    private static final String AES_KEY = "your-aes-key-here-256bit"; // 建议从配置中心获取
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
            throws Exception {
        // 只处理POST请求
        if ("POST".equals(request.getMethod())) {
            // 读取请求体
            BufferedReader reader = request.getReader();
            String body = reader.lines().collect(Collectors.joining());
            if (body != null && !body.isEmpty()) {
                try {
                    // 解密请求数据
                    String decrypted = AesUtil.decrypt(body, AES_KEY);
                    // 将解密后的数据封装为新的请求
                    request.setAttribute("decryptedBody", decrypted);
                } catch (Exception e) {
                    response.setStatus(400);
                    response.getWriter().write("{\"error\":\"Invalid encrypted data\"}");
                    return false;
                }
            }
        }
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                               Object handler, Exception ex) throws Exception {
        // 响应加密逻辑可以在ResponseBodyAdvice中处理
    }
}

3 AES响应加密配置

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.HashMap;
import java.util.Map;
/**
 * AES响应加密处理
 */
@ControllerAdvice
public class AesResponseAdvice implements ResponseBodyAdvice<Object> {
    private static final String AES_KEY = "your-aes-key-here-256bit";
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 自定义需要加密的注解或条件
        return returnType.hasMethodAnnotation(EncryptResponse.class);
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                 Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                 ServerHttpRequest request, ServerHttpResponse response) {
        try {
            // 将响应数据加密
            String jsonData = new ObjectMapper().writeValueAsString(body);
            String encrypted = AesUtil.encrypt(jsonData, AES_KEY);
            Map<String, String> result = new HashMap<>();
            result.put("data", encrypted);
            return result;
        } catch (Exception e) {
            return body;
        }
    }
}
/**
 * 自定义注解,标记需要加密的响应
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptResponse {
}

RSA非对称加解密方案

1 RSA工具类

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
 * RSA加密工具类
 */
public class RsaUtil {
    private static final String RSA_ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
    /**
     * 生成密钥对
     */
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }
    /**
     * 使用公钥加密
     */
    public static String encrypt(String data, String publicKey) throws Exception {
        PublicKey key = getPublicKey(publicKey);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    /**
     * 使用私钥解密
     */
    public static String decrypt(String encryptedData, String privateKey) throws Exception {
        PrivateKey key = getPrivateKey(privateKey);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decryptedBytes, "UTF-8");
    }
    /**
     * 使用私钥签名
     */
    public static String sign(String data, String privateKey) throws Exception {
        PrivateKey key = getPrivateKey(privateKey);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(key);
        signature.update(data.getBytes("UTF-8"));
        byte[] signatureBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signatureBytes);
    }
    /**
     * 使用公钥验签
     */
    public static boolean verify(String data, String signature, String publicKey) throws Exception {
        PublicKey key = getPublicKey(publicKey);
        Signature verifySignature = Signature.getInstance("SHA256withRSA");
        verifySignature.initVerify(key);
        verifySignature.update(data.getBytes("UTF-8"));
        return verifySignature.verify(Base64.getDecoder().decode(signature));
    }
    private static PublicKey getPublicKey(String base64Key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }
    private static PrivateKey getPrivateKey(String base64Key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }
}

2 混合加密方案(推荐)

import java.util.HashMap;
import java.util.Map;
/**
 * 混合加密服务(AES + RSA)
 * 使用RSA加密AES密钥,AES加密数据
 */
@Service
public class HybridEncryptionService {
    // RSA公钥和私钥应该是从配置或密钥管理系统中获取
    private static final String RSA_PUBLIC_KEY = "your-rsa-public-key";
    private static final String RSA_PRIVATE_KEY = "your-rsa-private-key";
    /**
     * 加密请求数据
     */
    public Map<String, String> encryptRequest(Object data) throws Exception {
        Map<String, String> result = new HashMap<>();
        // 1. 生成一次性的AES密钥
        String aesKey = AesUtil.generateKey();
        // 2. 使用AES加密数据
        String jsonData = new ObjectMapper().writeValueAsString(data);
        String encryptedData = AesUtil.encrypt(jsonData, aesKey);
        // 3. 使用RSA公钥加密AES密钥
        String encryptedAesKey = RsaUtil.encrypt(aesKey, RSA_PUBLIC_KEY);
        result.put("data", encryptedData);
        result.put("key", encryptedAesKey);
        return result;
    }
    /**
     * 解密响应数据
     */
    public Object decryptResponse(Map<String, String> encryptedData, Class<?> targetClass) throws Exception {
        // 1. 使用RSA私钥解密AES密钥
        String aesKey = RsaUtil.decrypt(encryptedData.get("key"), RSA_PRIVATE_KEY);
        // 2. 使用AES密钥解密数据
        String jsonData = AesUtil.decrypt(encryptedData.get("data"), aesKey);
        // 3. 转换为目标对象
        return new ObjectMapper().readValue(jsonData, targetClass);
    }
}

完整接口示例

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    private HybridEncryptionService encryptionService;
    @Autowired
    private UserService userService;
    /**
     * 加密的POST请求
     */
    @PostMapping("/user/encrypted")
    @EncryptResponse
    public ResponseEntity<?> createUser(@RequestBody Map<String, String> encryptedRequest) {
        try {
            // 解密请求数据
            UserRequest userRequest = (UserRequest) encryptionService.decryptResponse(
                encryptedRequest, UserRequest.class);
            // 处理业务逻辑
            User user = userService.createUser(userRequest);
            // 返回加密的响应
            Map<String, String> response = encryptionService.encryptRequest(user);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("Decryption failed: " + e.getMessage());
        }
    }
    /**
     * 简单AES加密的请求
     */
    @PostMapping("/user/aes")
    public ResponseEntity<?> createUserAes(@RequestBody EncryptedRequest request) {
        try {
            String decryptedData = AesUtil.decrypt(
                request.getData(), 
                ConfigProperties.get("aes.key")
            );
            UserRequest userRequest = new ObjectMapper()
                .readValue(decryptedData, UserRequest.class);
            User user = userService.createUser(userRequest);
            Map<String, String> response = new HashMap<>();
            response.put("encrypted", "true");
            response.put("data", AesUtil.encrypt(
                new ObjectMapper().writeValueAsString(user), 
                ConfigProperties.get("aes.key")
            ));
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("Processing failed");
        }
    }
}
/**
 * 加密请求DTO
 */
public class EncryptedRequest {
    private String data;
    private String key;
    // getters and setters...
}

配置文件

# application.yml
encryption:
  aes:
    key: your-aes-key-here-256bit
  rsa:
    public-key: your-rsa-public-key
    private-key: your-rsa-private-key
  enabled: true
  exclude-paths:
    - /api/public
    - /api/health

客户端调用示例

public class ApiClient {
    private RestTemplate restTemplate = new RestTemplate();
    /**
     * 发送加密请求
     */
    public void sendEncryptedRequest() throws Exception {
        // 准备数据
        UserRequest request = new UserRequest();
        request.setName("张三");
        request.setPhone("13800001234");
        // 获取服务器RSA公钥(可以从认证接口获取)
        String rsaPublicKey = getServerPublicKey();
        // 生成AES密钥
        String aesKey = AesUtil.generateKey();
        // 使用AES加密数据
        String jsonData = new ObjectMapper().writeValueAsString(request);
        String encryptedData = AesUtil.encrypt(jsonData, aesKey);
        // 使用RSA公钥加密AES密钥
        String encryptedAesKey = RsaUtil.encrypt(aesKey, rsaPublicKey);
        // 构建请求
        Map<String, String> body = new HashMap<>();
        body.put("data", encryptedData);
        body.put("key", encryptedAesKey);
        // 发送请求
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, String>> entity = new HttpEntity<>(body, headers);
        ResponseEntity<Map> response = restTemplate.exchange(
            "https://api.example.com/api/user/encrypted",
            HttpMethod.POST,
            entity,
            Map.class
        );
        // 解密响应
        if (response.getStatusCode() == HttpStatus.OK) {
            Map<String, String> responseBody = response.getBody();
            // 使用私钥解密AES密钥(客户端需要持有私钥)
            String decryptedAesKey = RsaUtil.decrypt(
                responseBody.get("key"), 
                getClientPrivateKey()
            );
            // 使用AES密钥解密数据
            String decryptedData = AesUtil.decrypt(
                responseBody.get("data"), 
                decryptedAesKey
            );
            System.out.println("解密后的响应: " + decryptedData);
        }
    }
}

安全建议

// 1. 密钥管理
public class KeyManagementUtil {
    // 定期轮换密钥
    @Scheduled(cron = "0 0 0 * * ?")
    public void rotateKeys() {
        // 生成新密钥
        // 更新到配置中心
        // 定期清理旧密钥
    }
    // 防止重放攻击
    public boolean validateTimestamp(String timestamp) {
        long requestTime = Long.parseLong(timestamp);
        long currentTime = System.currentTimeMillis();
        return Math.abs(currentTime - requestTime) < 300000; // 5分钟有效
    }
    // 添加请求签名
    public String generateSignature(String data, String key) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(
                key.getBytes(), "HmacSHA256"
            );
            mac.init(secretKeySpec);
            return Base64.getEncoder().encodeToString(
                mac.doFinal(data.getBytes())
            );
        } catch (Exception e) {
            throw new RuntimeException("签名生成失败", e);
        }
    }
}
// 2. 日志脱敏
public class SensitiveDataUtil {
    private static final Pattern PHONE_PATTERN = Pattern.compile("(\\d{3})\\d{4}(\\d{4})");
    public static String desensitize(String data) {
        if (data == null) return null;
        // 手机号脱敏
        data = PHONE_PATTERN.matcher(data).replaceAll("$1****$2");
        // 其他敏感信息处理...
        return data;
    }
}

这个完整的案例涵盖了:

  1. AES对称加密 - 适合大规模数据传输
  2. RSA非对称加密 - 用于密钥交换和数字签名
  3. 混合加密方案 - 推荐的生产级方案
  4. 拦截器实现 - 自动处理加密解密
  5. 安全配置 - 密钥管理、防重放攻击等

使用时请根据实际需求选择合适的方案,并确保密钥安全存储。

抱歉,评论功能暂时关闭!