todo/密钥加密方案.txt
2025-06-13 15:52:23 +08:00

230 lines
7.3 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Java实现多用户加密待办和日志系统方案
## 系统架构设计
### 1. 核心组件
- **用户认证模块**:处理用户注册/登录
- **密钥管理模块**:生成和管理用户加密密钥
- **数据加密模块**:处理文本的加密/解密
- **数据存储模块**:存储加密后的数据
### 2. 数据库设计
```sql
-- 用户表
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
salt VARCHAR(255) NOT NULL
);
-- 用户密钥表
CREATE TABLE user_keys (
user_id BIGINT PRIMARY KEY,
encrypted_key TEXT NOT NULL, -- 用主密码加密的密钥
key_iv VARCHAR(255) NOT NULL, -- 初始化向量
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 待办表
CREATE TABLE todos (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
encrypted_content TEXT NOT NULL,
iv VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 日志表
CREATE TABLE logs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
encrypted_content TEXT NOT NULL,
iv VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
```
## 关键实现代码
### 1. 加密服务类
```java
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.KeySpec;
import java.util.Base64;
public class EncryptionService {
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String SECRET_KEY_ALGORITHM = "PBKDF2WithHmacSHA256";
private static final int ITERATIONS = 65536;
private static final int KEY_LENGTH = 256;
// 生成随机密钥
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
return keyGenerator.generateKey();
}
// 从密码派生密钥
public static SecretKey getKeyFromPassword(String password, String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM);
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), ITERATIONS, KEY_LENGTH);
return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
}
// 生成随机IV
public static IvParameterSpec generateIv() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
// 加密文本
public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] cipherText = cipher.doFinal(input.getBytes());
return Base64.getEncoder().encodeToString(cipherText);
}
// 解密文本
public static String decrypt(String algorithm, String cipherText, SecretKey key, IvParameterSpec iv)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(plainText);
}
}
```
### 2. 用户服务类
```java
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.SecretKey;
public class UserService {
// 用户注册
public void registerUser(String username, String password) {
// 生成密码盐
String salt = generateSalt();
// 存储用户信息
storeUser(username, hashPassword(password, salt), salt);
// 为用户生成加密密钥
SecretKey userKey = EncryptionService.generateKey();
// 使用主密码加密用户密钥
String encryptedKey = encryptUserKey(userKey, password, salt);
// 存储加密后的用户密钥
storeUserKey(userId, encryptedKey);
}
// 用户登录并获取解密密钥
public SecretKey loginAndGetKey(String username, String password) {
// 验证用户凭据
if (!authenticateUser(username, password)) {
throw new SecurityException("Invalid credentials");
}
// 获取加密的用户密钥
String encryptedKey = getEncryptedUserKey(username);
String salt = getUserSalt(username);
// 使用主密码解密用户密钥
return decryptUserKey(encryptedKey, password, salt);
}
// 其他辅助方法...
}
```
### 3. 数据服务类
```java
public class TodoService {
private final EncryptionService encryptionService;
// 添加加密的待办事项
public void addEncryptedTodo(Long userId, String content, SecretKey userKey) {
IvParameterSpec iv = EncryptionService.generateIv();
String encryptedContent = encryptionService.encrypt(
EncryptionService.ALGORITHM,
content,
userKey,
iv
);
// 存储加密内容和IV
storeTodo(userId, encryptedContent, iv.getIV());
}
// 获取并解密的待办事项
public String getDecryptedTodo(Long todoId, SecretKey userKey) {
// 从数据库获取加密数据和IV
EncryptedTodo todo = getEncryptedTodo(todoId);
IvParameterSpec iv = new IvParameterSpec(todo.getIv());
return encryptionService.decrypt(
EncryptionService.ALGORITHM,
todo.getEncryptedContent(),
userKey,
iv
);
}
// 其他方法...
}
```
## 安全实践建议
1. **密钥管理**
- 每个用户拥有唯一的加密密钥
- 用户密钥使用主密码加密存储
- 主密码应使用强哈希算法存储(如Argon2, PBKDF2)
2. **加密操作**
- 每次加密使用不同的IV(初始化向量)
- 使用认证加密模式如AES-GCM(而不是示例中的AES-CBC)
- 考虑添加完整性校验
3. **传输安全**
- 所有通信使用HTTPS
- 敏感操作需要重新验证密码
4. **密钥生命周期**
- 提供密钥轮换机制
- 实现密码重置时的密钥重新加密流程
## 扩展考虑
1. **客户端加密**
- 可以在浏览器中使用Web Crypto API先加密数据再发送到服务器
- 实现"零知识"架构,服务器无法访问明文数据
2. **多设备支持**
- 实现密钥同步机制
- 使用密钥封装机制保护传输中的密钥
3. **审计日志**
- 记录关键操作(不记录敏感数据)
- 实现不可否认性机制
需要更详细的任何部分(如特定算法的实现、密钥轮换流程等)吗?