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数据库中的数据加密相关推荐

  1. 一起ORACLE数据库中数据查询结果不一致问题的排查过程

    一.问题描述 在某软件开发项目中,需要在ORACLE数据库中建立十张类型相同的员工信息表tb_employeeinfo0~tb_employeeinfo9,并建立向这十张表中插入数据的存储过程.ORA ...

  2. 批量插入数据库语句java_java相关:MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码)...

    java相关:MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码) 发布于 2020-7-22| 复制链接 本文通过实例代码给大家分享了MyBatis批量插入数据到Oracle数据库 ...

  3. 如何从Oracle数据库中的表中获取列名(字段名)列表?

    如何从Oracle数据库中的表中获取列名(字段名)列表? 目录 如何从Oracle数据库中的表中获取列名(字段名)列表? #示例一 #示例二 示例三: #示例一 可以获取: table_name:表名 ...

  4. 导出Windows服务器下的Oracle数据库并导入到Linux服务器下的Oracle数据库中

    2019独角兽企业重金招聘Python工程师标准>>> 说明: 1.Windows Oracle数据库 操作系统:Windows Server 2008 R2 IP地址:192.16 ...

  5. oracle 数据库中(创建、解锁、授权、删除)用户

    上文我们已经建立了名为orcl66的数据库. 想要在数据库中创建.修改用户需要我们以管理员权限登录到数据库中. 首先我们通过sqlplus命令登录连接数据库. 输入sqlplus命令--用户名: sy ...

  6. Oracle表里的照片怎么导出来,如何导出oracle数据库中某张表到excel_oracle数据库表格导出到excel...

    如何将oracle数据库表字段导成excel表格 这个你只要用ADO连oracle并获取记录集,根据你用的编程语言打开EXCEL,然后操作EXCEL对象的工作表就可以了.以VB为例: 1.在工程中引用 ...

  7. 如何将oracle数据库中的表结构导入到sqlserver中,Oracle转换成SqlServer数据库的步骤...

    1 背景 ITM系统目前支持MysqL.Oracle数据库,由于现在需要和CA产品进行结合,用CA产品的采集功能进行数据采集,因此需要使用CA产品的sqlServer数据库,为了使得系统支持sqlse ...

  8. linux删除sde服务,在Oracle数据库中部署多个SDE服务

    在Oracle数据库中部署多个SDE服务 一.一个Oracle部署多个SDE服务(采用问题的方式提供答案) 问题: 目的: 在机器上安装了oracle实例,默认会产生一个数据库实例(SID为 Orcl ...

  9. Oracle数据库中调用Java类开发存储过程、函数的方法

    Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日  浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...

最新文章

  1. 澳大利亚多地热浪来袭 最高温度超40摄氏度
  2. CentOS7.6 Open vSwitch安装
  3. cf534D 枚举握手次数
  4. VTK:网格之FitToHeightMap
  5. 可以发外链的网站_企业网站上线后,何提升网站排名?
  6. Mysql数据库(九)——mysql高阶语句(下)
  7. nyoj164——卡特兰数(待填坑)
  8. 分享 : 警惕MySQL运维陷阱:基于MyCat的伪分布式架构
  9. 【kafka】Group coordinator xx is unavailable or invalid, will attempt rediscovery
  10. Flex 页面跳转 四种方法
  11. Python使用线性回归简单预测数据
  12. MSCI 成份股 清单
  13. UltraEdit for Mac
  14. jQuery文档就绪事件
  15. linux 安装java环境
  16. ios系统gps测试软件,GPS工具箱苹果版
  17. ftp服务器匿名账号,登陆ftp服务器的匿名账号
  18. 使用IDEA+gradle构建spring5源码-手把手教程全图解
  19. 【郭东白架构课 模块一:生存法则】05|法则二:研发人员的人性需求是如何影响架构活动成败的?
  20. Groovy on Grails(Java笨狗)系列---前言(二)

热门文章

  1. 程序员、架构师、技术经理、技术总监和CTO分别都是干什么的?
  2. Tessent专栏第二篇:Tessent Shell ETChecker介绍(1)
  3. php泛目录seo静态泛目录批量千万网页页面生成程序
  4. Trello的5个开源替代品介绍
  5. 推荐免费WEB打印控件PAZU
  6. 西门子dcs系统组态手册下载_DCS、PLC相爱相杀多年,工控人都分清楚了吗?
  7. Mac电脑使用pr2020创建新项目导入素材之后找不到素材
  8. input/print,pycharm设置文件抬头
  9. js 格式化日期 yyyy-MM-dd等其他多种格式
  10. Gox语言的指针类型及其操作-GX12