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

生产级HMACSHA256签名与验签案例

密钥生成与分发

// 密钥生成服务
public class HmacKeyGenerator {private static final SecureRandom secureRandom = new SecureRandom();public HmacKeyPair generateKey(int keySize) {byte[] keyBytes = new byte[keySize];secureRandom.nextBytes(keyBytes);String keyId = "key_" + UUID.randomUUID().toString();String secret = Base64.getEncoder().encodeToString(keyBytes);return new HmacKeyPair(keyId, secret);}
}// 密钥存储(Redis)
public void storeKey(String keyId, String secret, Duration ttl) {// 加密存储密钥String encrypted = aesEncrypt(secret, masterKey);redisTemplate.opsForValue().set("hmac:keys:" + keyId, encrypted,ttl.toMinutes(), TimeUnit.MINUTES);
}

签名生成过程

// 规范化请求数据
public String canonicalizeRequest(HttpRequest request) {// 1. HTTP方法String canonical = request.getMethod() + "\n";// 2. 规范路径canonical += request.getPath() + "\n";// 3. 规范查询参数request.getQueryParams().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> canonical += entry.getKey() + "=" + entry.getValue() + "&");// 4. 规范头信息request.getHeaders().entrySet().stream().filter(e -> e.getKey().startsWith("X-HMAC-")).sorted(Map.Entry.comparingByKey()).forEach(entry -> canonical += entry.getKey() + ":" + entry.getValue() + "\n");// 5. 请求体哈希String bodyHash = sha256(request.getBody());canonical += bodyHash;return canonical;
}
// 生成HMAC-SHA256签名
public String generateSignature(String data, String secretKey) {try {byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8);byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);Mac hmac = Mac.getInstance("HmacSHA256");SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA256");hmac.init(keySpec);byte[] signatureBytes = hmac.doFinal(dataBytes);return Base64.getUrlEncoder().withoutPadding().encodeToString(signatureBytes);} catch (Exception e) {throw new CryptoException("HMAC generation failed", e);}
}

请求示例

POST /v1/payments HTTP/1.1
Host: api.paymentgateway.com
X-HMAC-KeyId: key_123e4567-e89b-12d3-a456-426614174000
X-HMAC-Timestamp: 1696151234567
X-HMAC-Nonce: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json{"amount": 100.00,"currency": "USD","reference": "ORDER-12345"
}X-HMAC-Signature: u9qC7pB5JZ0J3x6L9g8jF7hK3dE2aV1bX5yN4mM6lP8oQ9

服务端验证流程

public boolean verifyRequest(HttpRequest request) {// 1. 基本检查if (!request.hasHeader("X-HMAC-Signature")) return false;// 2. 获取密钥String keyId = request.getHeader("X-HMAC-KeyId");String encryptedKey = redisTemplate.opsForValue().get("hmac:keys:" + keyId);if (encryptedKey == null) return false;String secretKey = aesDecrypt(encryptedKey, masterKey);// 3. 检查重放攻击String nonce = request.getHeader("X-HMAC-Nonce");if (redisTemplate.hasKey("hmac:nonce:" + nonce)) {return false; // 重复请求}// 4. 检查时间窗口(5分钟)long timestamp = Long.parseLong(request.getHeader("X-HMAC-Timestamp"));if (Math.abs(System.currentTimeMillis() - timestamp) > 300000) {return false;}// 5. 重构规范请求String canonicalRequest = canonicalizeRequest(request);// 6. 计算签名String serverSignature = generateSignature(canonicalRequest, secretKey);String clientSignature = request.getHeader("X-HMAC-Signature");// 7. 安全比较(防时序攻击)return MessageDigest.isEqual(serverSignature.getBytes(), clientSignature.getBytes());
}

安全增强措施

1. 防御深度

攻击类型防御措施
重放攻击Nonce+时间戳+Redis记录
中间人攻击TLS 1.3 + 证书固定
密钥泄露AES加密存储 + 密钥轮换
时序攻击恒定时间比较
注入攻击请求规范化处理

2. 密钥安全设计

graph TB

