國密SM4/SM3
SM4:對稱加密算法,分組長度128位,密鑰長度128位,適用于數據加密(如數據庫字段、通信報文)】
加密存儲:用戶身份證號、銀行卡號等敏感字段(配合ShardingSphere等中間件自動加解密)
通信安全:API傳輸敏感數據時加密報文Body。
//加密銀行卡號(SpringBoot+BouncyCastle Provider)
public class SM4Util{public static String encrypt(String plaintext,String key)throws Exception{Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding","BC");/**private static final String ALGORITHM_NAME = "SM4";private static final String HSM_PROVIDER = "SunPKCS11-HSM";*///KeyStore keyStore = KeyStore.getInstance("PKCS11", HSM_PROVIDER);//SecretKey keySpec = (SecretKey) keyStore.getKey("sm4_key", null);SecretKeySpec keySpec = new SecretKeySpec(key,getBytes(),"SM4");cipher.init(Cipher.ENCRYPT_MODE, keySpec);byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(encrypted);}
}
#基于ShardingSphere的加密配置(YAML)
spring:shardingsphere:datasource:encrypt:encryptors:sm4_encryptor:type: SM4props:sm4.key: ${secure.key} # 密鑰從HSM獲取tables:t_user:columns:id_card:cipherColumn: id_card_cipherencryptorName: sm4_encryptorphone:cipherColumn: phone_cipherencryptorName: sm4_encryptor
SM3:哈希算法,輸出256位摘要,用于數據完整性校驗(如交易簽名、文件防篡改)
交易簽名:將交易流水號、金額、時間戳拼接后哈希,作為防篡改簽名
文件校驗:下載對賬文件時驗證SM3哈希值是否匹配
// 生成交易簽名(防止篡改)
public class SM3Util {public static String hash(String data) throws Exception {MessageDigest md = MessageDigest.getInstance("SM3", "BC");byte[] digest = md.digest(data.getBytes(StandardCharsets.UTF_8));return Hex.toHexString(digest);}
}
符合《中華人民共和國密碼法》及金融行業安全標準。
等保三級要求核心敏感數據必須使用國密算法或AES-256。
硬件加密機
HSM:專用硬件設備,用于安全生成/存儲密鑰、執行加密運算,提供物理級防護(如防拆機自毀)
常見廠商:Thales Luna HSMs、IBM Crypto Express、阿里云加密服務
密鑰管理
- 根密鑰(Master Key)永不離開HSM,應用僅獲取加密后的臨時密鑰
- 執行SM4/SM3運算時,由HSM硬件加速(提升10倍以上性能)
# 通過PKCS#11標準接口調用HSM(示例命令)
pkcs11-tool --module /usr/lib/libCryptoki2.so --login --pin 123456 \--generate-random 32 --output-file random.key
數字證書
- 簽發金融級數字證書(如網銀U盾)
- 區塊鏈交易簽名(避免私鑰泄漏風險)
// 從HSM獲取證書簽名(Java)
KeyStore keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-HSM");
keyStore.load(null, "hsm-password".toCharArray());
PrivateKey privateKey = (PrivateKey) keyStore.getKey("signing-key", null);
Signature signature = Signature.getInstance("SM3withSM2", "BC");
signature.initSign(privateKey);
signature.update(data.getBytes());
byte[] signed = signature.sign();
PCI DSS要求:信用卡相關密鑰必須存儲在HSM中
銀聯標準:跨境支付系統必須使用HSM保護密鑰
動態密鑰管理
動態密鑰:每次會話或交易生成臨時密鑰,通過密鑰派生函數(KDF)從主密鑰派生,有效期內自動失效
關鍵技術:密鑰輪換、前向保密(PFS)、密鑰分發協議(如KMIP)
支付交易動態密鑰
每筆支付交易使用唯一密鑰加密卡號,即使某次密鑰泄漏也不影響其他交易
# 使用HMAC-SM3派生會話密鑰(Python示例)
import hmac, hashlib
def derive_key(master_key, transaction_id):derived_key = hmac.new(master_key, transaction_id.encode(), hashlib.sm3).digest()return derived_key[:16] # 取前128位作為SM4密鑰
數據庫列級加密
定期輪換密鑰(如每月更換),舊數據通過密鑰ID解密后重新加密
-- 動態密鑰管理方案(配合KMS)
CREATE TABLE users (id BIGINT,phone_cipher TEXT, -- 使用動態密鑰加密key_id VARCHAR(64) -- 記錄當前使用的密鑰版本
);
從HSM獲取密鑰
public class HsmKeyLoader{@PostConstructpublic void init(){String sm4Key = hsmClient.getKey("sm4_enc_key");// 通過HSM API獲取System.setProperty("shardingsphere.encrypt.encryptors.sm4_encryptor.props.sm4.key", sm4Key);}
}
巴塞爾協議:要求密鑰生命周期管理(生成、分發、輪換、銷毀)
GDPR:密鑰輪換周期不得超過90天
ShardingSphere加密
寫入流程:
應用明文 → ShardingSphere攔截 → 加密字段替換為密文 → 數據庫存儲
查詢流程:
應用查詢條件 → ShardingSphere攔截 → 加密字段條件加密 → 數據庫查詢 → 返回結果解密 → 明文返回應用
一、依賴
<!-- ShardingSphere JDBC + 加密模塊 -->
<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.3.2</version>
</dependency>
二、配置加密規則
spring:shardingsphere:datasource:names: dsds:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.jdbc.Driverjdbc-url: jdbc:mysql://localhost:3306/finance_dbusername: rootpassword: 123456rules:encrypt:encryptors:sm4_encryptor: # 定義SM4加密器type: SM4props:sm4.key: 1234567890abcdef1234567890abcdef # 256-bit密鑰(需從HSM獲取)aes_encryptor: # 定義AES加密器(備用)type: AESprops:aes.key.value: 1234567890abcdeftables:t_user: # 用戶表加密配置columns:id_card: # 身份證字段cipherColumn: id_card_cipher # 密文存儲列encryptorName: sm4_encryptorphone: # 手機號字段cipherColumn: phone_cipherplainColumn: phone_plain # 保留明文列(可選,用于模糊查詢)encryptorName: aes_encryptor
三、數據庫表設計
CREATE TABLE t_user (id BIGINT PRIMARY KEY,name VARCHAR(100),id_card_cipher VARCHAR(200), -- SM4加密后的密文phone_cipher VARCHAR(200), -- AES加密后的密文phone_plain VARCHAR(20) -- 明文(如需模糊查詢)
);
四、業務代碼
// 插入數據(無需手動加密)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {@Query("INSERT INTO t_user (name, id_card, phone) VALUES (:name, :idCard, :phone)")void saveUser(@Param("name") String name, @Param("idCard") String idCard, // 自動加密@Param("phone") String phone);
}// 查詢數據(自動解密)
public User getUserById(Long id) {return userRepository.findById(id).orElse(null); // 返回的idCard/phone已是明文
}
審計日志脫敏
// 使用ShardingSphere的SQL解析器攔截日志
@Bean
public ShardingSphereDataSource dataSource() throws SQLException {Properties props = new Properties();props.setProperty("sql.show", "true"); // 顯示SQL日志(自動脫敏)return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(encryptRule), props);
}