当前位置: 首页 > news >正文

无需公钥的无损加密解密

Java 实现方案:通过自定义编码(Base64)+ 时间戳动态密钥 + AES 对称加密,实现无需公钥的无损加密解密。核心逻辑是利用时间戳生成动态密钥,加密和解密时通过相同的时间戳验证和密钥生成规则确保数据一致性

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;public class TimeBasedCrypto {// 固定密钥(实际使用中需安全存储,如配置中心)private static final String FIXED_KEY = "your-secure-fixed-key-123";// 时间戳容忍范围(毫秒),防止时钟偏差导致解密失败private static final long TIMESTAMP_TOLERANCE = 5 * 60 * 1000; // 5分钟/*** 加密流程:参数编码 -> 生成时间戳密钥 -> AES加密* @param originalParam 原始参数(明文)* @return 加密后的数据(格式:Base64(加密内容):时间戳)*/public static String encrypt(String originalParam) throws Exception {// 1. 对原始参数进行Base64编码(确保二进制安全传输)String encodedParam = Base64.getEncoder().encodeToString(originalParam.getBytes(StandardCharsets.UTF_8));// 2. 生成当前时间戳(毫秒)long timestamp = System.currentTimeMillis();// 3. 基于时间戳和固定密钥生成AES密钥(AES密钥长度需为16/24/32字节)SecretKeySpec secretKey = generateKey(timestamp);// 4. AES加密编码后的参数Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedBytes = cipher.doFinal(encodedParam.getBytes(StandardCharsets.UTF_8));// 5. 加密内容Base64编码,与时间戳拼接返回(格式:加密内容:时间戳)String encryptedContent = Base64.getEncoder().encodeToString(encryptedBytes);return encryptedContent + ":" + timestamp;}/*** 解密流程:解析时间戳 -> 验证有效性 -> 生成密钥 -> AES解密 -> 解码参数* @param encryptedData 加密后的数据(格式:Base64(加密内容):时间戳)* @return 原始参数(明文)*/public static String decrypt(String encryptedData) throws Exception {// 1. 拆分加密内容和时间戳String[] parts = encryptedData.split(":", 2);if (parts.length != 2) {throw new IllegalArgumentException("无效的加密数据格式");}String encryptedContent = parts[0];long timestamp = Long.parseLong(parts[1]);// 2. 验证时间戳有效性(是否在容忍范围内)long currentTime = System.currentTimeMillis();if (Math.abs(currentTime - timestamp) > TIMESTAMP_TOLERANCE) {throw new SecurityException("时间戳过期或无效(超出" + TIMESTAMP_TOLERANCE + "毫秒)");}// 3. 基于相同时间戳生成解密密钥SecretKeySpec secretKey = generateKey(timestamp);// 4. AES解密Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decodedBytes = Base64.getDecoder().decode(encryptedContent);byte[] decryptedBytes = cipher.doFinal(decodedBytes);String encodedParam = new String(decryptedBytes, StandardCharsets.UTF_8);// 5. Base64解码,恢复原始参数return new String(Base64.getDecoder().decode(encodedParam), StandardCharsets.UTF_8);}/*** 生成AES密钥:时间戳+固定密钥哈希后取前16字节(AES-128)*/private static SecretKeySpec generateKey(long timestamp) throws Exception {// 拼接时间戳和固定密钥String keyMaterial = timestamp + ":" + FIXED_KEY;// SHA-256哈希确保密钥随机性,取前16字节作为AES-128密钥MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[] keyBytes = digest.digest(keyMaterial.getBytes(StandardCharsets.UTF_8));byte[] aesKey = new byte[16];System.arraycopy(keyBytes, 0, aesKey, 0, 16); // 截取前16字节return new SecretKeySpec(aesKey, "AES");}// 测试示例public static void main(String[] args) throws Exception {// 原始数据String original = "这是一段需要加密的数据:123456";System.out.println("原始数据:" + original);// 加密String encrypted = encrypt(original);System.out.println("加密后:" + encrypted);// 解密String decrypted = decrypt(encrypted);System.out.println("解密后:" + decrypted);// 验证无损性System.out.println("解密是否无损:" + original.equals(decrypted));}
}