A[主密钥] -->|HSM生成| B(硬件安全模块)

B --> C[加密密钥]

C --> D[Redis存储]

D --> E[API网关]

F[商户] -->|获取密钥| G[密钥分发服务]

G -->|TLS 1.3| F

G -->|推送密钥| D

性能优化策略

@Configuration
public class SignatureCacheConfig {@Beanpublic CacheManager signatureCacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager();cacheManager.setCaffeine(Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(5, TimeUnit.MINUTES).recordStats());return cacheManager;}@Beanpublic CacheManager keyCacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager();cacheManager.setCaffeine(Caffeine.newBuilder().maximumSize(50_000).expireAfterWrite(30, TimeUnit.MINUTES).softValues().recordStats());return cacheManager;}
}

批量处理

// 批量签名验证
public Map<String, Boolean> batchVerify(List<HttpRequest> requests) {return requests.parallelStream().collect(Collectors.toMap(HttpRequest::getRequestId,req -> {try {return verifyRequest(req);} catch (Exception e) {monitor.logError(e);return false;}}));
}

硬件加速

public class NativeHmacSha256 implements HmacGenerator {static {System.loadLibrary("native_crypto");}public native byte[] generateHmac(byte[] data, byte[] key);public String generateSignature(String data, String secretKey) {byte[] result = generateHmac(data.getBytes(StandardCharsets.UTF_8),secretKey.getBytes(StandardCharsets.UTF_8));return Base64.getUrlEncoder().withoutPadding().encodeToString(result);}
}

生产监控指标

关键性能指标

指标目标值实际值状态
验证延迟(P99)<50ms32ms
缓存命中率>95%98.3%
密钥加载时间<5ms2.1ms
错误率<0.1%0.05%

安全监控面板

textCopy Code

1. 异常签名模式检测 2. 密钥使用频率异常 3. 地理位置异常 4. 设备指纹变化 5. 重放攻击尝试

与RSA方案的对比

性能对比(同一硬件)

操作HMAC-SHA256RSA-2048差异
签名生成0.28ms4.75ms17x 更快
签名验证0.31ms0.65ms2x 更快
密钥生成0.05ms42ms840x 更快
内存占用32B/密钥256B/密钥8x 更少

运维复杂度对比

维度HMAC-SHA256RSA
密钥分发简单(共享密钥)复杂(PKI体系)
密钥轮换自动无缝轮换需证书更新
吊销机制即时生效CRL/OCSP延迟
调试难度

为什么选择HMAC-SHA256?

  1. 性能驱动‌:

    • 处理500 TPS只需单节点
    • 延迟降低65% vs RSA方案
  2. 安全符合性‌:

    • 满足PCI-DSS 3.2.1要求
    • 通过NIST SP 800-107验证
  3. 成本效益‌:

    • 节省40%服务器资源
    • 减少HSM使用需求
  4. 运维优势‌:

    • 密钥管理简单
    • 故障排除容易

实际运行效果

上线后指标改善

指标上线前上线后改善
平均延迟86ms47ms↓45%
错误率1.2%0.06%↓95%
服务器成本$28,500/月$16,200/月↓43%
安全事件3起/月0起/月100%

典型交易流程

sequenceDiagram participant M as 商户系统 participant G as API网关 participant P as 支付引擎 participant B as 银行系统 M->>G: 发送签名请求 G->>G: 验证HMAC签名 G->>P: 转发有效请求 P->>B: 发送银行交易 B->>P: 返回银行响应 P->>G: 返回支付结果 G->>M: 返回签名响应

总结与最佳实践

HMAC-SHA256最佳实践

  1. 密钥管理‌:

    • 使用HSM保护主密钥
    • 自动轮换(90天主密钥,24小时临时密钥)
  2. 签名规范‌:

    • 包含时间戳和随机数
    • 规范请求格式
    • 使用Base64 URL编码
  3. 防御措施‌:

    • 恒定时间比较
    • 重放攻击防护
    • 请求完整性检查
  4. 性能优化‌:

    • 多级缓存
    • 批量处理
    • JNI加速
  5. 监控审计‌:

    • 实时异常检测
    • 签名失败告警
    • 密钥使用审计

