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形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...
随机推荐
- Spring Boot入门系列(十三)如何实现事务
前面介绍了Spring Boot 中的整合Mybatis并实现增删改查.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1 ...
- HMM-前向后向算法理解与实现(python)
目录 基本要素 HMM三大问题 概率计算问题 前向算法 后向算法 前向-后向算法 基本要素 状态 \(N\)个 状态序列 \(S = s_1,s_2,...\) 观测序列 \(O=O_1,O_2,.. ...
- 超过百万的StackOverflow Flutter 问题-第二期
老孟导读:一个月前分享的<超过百万的StackOverflow Flutter 问题-第一期>受到很多朋友的喜欢,非常感谢大家的支持,在文章末尾有第一期的链接,希望此文能对你有所帮助. N ...
- fragment hide/show 生命周期
Fragment的使用越来越普遍了,掌握它的生命周期以及注意事项时非常有必要的,首先 All subclasses of Fragment must include a public empty co ...
- Atcoder Beginner Contest 166
VP赛况如下: 前言:感觉这一场题目难度还是比较贴近新生的,我一个codeforces小蓝名一小时居然AK了,F题数据有点水(?)暴力dfs居然都能过... A:A?C 题意:给你字符串,如果字符串是 ...
- 非系统盘根目录出现msdia80.dll文件,能否删除?
出现此问题的原因:计算机上安装了 Microsoft Visual C++ 2005 可再发行组件时,Msdia80.dll文件被错误安装在其他驱动器的根文件夹中. 它的正确路径应该是"C: ...
- virtualbox复制了以后网卡启动不了。
还是有些坑..必须踩 virtualbox复制了以后网卡启动不了.原因是如果没选重新生成mac ,那么mac地址会和第一台 机器一模一样,出现ip 征用的情况. 第二是系统方面的原因,你要删一个文件, ...
- EOS基础全家桶(十二)智能合约IDE-VSCode
简介 上一篇我们介绍了EOS的专用IDE工具EOS Studio,该工具的优势是简单,易上手,但是灵活性低,且对系统资源开销大,依赖多,容易出现功能异常.那么我们开发人员最容易使用的,可能还是深度定制 ...
- 2-SAT问题简述
前置知识 强连通分量 k-SAT问题 k-SAT问题中的SAT意思就是(stability),也就是适应性问题.本意是给出n个变量,每一个变量有k个状态,并且也给出一些约束条件,要求你求出是否存在每一 ...
- jQuery的插件和跨域、ajax
1. 插件: 也称组件 什么是: 拥有专属的HTML,CSS和js的独立页面区域 为什么: 重用! 何时: 只要一个功能/区域可能被反复使用时 如何: 3个来源: 1. 官方插件:jquery ui ...