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形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...
随机推荐
- sqlserver2005定期备份和清除
1.打开管理->维护计划 2.右键点击新建维护计划 3.给新的维护计划自定义命名 4.可以看左下角的维护方式 5.拖动“备份数据库”到右边 6.选中,编辑备份方式 7.选择备份方式,所有数据库, ...
- spring学习笔记(七)HttpMessageConverter
spring学习笔记(七)HttpMessageConverter 1. HttpMessageConverter的加载 2. 从StringMessageConverter探究消息转换器的原理 1. ...
- 201771010113 李婷华 《面向对象程序设计(Java)》第十三周总结
一.理论知识部分 第十一章 事件处理 事件源 (event source):能够产生事件的对象都可 以成为事件源 ,如文本框 .按钮等 .一个事件源是一个能够注册监听器并向发送事件对象的对象. 监听器 ...
- Day_09【常用API】扩展案例8_计算字符'j'和字符串'java'在字符串中出现的次数
需求说明 定义如下字符串: String str = "javajfiewjavajfiowfjavagkljjava"; 请分别定义方法统计出: 1.字符串中:字符j的数量 2. ...
- 《C程序设计语言》 练习2-6 及 位运算总结
问题描述 2.6 编写一个函数setbits(x, p ,n, y),该函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变. Wr ...
- MOS管、PCB、H桥、步进电机驱动电路、51单片机的IO口驱动能力、灌电流、拉电流、上拉电阻的选择
嵌入式开发PCB设计几点体会(转载):http://bbs.ednchina.com/BLOG_ARTICLE_3021801.HTMCollector-Emitter Saturation Volt ...
- MATLAB1127(传递函数)
sys=tf(400,[1,50,0]) sys = 400 ---------- s^2 + 50 s 其中,tf()函数的用法. 传递函数 dsys=c2d(sys,ts,'z') dsys ...
- 24款WordPress网站AI插件大盘点
------------恢复内容开始------------ 你想把AI(人工智能)技术和机器学习技术添加到自己的WordPress网站吗?本文中,我会分享24个利用AI技术和机器学习技术的WordP ...
- [whu1564]后缀数组
http://acm.whu.edu.cn/land/problem/detail?problem_id=1564 思路:先把串复制一遍,在末尾补个标记,后缀数组跑一下,扫一遍就ok了(过滤后缀在后半 ...
- git工作中最常用的用法教程,不走命令行
·1.1 git的概述 Git(读音为/gɪt/.)是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Lin ...