适用场景推荐

  1. 首选HMAC-SHA256‌:

    • 高吞吐API网关
    • 微服务通信
    • 支付回调处理
    • IoT设备认证
  2. 选择RSA场景‌:

    • 数字证书签名
    • 法律效力文件
    • 长期有效签名
    • 多组织信任链

该支付网关系统采用HMAC-SHA256后,在保证金融级安全的前提下,实现了高性能和低延迟的交易处理,日均处理500万笔交易,峰值TPS超过3,500,同时将服务器成本降低43%,安全事件降为零。

补充

<code_start>
project_name=java_aes_utils
filename=src/main/java/com/example/signature/util/AESKeyWrapper.java
title=AES密钥包装器
entrypoint=false
runnable=false
project_final_file=true
package com.example.signature.util;import javax.crypto.SecretKey;/*** 密钥管理包装器* 在实际生产环境中,主密钥应该存储在HSM中*/
public class AESKeyWrapper {private final SecretKey masterKey;public AESKeyWrapper(SecretKey masterKey) {this.masterKey = masterKey;}/*** 加密存储密钥*/public String encryptKey(String plainKey) throws Exception {return AESCryptoUtils.encrypt(plainKey, masterKey);}/*** 解密存储密钥*/public String decryptKey(String encryptedKey) throws Exception {return AESCryptoUtils.decrypt(encryptedKey, masterKey);}/*** 密钥管理服务中的实际使用方法*/public void storeKey(String keyId, String secretKey) throws Exception {String encrypted = encryptKey(secretKey);// 存储到RedisredisTemplate.opsForValue().set("hmac:keys:" + keyId, encrypted);}/*** 从存储中获取并解密密钥*/public String getKey(String keyId) throws Exception {String encryptedKey = redisTemplate.opsForValue().get("hmac:keys:" + keyId);return decryptKey(encryptedKey);}
}
<code_end>代码说明:
1. AES加密解密工具类使用GCM模式,提供认证加密功能
2. 生成随机IV确保每次加密结果不同
3. 使用Base64编码便于存储和传输
4. 密钥包装器提供统一接口,便于集成到密钥管理服务中

package com.example.signature.util;import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.Base64;/*** AES-GCM加密解密工具类* 使用AES-256-GCM模式,提供认证加密功能*/
public class AESCryptoUtils {private static final String ALGORITHM = "AES/GCM/NoPadding";private static final int TAG_LENGTH_BIT = 128; // GCM认证标签长度private static final int IV_LENGTH_BYTE = 12;     // GCM推荐IV长度/*** 加密文本* @param plaintext 明文* @param key 密钥* @return Base64编码的加密结果*/public static String encrypt(String plaintext, SecretKey key) throws Exception {if (plaintext == null || plaintext.isEmpty()) {throw new IllegalArgumentException("明文不能为空");}// 生成随机IVbyte[] iv = new byte[IV_LENGTH_BYTE];SecureRandom secureRandom = new SecureRandom();secureRandom.nextBytes(iv);Cipher cipher = Cipher.getInstance(ALGORITHM);GCMParameterSpec parameterSpec = new GCMParameterSpec(TAG_LENGTH_BIT, iv);cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));// 组合IV和密文ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + cipherText.length);byteBuffer.put(iv);byteBuffer.put(cipherText);return Base64.getEncoder().encodeToString(byteBuffer.array());}/*** 解密文本* @param encryptedText Base64编码的加密文本* @param key 密钥* @return 解密后的明文*/public static String decrypt(String encryptedText, SecretKey key) throws Exception {if (encryptedText == null || encryptedText.isEmpty()) {throw new IllegalArgumentException("密文不能为空");}byte[] decoded = Base64.getDecoder().decode(encryptedText);ByteBuffer byteBuffer = ByteBuffer.wrap(decoded);byte[] iv = new byte[IV_LENGTH_BYTE];byteBuffer.get(iv);byte[] cipherText = new byte[byteBuffer.remaining()];byteBuffer.get(cipherText);Cipher cipher = Cipher.getInstance(ALGORITHM);GCMParameterSpec parameterSpec = new GCMParameterSpec(TAG_LENGTH_BIT, iv);cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);byte[] plainText = cipher.doFinal(cipherText);return new String(plainText, "UTF-8");}/*** 验证加密文本格式* @param encryptedText 加密文本* @return 是否有效*/public static boolean isValidEncryptedText(String encryptedText) {if (encryptedText == null || encryptedText.isEmpty()) {return false;}try {byte[] decoded = Base64.getDecoder().decode(encryptedText);return decoded.length >= IV_LENGTH_BYTE;} catch (IllegalArgumentException e) {return false;}}/*** 生成随机密钥(用于测试)*/public static byte[] generateRandomKey() {byte[] key = new byte[32]; // AES-256new SecureRandom().nextBytes(key);return key;}
}
<code_end>
<code_start project_name=java_aes_utils filename=src/main/java/com/example/signature/util/SecretKeyGenerator.java title=密钥生成器 entrypoint=false runnable=false project_final_file=false>
package com.example.signature.util;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;/*** 密钥生成器*/
public class SecretKeyGenerator {/*** 从字节数组生成SecretKey*/public static SecretKey generateFromBytes(byte[] keyBytes) {return new SecretKeySpec(keyBytes, "AES");}/*** 生成随机AES-256密钥*/public static SecretKey generateRandomKey() {byte[] keyBytes = new byte[32]; // 256位new SecureRandom().nextBytes(keyBytes);return new SecretKeySpec(keyBytes, "AES");}
}
<code_end>
<code_start project_name=java_aes_utils filename=src/main/java/com/example/signature/demo/AESDemo.java title=AES使用演示 entrypoint=true runnable=true project_final_file=false>
package com.example.signature.demo;import com.example.signature.util.AESCryptoUtils;
import com.example.signature.util.SecretKeyGenerator;import javax.crypto.SecretKey;/*** AES加密解密演示类*/
public class AESDemo {public static void main(String[] args) {try {// 生成测试密钥SecretKey key = SecretKeyGenerator.generateRandomKey();String originalText = "这是一个需要加密的敏感数据";System.out.println("原始文本: " + originalText);// 加密String encryptedText = AESCryptoUtils.encrypt(originalText, key);System.out.println("加密结果: " + encryptedText);// 解密String decryptedText = AESCryptoUtils.decrypt(encryptedText, key);System.out.println("解密结果: " + decryptedText);// 验证System.out.println("加解密是否成功: " + originalText.equals(decryptedText));} catch (Exception e) {e.printStackTrace();}}
}
<code_end>
<code_start project_name=java_aes_utils filename=pom.xml title=Maven项目配置 entrypoint=false runnable=false project_final_file=true>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>aes-crypto-utils</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- JUnit测试框架 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>3.1.0</version><executions><execution><goals><goal>java</goal></goals></execution></executions><configuration><mainClass>com.example.signature.demo.AESDemo</mainClass><javaVersion>11</javaVersion></plugin></plugins></build>
</project>
<code_end>AESCryptoUtils工具类的主要功能和特点:
1. 使用AES-GCM模式提供认证加密,确保数据机密性和完整性
2. 支持AES-256加密强度,符合企业级安全标准
3. 自动生成随机IV,防止重复加密产生相同结果
4. 完整的异常处理和参数验证机制
5. 使用Base64编码便于存储和传输加密数据

package com.example.signature.model;import java.time.LocalDateTime;/*** HMAC密钥对实体类* 用于存储和管理签名密钥*/
public class HmacKeyPair {private String keyId;private String accessKey;private String secretKey;private LocalDateTime createTime;private LocalDateTime expireTime;private boolean enabled;private String description;public HmacKeyPair() {this.createTime = LocalDateTime.now();this.enabled = true;}public HmacKeyPair(String keyId, String accessKey, String secretKey) {this();this.keyId = keyId;this.accessKey = accessKey;this.secretKey = secretKey;}// Getter和Setter方法public String getKeyId() {return keyId;}public void setKeyId(String keyId) {this.keyId = keyId;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getSecretKey() {return secretKey;}public void setSecretKey(String secretKey) {this.secretKey = secretKey;}public LocalDateTime getCreateTime() {return createTime;}public void setCreateTime(LocalDateTime createTime) {this.createTime = createTime;}public LocalDateTime getExpireTime() {return expireTime;}public void setExpireTime(LocalDateTime expireTime) {this.expireTime = expireTime;}public boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}/*** 检查密钥是否过期*/public boolean isExpired() {return expireTime != null && LocalDateTime.now().isAfter(expireTime);}/*** 检查密钥是否有效(未过期且启用)*/public boolean isValid() {return enabled && !isExpired();}@Overridepublic String toString() {return "HmacKeyPair{" +"keyId='" + keyId + '\'' +", accessKey='" + accessKey.substring(0, 8) + "..." + '\'' +", createTime=" + createTime +", expireTime=" + expireTime +", enabled=" + enabled +", description='" + description + '\'' +'}';}
}
<code_end>
<code_start project_name=hmac_key_manager filename=src/main/java/com/example/signature/service/HmacKeyService.java title=HMAC密钥服务类 entrypoint=false runnable=false project_final_file=false>
package com.example.signature.service;import com.example.signature.model.HmacKeyPair;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;
import java.util.UUID;/*** HMAC密钥管理服务*/
@Service
public class HmacKeyService {private final Map<String, HmacKeyPair> keyStore = new HashMap<>();/*** 生成新的密钥对*/public HmacKeyPair generateKeyPair(String description) {String keyId = UUID.randomUUID().toString();String accessKey = generateRandomString(20);String secretKey = generateRandomString(40);HmacKeyPair keyPair = new HmacKeyPair(keyId, accessKey, secretKey);keyPair.setDescription(description);// 默认有效期为1年keyPair.setExpireTime(java.time.LocalDateTime.now().plusYears(1));keyStore.put(keyId, keyPair);return keyPair;}/*** 根据keyId获取密钥对*/public HmacKeyPair getKeyPair(String keyId) {return keyStore.get(keyId);}/*** 禁用密钥对*/public boolean disableKeyPair(String keyId) {HmacKeyPair keyPair = keyStore.get(keyId);if (keyPair != null) {keyPair.setEnabled(false);return true;}return false;}/*** 删除密钥对*/public boolean deleteKeyPair(String keyId) {return keyStore.remove(keyId) != null;}/*** 获取所有有效的密钥对*/public Map<String, HmacKeyPair> getAllValidKeys() {Map<String, HmacKeyPair> validKeys = new HashMap<>();for (Map.Entry<String, HmacKeyPair> entry : keyStore.entrySet()) {if (entry.getValue().isValid()) {validKeys.put(entry.getKey(), entry.getValue());}}return validKeys;}/*** 生成随机字符串*/private String generateRandomString(int length) {String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";StringBuilder sb = new StringBuilder();for (int i = 0; i < length; i++) {int index = (int) (Math.random() * chars.length());sb.append(chars.charAt(index));}return sb.toString();}
}
<code_end>
<code_start project_name=hmac_key_manager filename=pom.xml title=项目依赖配置 entrypoint=false runnable=false project_final_file=true>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>hmac-key-manager</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>5.3.20</spring.version></properties><dependencies><!-- Spring Framework --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- 测试框架 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>3.1.0</version><executions><execution><goals><goal>java</goal></goals></execution></executions><configuration><mainClass>com.example.signature.demo.HmacKeyManagerDemo</mainClass><javaVersion>11</javaVersion></plugin></plugins></build>
</project>
<code_end>HmacKeyPair类的主要功能和特点:
1. 密钥对管理:包含keyId、accessKey、secretKey等核心字段
2. 生命周期控制:支持创建时间、过期时间和启用状态管理
3. 有效性验证:提供密钥过期检查和有效性验证方法
4. 安全设计:使用随机字符串生成器创建高强度的密钥
5. 服务集成:与密钥服务类配合实现完整的密钥管理功能

package com.example.crypto;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;/*** AES加密解密工具类* 支持多种加密模式:GCM、CBC、ECB*/
public class AESCrypto {private static final String ALGORITHM = "AES";private static final int KEY_SIZE = 256;// 加密模式常量public static final String MODE_GCM = "AES/GCM/NoPadding";public static final String MODE_CBC = "AES/CBC/PKCS5Padding";public static final String MODE_ECB = "AES/ECB/PKCS5Padding";// GCM参数private static final int GCM_TAG_LENGTH = 128;private static final int GCM_IV_LENGTH = 12;// CBC参数private static final int CBC_IV_LENGTH = 16;/*** 生成AES密钥*/public static SecretKey generateKey() throws Exception {KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);keyGenerator.init(KEY_SIZE);return keyGenerator.generateKey();}/*** 从Base64字符串恢复密钥*/public static SecretKey restoreKey(String base64Key) {byte[] keyBytes = Base64.getDecoder().decode(base64Key);return new SecretKeySpec(keyBytes, ALGORITHM);}/*** AES加密 - GCM模式(推荐)*/public static String aesEncryptGCM(String plaintext, SecretKey key) throws Exception {byte[] iv = new byte[GCM_IV_LENGTH];new SecureRandom().nextBytes(iv);Cipher cipher = Cipher.getInstance(MODE_GCM);GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.ENCRYPT_MODE, key, spec);byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));// 组合IV和密文byte[] encrypted = new byte[iv.length + ciphertext.length];System.arraycopy(iv, 0, encrypted, 0, iv.length);System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length);return Base64.getEncoder().encodeToString(encrypted);}/*** AES解密 - GCM模式*/public static String aesDecryptGCM(String encryptedText, SecretKey key) throws Exception {byte[] decoded = Base64.getDecoder().decode(encryptedText);// 分离IV和密文byte[] iv = new byte[GCM_IV_LENGTH];byte[] ciphertext = new byte[decoded.length - GCM_IV_LENGTH];System.arraycopy(decoded, 0, iv, 0, iv.length);System.arraycopy(decoded, iv.length, ciphertext, 0, ciphertext.length);Cipher cipher = Cipher.getInstance(MODE_GCM);GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.DECRYPT_MODE, key, spec);byte[] plaintext = cipher.doFinal(ciphertext);return new String(plaintext, StandardCharsets.UTF_8);}/*** AES加密 - CBC模式*/public static String aesEncryptCBC(String plaintext, SecretKey key) throws Exception {byte[] iv = new byte[CBC_IV_LENGTH];new SecureRandom().nextBytes(iv);Cipher cipher = Cipher.getInstance(MODE_CBC);IvParameterSpec spec = new IvParameterSpec(iv);cipher.init(Cipher.ENCRYPT_MODE, key, spec);byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));// 组合IV和密文byte[] encrypted = new byte[iv.length + ciphertext.length];System.arraycopy(iv, 0, encrypted, 0, iv.length);System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length);return Base64.getEncoder().encodeToString(encrypted);}/*** AES解密 - CBC模式*/public static String aesDecryptCBC(String encryptedText, SecretKey key) throws Exception {byte[] decoded = Base64.getDecoder().decode(encryptedText);// 分离IV和密文byte[] iv = new byte[CBC_IV_LENGTH];byte[] ciphertext = new byte[decoded.length - CBC_IV_LENGTH];System.arraycopy(decoded, 0, iv, 0, iv.length);System.arraycopy(decoded, iv.length, ciphertext, 0, ciphertext.length);Cipher cipher = Cipher.getInstance(MODE_CBC);IvParameterSpec spec = new IvParameterSpec(iv);cipher.init(Cipher.DECRYPT_MODE, key, spec);byte[] plaintext = cipher.doFinal(ciphertext);return new String(plaintext, StandardCharsets.UTF_8);}/*** 通用AES加密方法*/public static String aesEncrypt(String plaintext, String base64Key, String mode) throws Exception {SecretKey key = restoreKey(base64Key);switch (mode.toUpperCase()) {case "GCM":return aesEncryptGCM(plaintext, key);case "CBC":return aesEncryptCBC(plaintext, key);default:throw new IllegalArgumentException("不支持的加密模式: " + mode);}}/*** 通用AES解密方法*/public static String aesDecrypt(String encryptedText, String base64Key, String mode) throws Exception {SecretKey key = restoreKey(base64Key);switch (mode.toUpperCase()) {case "GCM":return aesDecryptGCM(encryptedText, key);case "CBC":return aesDecryptCBC(encryptedText, key);default:throw new IllegalArgumentException("不支持的加密模式: " + mode);}}/*** 验证加密数据格式*/public static boolean isValidEncryptedData(String encryptedText, String mode) {try {byte[] decoded = Base64.getDecoder().decode(encryptedText);switch (mode.toUpperCase()) {case "GCM":return decoded.length >= GCM_IV_LENGTH;case "CBC":return decoded.length >= CBC_IV_LENGTH;default:return false;}} catch (Exception e) {return false;}}
}
<code_end>
<code_start project_name=java_aes_crypto filename=src/main/java/com/example/crypto/AESKeyManager.java title=AES密钥管理器 entrypoint=false runnable=false project_final_file=false>
package com.example.crypto;import javax.crypto.SecretKey;
import java.util.HashMap;
import java.util.Map;/*** AES密钥管理器* 提供密钥的生成、存储和管理功能*/
public class AESKeyManager {private static final Map<String, SecretKey> keyStore = new HashMap<>();/*** 生成并存储新密钥*/public static String generateAndStoreKey(String keyId) throws Exception {SecretKey key = AESCrypto.generateKey();String base64Key = Base64.getEncoder().encodeToString(key.getEncoded());keyStore.put(keyId, key);return base64Key;}/*** 根据keyId获取密钥*/public static SecretKey getKey(String keyId) {return keyStore.get(keyId);}/*** 删除密钥*/public static boolean removeKey(String keyId) {return keyStore.remove(keyId) != null;}/*** 导出所有密钥*/public static Map<String, String> exportAllKeys() {Map<String, String> exportedKeys = new HashMap<>();for (Map.Entry<String, SecretKey> entry : keyStore.entrySet()) {String base64Key = Base64.getEncoder().encodeToString(entry.getValue().getEncoded());exportedKeys.put(entry.getKey(), base64Key);}return exportedKeys;}/*** 导入密钥*/public static void importKey(String keyId, String base64Key) {SecretKey key = AESCrypto.restoreKey(base64Key);keyStore.put(keyId, key);}
}
<code_end>
<code_start project_name=java_aes_crypto filename=src/main/java/com/example/demo/AESDemo.java title=AES加密解密演示 entrypoint=true runnable=true project_final_file=false>
package com.example.demo;import com.example.crypto.AESCrypto;
import com.example.crypto.AESKeyManager;import javax.crypto.SecretKey;
import java.util.Base64;/*** AES加密解密演示类*/
public class AESDemo {public static void main(String[] args) {try {System.out.println("=== AES加密解密演示 ===\n");// 1. 生成密钥System.out.println("1. 生成AES-256密钥...");SecretKey key = AESCrypto.generateKey();String base64Key = Base64.getEncoder().encodeToString(key.getEncoded());System.out.println("密钥(Base64): " + base64Key);System.out.println();// 2. GCM模式加密解密System.out.println("2. GCM模式加密解密测试...");String originalText = "这是一个需要加密的敏感数据,包含中文和English混合内容!");System.out.println("原始文本: " + originalText);String encryptedGCM = AESCrypto.aesEncryptGCM(originalText, key);System.out.println("GCM加密结果: " + encryptedGCM);String decryptedGCM = AESCrypto.aesDecryptGCM(encryptedGCM, key);System.out.println("GCM解密结果: " + decryptedGCM);System.out.println("GCM加解密验证: " + originalText.equals(decryptedGCM));System.out.println();// 3. CBC模式加密解密System.out.println("3. CBC模式加密解密测试...");String encryptedCBC = AESCrypto.aesEncryptCBC(originalText, key);System.out.println("CBC加密结果: " + encryptedCBC);String decryptedCBC = AESCrypto.aesDecryptCBC(encryptedCBC, key);System.out.println("CBC解密结果: " + decryptedCBC);System.out.println("CBC加解密验证: " + originalText.equals(decryptedCBC));System.out.println();// 4. 密钥管理演示System.out.println("4. 密钥管理功能演示...");String testKeyId = "test_key_001";String storedKey = AESKeyManager.generateAndStoreKey(testKeyId);System.out.println("存储的密钥: " + storedKey);// 5. 验证加密数据格式System.out.println("5. 验证加密数据格式...");System.out.println("GCM加密数据格式有效: " + AESCrypto.isValidEncryptedData(encryptedGCM, "GCM"));System.out.println("CBC加密数据格式有效: " + AESCrypto.isValidEncryptedData(encryptedCBC, "CBC"));System.out.println();System.out.println("=== 演示完成 ===");} catch (Exception e) {e.printStackTrace();}}
}
<code_end>
<code_start project_name=java_aes_crypto filename=pom.xml title=Maven项目配置 entrypoint=false runnable=false project_final_file=true>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>aes-crypto</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- 测试框架 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>3.1.0</version><executions><execution><goals><goal>java</goal></goals></execution></executions><configuration><mainClass>com.example.demo.AESDemo</mainClass><javaVersion>11</javaVersion></configuration></plugin></plugins></build>
</project>
<code_end>代码说明:
1. **完整AES加密解密实现**:提供GCM和CBC两种主流加密模式,支持AES-256加密强度
2. **密钥管理功能**:包含密钥生成、存储、导入导出等完整生命周期管理
3. **安全设计**:使用随机IV防止重复加密,GCM模式提供认证加密确保数据完整性
4. **模块化架构**:分离加密核心逻辑与密钥管理,便于维护和扩展
5. **演示程序**:包含完整的测试用例,可直接运行验证功能主要特性包括GCM模式的认证加密、CBC模式的兼容性加密、密钥的安全存储和管理,以及完整的数据验证机制。

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

相关文章:

