前言:
之前我们介绍了一些常用的加密算法(如:对称加密AES,非对称加密RSA,ECC等),不论是哪一种都需要涉及到秘钥的管理。通常的做法都是把秘钥放到配置文件中进行配置,但是对于一些高度需要安全保证的场景来说,这样并不是安全的,容易造成秘钥泄漏,进而造成数据被破解。所以这个时候我们就需要借助一些相对安全的机制去管理秘钥,例如:亚马逊的AWS KMS,或Azure Key Vault等。本篇介绍下AWS KMS。
1、为什么不能简单将密钥放在系统配置中?
(1)、明文存储风险
- 系统配置文件(如
.env
、config.properties
)通常以明文形式存储密钥,一旦被非法访问(如代码泄露、服务器入侵),密钥将直接暴露,导致数据被窃取或篡改。
(2)、缺乏生命周期管理
- 系统配置中的密钥通常静态不变,无法自动更新或销毁,长期使用会增加被破解的风险(如穷举攻击)。
(3)、权限控制不足
- 配置文件的访问权限可能未严格限制,导致非授权人员或系统可直接读取密钥。
(4)、无法应对复杂场景
- 多环境(开发/测试/生产)、多服务(如微服务架构)的密钥分发和管理会变得混乱,难以追踪和审计。
2、密钥管理的核心好处
(1)、提升安全性
-
安全存储:
密钥存储在硬件安全模块(HSM)或加密的密钥管理系统(如Azure Key Vault、AWS KMS),而非明文文件中。 -
防止泄露:
通过访问控制(如RBAC)、最小权限原则和审计日志,确保只有授权方能访问密钥。 -
抵御攻击:
密钥轮换(定期更换密钥)和分层保护(如主密钥保护会话密钥)降低泄露风险。
(2)、符合合规要求
- 行业标准:
密钥管理需符合GDPR、PCI DSS等法规,直接存放配置文件可能违反合规性要求。
(3)、简化运维与自动化
-
集中化管理:
通过密钥管理系统(如HashiCorp Vault、AWS KMS)统一管理所有密钥,支持多环境和多服务。 -
自动化生命周期:
自动轮换密钥、设置有效期、销毁旧密钥,减少人为操作错误。
(4)、支持复杂场景
-
动态分发:
通过安全协议(如TLS)分发密钥,支持云原生、微服务等分布式架构。 -
审计与追溯:
记录密钥的使用、访问和变更日志,便于追踪异常行为。
(5)、降低业务风险
- 避免数据泄露损失:
密钥泄露可能导致数据泄露,进而引发法律纠纷和经济损失(如平均泄露成本达488万美元)。
3、密钥管理 vs 直接存放配置的对比
4、AWS KMS简介
AWS KMS(Key Management Service,密钥管理服务)是亚马逊云(AWS)提供的一项全托管服务,用于简化加密密钥的创建、存储和管理,帮助用户轻松实现数据的加密保护。
-
密钥管理
- 密钥类型:支持对称密钥(AES-256)和非对称密钥(RSA/ECC)。
- 生命周期管理:创建、启用/禁用、轮换(自动或手动)、删除密钥。
-
密钥分类:
- 客户主密钥(CMK):用户自定义密钥,完全控制权限和策略。
- AWS托管密钥:AWS自动生成并管理的密钥(如S3默认加密密钥)。
-
加密服务
- 集成加密:与AWS服务(S3、RDS、EBS等)无缝集成,自动加密存储的数据。
- API调用:通过AWS SDK直接调用加密/解密接口,保护应用程序数据。
-
安全性
- 硬件安全模块(HSM):密钥存储在通过FIPS 140-2/3认证的HSM中,确保物理隔离。
- 访问控制:通过IAM策略和密钥策略,精细化控制“谁能在什么条件下使用密钥”。
5、亚马逊云平台基本配置
(1)、创建 AWS 账户
- 如果还没有 AWS 账户,请前往 AWS 官网 注册一个账户。
(2)、创建 KMS 密钥
- 登录 AWS 管理控制台。
- 在服务列表中搜索并选择 KMS (Key Management Service)。
- 单击 Create key 按钮。
- 选择密钥类型(如对称密钥或非对称密钥),然后按照向导完成密钥的创建。
- 记下密钥的 ARN(Amazon Resource Name),例如:
arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd5678
(4)、配置 IAM 权限
- 创建一个 IAM 用户或角色,并赋予其访问 KMS 的权限。
- 在 IAM 控制台中,为用户或角色附加以下策略:
json示例:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234abcd5678"
}
]
}
(4)、获取访问凭证
- 在 IAM 控制台中,获取该用户的访问密钥(Access Key ID 和 Secret Access Key)。
- 将这些凭证存储到本地环境变量中,或者使用 AWS CLI 配置凭证。
6、Spring Boot 项目代码示例
(1)、添加依赖
在 pom.xml 中添加 Spring Cloud AWS KMS 依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-autoconfigure</artifactId>
<version>2.4.0</version> <!-- 确保版本与 Spring Boot 兼容 -->
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.4.0</version>
</dependency>
(2)、配置 application.properties
在项目 src/main/resources 目录下配置 AWS 凭据和 KMS 参数:
properties示例:
# AWS 全局配置
cloud.aws.credentials.access-key=YOUR_ACCESS_KEY_ID
cloud.aws.credentials.secret-key=YOUR_SECRET_ACCESS_KEY
cloud.aws.region.static=us-east-1
# KMS 配置
cloud.aws.kms.key-id=arn:aws:kms:us-east-1:123456789012:key/abcd1234-a123-4567-8abc-def123456789
(3)、建 KMS 服务类
创建一个服务类 KmsService,使用 Spring Cloud AWS 提供的 KmsTemplate 进行加密和解密:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.aws.kms.AWSKmsMessageCrypto;
import org.springframework.cloud.aws.kms.AWSKmsMessageCryptoFactory;
import org.springframework.stereotype.Service;
@Service
public class KmsService {
private final AWSKmsMessageCrypto crypto;
public KmsService(AWSKmsMessageCryptoFactory cryptoFactory) {
this.crypto = cryptoFactory.createCrypto();
}
// 加密方法
public String encrypt(String plaintext) {
try {
byte[] encrypted = crypto.encrypt(plaintext.getBytes());
return new String(encrypted);
} catch (Exception e) {
throw new RuntimeException("加密失败", e);
}
}
// 解密方法
public String decrypt(String ciphertext) {
try {
byte[] decrypted = crypto.decrypt(ciphertext.getBytes());
return new String(decrypted);
} catch (Exception e) {
throw new RuntimeException("解密失败", e);
}
}
}
(4)、创建 REST 控制器
创建一个控制器 KmsController,提供加密和解密的 REST 接口:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/kms")
public class KmsController {
@Autowired
private KmsService kmsService;
@PostMapping("/encrypt")
public String encrypt(@RequestParam String text) {
return kmsService.encrypt(text);
}
@PostMapping("/decrypt")
public String decrypt(@RequestParam String ciphertext) {
return kmsService.decrypt(ciphertext);
}
}
逆风翻盘,Dare To Be!!!