AES实现财务数据的加密解密存储
- 需求背景
众所周知,金融行业有各种各样的财务报表,有些报表涉及到公司财务或经营相关的敏感数据,需要进行加密存储,只有掌握密钥的用户才能看到解密后的数据。注意,这里所说的加密并不是针对整个数据库或者表全局加密,而是针对表的某些字段进行加密。
- 实现思路
1、针对某一张报表创建相对应的一张落地表,相关需要加密的字段统一定义为VARCHAR2(1000)。
2、实现Hibernate监听器接口,在实体保存之前进行加密,数据Load出来之后进行解密,这样可以实现加密解密逻辑的统一处理。
3、对是否需要加密的实体和字段标注对应的注解,将加密解密的实现逻辑转化为对注解的解析处理。
4、统一采用AES加密解密算法,放在工具类中实现,加密解密流程(原图摘自:https://blog.csdn.net/gulang03/article/details/81175854)如下:

5、其他需要处理的场景
a、数据的保存和查询采用的是JDBC的处理方式,需要在SQL中统一处理(建议用JdbcTemplate底层统一封装下),mysql有内置函数,oracle需要自定义函数实现
b、数据修改时也需要考虑加密的场景
c、oracle正常情况,用户不能访问sys.dbms_crypto,需要DBA授权
- 核心代码
1、注册监听器事件
public class HibernateEvent {
@Autowired
private SessionFactory sessionFactory;
@Autowired
private AesListener aesListener;
@PostConstruct
public void registerListeners() {
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(aesListener);
registry.getEventListenerGroup(EventType.POST_LOAD).appendListener(aesListener);
}
}
2、监听器实现
@Component
public class AesListener implements PreInsertEventListener, PostLoadEventListener {
@Override
public boolean onPreInsert(PreInsertEvent event) { Class clazz = event.getPersister().getMappedClass(); String[] propertyNames = event.getPersister().getPropertyNames(); EnableEncrypted enableEncrypted = (EnableEncrypted)clazz.getAnnotation(EnableEncrypted.class); if(enableEncrypted != null){
Field[] fields = clazz.getDeclaredFields();
if(fields != null){
for(Field field : fields){
boolean isAccessible = field.isAccessible();
if(!isAccessible){
field.setAccessible(true);
}
Encrypted encrypted = field.getAnnotation(Encrypted.class);
if(encrypted != null){
try {
Object value = field.get(event.getEntity()); Class<?> type = field.getType();
String enStr = null;
if(type == String.class){
enStr = AesUtils.aesEncrypt(value.toString());
}else if(type == Double.class){
Double val = (Double)value;
enStr = AesUtils.aesDecrypt(String.valueOf(val));
} if(enStr != null){
field.set(event.getEntity(), enStr);
field.setAccessible(isAccessible); for(int i = 0; i < propertyNames.length; i++){
if(field.getName().equals(propertyNames[i])){
event.getState()[i] = enStr;
break;
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
return false;
}
}
3、加密解密工具类
public class AesUtils {
public static String selectSql(String columnName){
if(StringUtils.isNotEmpty(columnName)){
String alias = columnName.contains(".")?columnName.substring(columnName.lastIndexOf(".")+1):columnName;
return whereSql(columnName) + " AS "+alias;
}
return null;
}
public static String whereSql(String columnName){
if(StringUtils.isNotEmpty(columnName)){
return "CAST(AES_DECRYPT(UNHEX("+columnName+"), '"+ AesConstants.AES_KEY +"') AS CHAR)";
}
return null;
}
public static String writeSql(String columnValue){
if(StringUtils.isNotEmpty(columnValue)){
return "HEX(AES_ENCRYPT('"+columnValue+"', '"+AesConstants.AES_KEY+"'))";
}
return null;
}
private static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
private static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
for (int i = 0;i< hexStr.length()/2; i++) {
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static String aesEncrypt(String content) {
try {
SecretKey key = generateMySQLAESKey("ASCII");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cleartext = content.getBytes("UTF-8");
byte[] ciphertextBytes = cipher.doFinal(cleartext);
return new String(Hex.encodeHex(ciphertextBytes));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static String aesDecrypt(String content){
try {
SecretKey key = generateMySQLAESKey("ASCII");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] cleartext = new byte[0];
try {
cleartext = Hex.decodeHex(content.toCharArray());
} catch (DecoderException e) {
log.error("非法的16进制字符串:" + content, e);
}
byte[] ciphertextBytes = cipher.doFinal(cleartext);
return new String(ciphertextBytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static SecretKeySpec generateMySQLAESKey(final String encoding) {
try {
final byte[] finalKey = new byte[16];
int i = 0;
for(byte b : AesConstants.AES_KEY.getBytes(encoding))
finalKey[i++%16] ^= b;
return new SecretKeySpec(finalKey, "AES");
} catch(UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
AES实现财务数据的加密解密存储的更多相关文章
- php中签名公钥、私钥(SHA1withRSA签名)以及AES(AES/ECB/PKCS5Padding)加密解密详解
由于http请求是无状态,所以我们不知道请求方到底是谁.于是就诞生了签名,接收方和请求方协商一种签名方式进行验证,来取得互相信任,进行下一步业务逻辑交流. 其中签名用得很多的就是公钥私钥,用私钥签名, ...
- 通过Jni实现AES的CBC模式加密解密
AES加密方式基本实现,出现一个问题就是代码的安全性.我们知道java层代码很容易被反编译,很有可能泄漏我们加密方式与密钥 内容,那我们该怎么办呢?我们可以使用c/c++实现加密,编译成So库的形式, ...
- JAVA和PYTHON同时实现AES的加密解密操作---且生成的BASE62编码一致
终于有机会生产JAVA的东东了. 有点兴奋. 花了一天搞完.. java(关键key及算法有缩减): package com.security; import javax.crypto.Cipher; ...
- php实现AES/CBC/PKCS5Padding加密解密(又叫:对称加密)
今天在做一个和java程序接口的架接,java那边需要我这边(PHP)对传过去的值进行AES对称加密,接口返回的结果也是加密过的(就要用到解密),然后试了很多办法,也一一对应了AES的key密钥值,偏 ...
- python中常用的base64 md5 aes des crc32等的加密解密
1.base64 Python内置的base64模块可以实现base64.base32.base16.base85.urlsafe_base64的编码解码,python 3.x通常输入输出都是二进制形 ...
- AES加密解密的例子小结
话不多说,先放上代码,一共有两个文件:AES.php(aes算法类文件)和aesDemo.php(应用实例文件),这里只贴出aesDemo.php,其他的看附件吧!aesDemo.php: 例子, ...
- DES加密解密与AES加密解密
随着开发时间的变长,当初认为比较难的东西,现在渐渐也就变的不那么难了!特别对于一些经常很少使用的类,时间长了之后渐渐就陌生了.所以在这里写一些日后可能会用到的加密与解密. 一.AES加密算法和DES加 ...
- Java 关于密码处理的工具类[MD5编码][AES加密/解密]
项目中又遇到了加密问题,又去翻了半天,然后做测试,干脆就把常用的两类小结一下. 1.第一种所谓的MD5加密 其实也不算加密,只是基于Hash算法的不可逆编码而已,等于说,一旦经过MD5处理,是不可能从 ...
- 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目 .net 笔试面试总结(3) .net 笔试面试总结(2) 依赖注入 C# RSA 加密 C#与Java AES 加密解密
你真的了解字典(Dictionary)吗? 从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...
随机推荐
- nginx代理vue项目
很多项目的前端都使用vue编写的,在项目上线部署的时候,有些项目要求把前端页面和后台服务部署在不同的服务器,这就要求使用nginx代理,本文就来讲讲vue项目怎么使用nginx代理. 项目github ...
- Halloween Costumes 玄学题
传送门 太难了,完全不懂 设\(dp[i][j]\)为第i天到第j天的最少代价 \(dp[i][j]=dp[i][j-1]+1\)(第j天多穿一件衣服) \(dp[i][j]=min(dp[i][j] ...
- C. Journey bfs 拓扑排序+dp
C. Journey 补今天早训 这个是一个dp,开始我以为是一个图论,然后就写了一个dij和网络流,然后mle了,不过我觉得如果空间开的足够的,应该也是可以过的. 然后看了题解说是一个dp,这个dp ...
- django 整理数据库文档时,从mysql导出的表中没有注释的解决方案
公司要将Django项目重构成Java项目,也就有了整理数据库文档的经历....... 由于django从model迁移时没有将注释(也就是模型类中的verbose_name)写进mysql的表中,导 ...
- php报错:strip_tags() expects parameter 1 to be string, array given
囧....... 这个表示参数需要字符串,而你传入了数组,所以出错了~ 检查下函数或者方法是否正确,还有参数
- spring boot中使用AJAX请求,并将回调函数赋值给input输入框
HTML: <script>/* $(document).ready(function(){} 页面加载事件,加载完页面之后执行 */ $(document).ready(function ...
- Mybatis使用ResultMap
解决字段名和属性名不一致的问题 - 新建数据库表的字段-这里就不贴上了 在下面链接有 https://www.cnblogs.com/rzkwz/p/12853899.html 设置实体类和数据库字段 ...
- 【Hadoop离线基础总结】工作流调度器azkaban
目录 Azkaban概述 工作流调度系统的作用 工作流调度系统的实现 常见工作流调度工具对比 Azkaban简单介绍 安装部署 Azkaban的编译 azkaban单服务模式安装与使用 azkaban ...
- STM32 CubeIDE快速创建工程(图文详解)
使用STM32CubeIDE快速创建STM32的HAL库工程. 文章目录 1 STM32CubeIDE Home 2 生成工程 3 程序下载 1 STM32CubeIDE Home 进入到官网的下载界 ...
- CTR学习笔记&代码实现5-深度ctr模型 DeepCrossing -> DCN
之前总结了PNN,NFM,AFM这类两两向量乘积的方式,这一节我们换新的思路来看特征交互.DeepCrossing是最早在CTR模型中使用ResNet的前辈,DCN在ResNet上进一步创新,为高阶特 ...