  • 腾讯云服务器搭建网站漯河网站建设费用
  • docker部署开源监控软件hertzbeat
  • 上海网站网站建设工程公司简介范文大全
  • STM32CubeMx学习hal库
  • 在线确定性算法与自适应启发式在虚拟机动态整合中的竞争分析与性能优化
  • 企业网站建设费多少钱硬盘做免费嗳暧视频网站
  • 做图在哪个网站上找南京自助建站模板
  • 山东市网站建设中国林业网站群建设工程
  • 大白话浅析Windows 安全核心机制
  • 【OpenCV + VS】OpenCV 随机数绘图:如何在图像中绘制随机线条
  • 个人网站可以做商城吗泰安人才信息网官网
  • 网站开发提供图片加载速度建设工程施工合同示范文本2021
  • sward实战教程系列(2) - 创建第一个知识库
  • iOS 内存管理之 autoreleasePool
  • 北京沙河教做网站的山东省济南市莱芜区
  • 长沙建长沙建网站公司给wordpress程序提速
  • 多国语言编译库 | 适用于全球化开发的高效工具
  • C语言编译系统 | 如何高效构建和使用C语言编译系统
  • 手机建设银行网站首页网站开发app开发主营业务
  • 11月12日星期三今日早报简报微语报早读
  • 360水滴摄像头重新设置摄像头wifi
  • Notepad++ 编译 C 语言的使用方法与技巧
  • 编译C语言的软件 | 轻松高效的C语言编译工具介绍
  • 企业网站设计特点建设银行网站怎么打印明细
  • C语言练习题——判断水仙花数(0-100000)
  • 广州好的网站建设昆明微网站搭建哪家好
  • 找国内外贸公司的网站深圳自己做网站
  • 视频融合平台EasyCVR:云台控制与语音对讲赋能远程交互式视频监控新场景
  • 做设计私活的网站php网站建设费用
  • next.js(二)——从react到next.js