核心逻辑说明

  1. 编码层:使用 Base64 编码原始参数,避免二进制数据在传输中被破坏(如 HTTP 请求参数、JSON 字段)。

  2. 密钥生成

    • 加密时,将当前时间戳与固定密钥拼接,通过 SHA-256 哈希生成 32 字节摘要,取前 16 字节作为 AES-128 密钥(确保密钥长度符合 AES 要求)。
    • 解密时,使用加密数据中携带的时间戳,按相同规则重新生成密钥,无需公钥即可解密。
  3. 时间戳验证:解密时检查时间戳是否在容忍范围内(如 5 分钟),防止过期数据被重复使用(类似防重放机制)。

  4. 加密算法:采用 AES 对称加密(ECB 模式 + PKCS5 填充),加密解密使用同一密钥,确保无损解密(前提是密钥一致)。

注意事项

  1. 安全性

    • 固定密钥(FIXED_KEY)需严格保密,建议通过安全配置中心管理,避免硬编码。
    • ECB 模式安全性较低(相同明文加密后结果相同),生产环境可改用 CBC/GCM 模式(需额外处理 IV 向量)。
    • 时间戳容忍范围需根据业务场景调整(过短可能因时钟偏差解密失败,过长增加重放风险)。
  2. 无损性保证:Base64 编码和解码、AES 加密和解密均为可逆操作,只要密钥正确,解密后的数据与原始数据完全一致。

  3. 适用场景:适合短期有效的数据传输(如 API 请求签名、临时令牌),不适合长期存储加密(时间戳过期后无法解密)。

通过这种方式,无需公钥体系即可实现数据的安全加密和解密,且时间戳的引入增加了密钥的动态性,提升了安全性。

http://www.dtcms.com/a/331317.html

相关文章:

  • 深入详解C语言数组:承上启下——从C语言数组基础到数据结构衔接
  • 码上爬第八题【协程+ob混淆】
  • 【Java虚拟机】JVM相关面试题
  • 2025天府杯数学建模C题
  • 2025天府杯数学建模A题分析
  • 智能门锁:安全与便捷的现代家居入口
  • 第1节 从函数到神经网络:AI思路的逆袭之路
  • Mybatis学习笔记(八)
  • VS2022 C++生成和调用DLL动态链接库
  • 小杰python高级(six day)——pandas库
  • 自由学习记录(84)
  • nnDetection在windows系统下使用教程
  • 4.Ansible部署文件到主机
  • Torch -- 卷积学习day2 -- 卷积扩展、数据集、模型
  • Linux软件编程(四)多任务与多进程管理
  • 机械硬盘模块逻辑与工作原理
  • 某处卖600的【独角仙】尾盘十分钟短线 尾盘短线思路 手机电脑通用无未来函数
  • uniapp对接极光消息推送
  • 【CLR via C#(第3版)阅读笔记】类型基础
  • [特殊字符]走进华为,解锁商业传奇密码
  • K8s学习----Namespace:资源隔离与环境管理的核心机制
  • 渲染 opentype 多个字符的文本,并设置文本的渲染开始位置
  • Warm-Flow 1.8.0 重大更新
  • Lua 脚本在 Redis 中的应用
  • vivo Pulsar 万亿级消息处理实践(4)-Ansible运维部署
  • 河南萌新联赛2025第(五)场:信息工程大学补题
  • 飞书文档定时自动同步至百炼知识库
  • ESP32 I2S音频总线学习笔记(六):DIY蓝牙音箱教程
  • CVPR 2025 | 北大团队SLAM3R:单目RGB长视频实时重建,精度效率双杀!
  • 在mysql> 下怎么运行 .sql脚本