Oracle数据库中的数据加密
Oracle数据库中的数据加密 / Oracle数据库DES加密
有个需求,需要对某些敏感信息字段进行脱敏,要求在数据库中不能显示明文。如果目的侧重保护数据而非脱敏的话,可以考虑用表空间透明数据加密(TDE),不过现在是需要对字段内容脱敏,则读取和存储都要是加密后的密文数据。
增量数据好说,后台代码实现即可。但存量数据如果也要后台与数据库交互进行加密的话,且不说IO的消耗,就先查再改,无论单条还是分批,在数十、百万的数据量下估计需要很长时间。那就要考虑在数据库里用PL/SQL做存量数据的加密操作。
Oracle中的加密函数
Oracle的PL/SQL包中有提供相关的函数。
PL/SQL包类官方文档(10.2版本):Database PL/SQL Packages and Types Reference - Contents (oracle.com)
版本在10g之前的话,只能使用DBMS_OBFUSCATION_TOOLKIT这个包来加密,这个包只支持DES和3DES算法,且只有CBC模式,还要手动补位;而在10g以及更高的版本中,则能使用DBMS_CRYPTO包,这个包的加密算法更加丰富,DES、3DES、 AES、RC4、3DES_2KEY等算法和CBC、CFB、ECB、OFB模式,也提供补位,使用起来更简单。
DBMS_CRYPTO和DBMS_OBFUSCATION_TOOLKIT的特性对比
Package Feature | DBMS_CRYPTO | DBMS_OBFUSCATION_TOOLKIT |
---|---|---|
Cryptographic algorithms | DES, 3DES, AES, RC4, 3DES_2KEY | DES, 3DES |
Padding forms | PKCS5, zeroes | none supported |
Block cipher chaining modes | CBC, CFB, ECB, OFB | CBC |
Cryptographic hash algorithms | MD5, SHA-1, MD4 | MD5 |
Keyed hash (MAC) algorithms | HMAC_MD5, HMAC_SH1 | none supported |
Cryptographic pseudo-random number generator |
RAW , NUMBER , BINARY_INTEGER
|
RAW , VARCHAR2
|
Database types |
RAW , CLOB , BLOB
|
RAW , VARCHAR2
|
DBMS_OBFUSCATION_TOOLKIT
使用该包的加密函数需要手动实现补位,同时也只有CBC模式。以使用DES加密为例,自定义一个函数实现输入明文字符串,输出DES/CBC/PKCS5加密并Base64编码后的密文字符串。
根据文档提供的函数定义,选用第一种。
DBMS_OBFUSCATION_TOOLKIT.DESEncrypt(input IN RAW,key IN RAW)RETURN RAW;DBMS_OBFUSCATION_TOOLKIT.DESEncrypt(input_string IN VARCHAR2,key_string IN VARCHAR2)RETURN VARCHAR2;
因为加密的数据含中文,一个汉字占两个字节,而数字英文占一个字节,VARCHAR2类型直接进行长度判断补位不对,需要转为RAW类型按字节长度判断,所以直接以RAW类型传参。
Oracle中可以使用UTL_I18N.STRING_TO_RAW或UTL_RAW.CAST_TO_RAW来将VARCHAR2类型转为RAW类型。
将明文字符串转成二进制数据类型RAW,然后判断其长度进行PKCS5方式的补位(该补位方法是缺几位就补几位的“几”以满足八的倍数结果,如果一开始已满足,也要加八位的八),密钥也需要转换为RAW格式。DES密钥为64位,即需要8字节的输入,小于8字节会报错,大于的部分会被忽略。
密钥这里我在函数中定义了(应该提出来作为入参,提高安全性)。因为BASE64_ENCODE进行编码的时候,输入的字节数多的话会自动添加换行符,所以做了一个去除处理。
create or replace function encrypt_des(input_str varchar2) return varchar2isenc_str varchar2(256);pad_length NUMBER(1);pad_byte RAW(1);raw_input RAW(512);raw_key RAW(16);enc_raw RAW(1024);
beginif input_str is nullthenreturn input_str;elseraw_input := UTL_RAW.CAST_TO_RAW(input_str);-- padding: pad n with n lacking n lengthpad_length := (8 - MOD(UTL_RAW.LENGTH(raw_input), 8));pad_byte := TO_SINGLE_BYTE(pad_length);while pad_length > 0loopraw_input := UTL_RAW.CONCAT(raw_input, pad_byte);pad_length := pad_length - 1;end loop;-- key settingraw_key := UTL_RAW.CAST_TO_RAW('keytests');enc_raw := DBMS_OBFUSCATION_TOOLKIT.DESENCRYPT(input => raw_input, key => raw_key);-- remove line breakenc_str := UTL_RAW.CAST_TO_VARCHAR2(REPLACE(UTL_ENCODE.BASE64_ENCODE(enc_raw), '0D0A', ''));return enc_str;end if;
end;
/
DBMS_CRYPTO
使用此包需要向调用的用户授予权限。
以SYSDBA用户登录后:
$ sqlplus / as sysdba
授予权限:
GRANT EXECUTE ON DBMS_CRYPTO TO USER_NAME;
加密函数语法:
DBMS_CRYPTO.ENCRYPT(src IN RAW,typ IN PLS_INTEGER,key IN RAW,iv IN RAW DEFAULT NULL)RETURN RAW;
使用该包的加密函数,就不需要手动补位了,只要选择好想实现加密算法、加密模式和补位的模式即可。因此自定的函数式为输入的字符串做RAW类型的转换并加密和base64编码的实现。
create or replace function crypto_des(input_str varchar2) return varchar2isenc_str varchar2(256);raw_key RAW(16);enc_raw RAW(1024);enc_type PLS_INTEGER := -- total encryption typeDBMS_CRYPTO.ENCRYPT_DES+ DBMS_CRYPTO.CHAIN_CBC+ DBMS_CRYPTO.PAD_PKCS5;
beginif input_str is nullthenreturn input_str;else-- key settingraw_key := UTL_RAW.CAST_TO_RAW('keytests');enc_raw := DBMS_CRYPTO.ENCRYPT(UTL_RAW.CAST_TO_RAW(input_str), enc_type, raw_key);-- remove line breakenc_str := UTL_RAW.CAST_TO_VARCHAR2(REPLACE(UTL_ENCODE.BASE64_ENCODE(enc_raw), '0D0A', ''));return enc_str;end if;
end;
/
也可以直接一条SQL实现:
select UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(DBMS_CRYPTO.ENCRYPT(UTL_RAW.CAST_TO_RAW('测试一下123abc'), 4353, UTL_RAW.CAST_TO_RAW('keytests')))) as test from dual;
4353是DES/CBC/PKCS5加密方式的数字代码。因为PL/SQL中的常量不能直接在SQL中使用,而需要在PL/SQL块中使用,所以把4353换成DBMS_CRYPTO.DES_CBC_PKCS5或是DBMS_CRYPTO.ENCRYPT_DES+ DBMS_CRYPTO.CHAIN_CBC+ DBMS_CRYPTO.PAD_PKCS5的话会报错。
Java中相应的加解密
RFC 822规定中Base64编码后每76个字符需要加一个换行符。一些旧包编码后会带换行符,如sun.mis(效率也不太好)。
JDK1.8可以直接用自带的java.util.Base64包,不会有换行符。
这里示例Base64编码包是commons-codec的,该包编码后不会有换行符。
public static final String KEY = "keytests";public static String encrypt(String inputStr) {if (null != inputStr && !"".equals(inputStr)) {try {DESKeySpec desKey = new DESKeySpec(KEY.getBytes());SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(desKey);Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[8]));byte[] encryptedBytes = cipher.doFinal(inputStr.getBytes());return Base64.encodeBase64String(encryptedBytes);} catch (Exception e) {e.printStackTrace();}}return inputStr;
}
public static String decrypt(String encryptedStr){if (null != encryptedStr && !"".equals(encryptedStr)) {try {// encryptStr = encryptStr.replace("\r\n","");DESKeySpec desKey = new DESKeySpec(KEY.getBytes());SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(desKey);Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(new byte[8]));byte[] decryptBytes = cipher.doFinal(Base64.decodeBase64(encryptedStr));return new String(decryptBytes);} catch (Exception e) {e.printStackTrace();}}return encryptedStr;
}
Oracle数据库中的数据加密相关推荐
- 一起ORACLE数据库中数据查询结果不一致问题的排查过程
一.问题描述 在某软件开发项目中,需要在ORACLE数据库中建立十张类型相同的员工信息表tb_employeeinfo0~tb_employeeinfo9,并建立向这十张表中插入数据的存储过程.ORA ...
- 批量插入数据库语句java_java相关:MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码)...
java相关:MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码) 发布于 2020-7-22| 复制链接 本文通过实例代码给大家分享了MyBatis批量插入数据到Oracle数据库 ...
- 如何从Oracle数据库中的表中获取列名(字段名)列表?
如何从Oracle数据库中的表中获取列名(字段名)列表? 目录 如何从Oracle数据库中的表中获取列名(字段名)列表? #示例一 #示例二 示例三: #示例一 可以获取: table_name:表名 ...
- 导出Windows服务器下的Oracle数据库并导入到Linux服务器下的Oracle数据库中
2019独角兽企业重金招聘Python工程师标准>>> 说明: 1.Windows Oracle数据库 操作系统:Windows Server 2008 R2 IP地址:192.16 ...
- oracle 数据库中(创建、解锁、授权、删除)用户
上文我们已经建立了名为orcl66的数据库. 想要在数据库中创建.修改用户需要我们以管理员权限登录到数据库中. 首先我们通过sqlplus命令登录连接数据库. 输入sqlplus命令--用户名: sy ...
- Oracle表里的照片怎么导出来,如何导出oracle数据库中某张表到excel_oracle数据库表格导出到excel...
如何将oracle数据库表字段导成excel表格 这个你只要用ADO连oracle并获取记录集,根据你用的编程语言打开EXCEL,然后操作EXCEL对象的工作表就可以了.以VB为例: 1.在工程中引用 ...
- 如何将oracle数据库中的表结构导入到sqlserver中,Oracle转换成SqlServer数据库的步骤...
1 背景 ITM系统目前支持MysqL.Oracle数据库,由于现在需要和CA产品进行结合,用CA产品的采集功能进行数据采集,因此需要使用CA产品的sqlServer数据库,为了使得系统支持sqlse ...
- linux删除sde服务,在Oracle数据库中部署多个SDE服务
在Oracle数据库中部署多个SDE服务 一.一个Oracle部署多个SDE服务(采用问题的方式提供答案) 问题: 目的: 在机器上安装了oracle实例,默认会产生一个数据库实例(SID为 Orcl ...
- Oracle数据库中调用Java类开发存储过程、函数的方法
Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日 浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...
最新文章
- 澳大利亚多地热浪来袭 最高温度超40摄氏度
- CentOS7.6 Open vSwitch安装
- cf534D 枚举握手次数
- VTK:网格之FitToHeightMap
- 可以发外链的网站_企业网站上线后,何提升网站排名?
- Mysql数据库(九)——mysql高阶语句(下)
- nyoj164——卡特兰数(待填坑)
- 分享 : 警惕MySQL运维陷阱:基于MyCat的伪分布式架构
- 【kafka】Group coordinator xx is unavailable or invalid, will attempt rediscovery
- Flex 页面跳转 四种方法
- Python使用线性回归简单预测数据
- MSCI 成份股 清单
- UltraEdit for Mac
- jQuery文档就绪事件
- linux 安装java环境
- ios系统gps测试软件,GPS工具箱苹果版
- ftp服务器匿名账号,登陆ftp服务器的匿名账号
- 使用IDEA+gradle构建spring5源码-手把手教程全图解
- 【郭东白架构课 模块一:生存法则】05|法则二:研发人员的人性需求是如何影响架构活动成败的?
- Groovy on Grails(Java笨狗)系列---前言(二)
热门文章
- 程序员、架构师、技术经理、技术总监和CTO分别都是干什么的?
- Tessent专栏第二篇:Tessent Shell ETChecker介绍(1)
- php泛目录seo静态泛目录批量千万网页页面生成程序
- Trello的5个开源替代品介绍
- 推荐免费WEB打印控件PAZU
- 西门子dcs系统组态手册下载_DCS、PLC相爱相杀多年,工控人都分清楚了吗?
- Mac电脑使用pr2020创建新项目导入素材之后找不到素材
- input/print,pycharm设置文件抬头
- js 格式化日期 yyyy-MM-dd等其他多种格式
- Gox语言的指针类型及其操作-GX12