Oracle中对列加密的方法

时间:2022-09-11 21:33:54
Oracle中对列加密的方法 2011-12-22 17:21:13

分类: Linux

Oracle支持多种列加密方式:

1,透明数据加密(TDE):
create table encrypt_col(id int,
txt varchar2(100) encrypt using '算法名称' identified by '密钥' no salt);
优点:对应用完全透明
缺点:需要数据库管理员管理wallet,增加了管理复杂性,也无法避免数据库管理员查看原文。

2,使用DBMS_CRYPTO包
优点:只要应用程序保存好密钥,数据库管理员无法察看:

测试:
DECLARE
   input_string       VARCHAR2 (200) :=  'Secret Message';
   output_string      VARCHAR2 (200);
   encrypted_raw      RAW (2000);             -- stores encrypted binary text
   decrypted_raw      RAW (2000);             -- stores decrypted binary text
   num_key_bytes      NUMBER := 256/8;        -- key length 256 bits (32 bytes)
   key_bytes_raw      RAW (32);               -- stores 256-bit encryption key
   encryption_type    PLS_INTEGER :=          -- total encryption type
                            DBMS_CRYPTO.ENCRYPT_AES256
                          + DBMS_CRYPTO.CHAIN_CBC
                          + DBMS_CRYPTO.PAD_PKCS5;
BEGIN
   DBMS_OUTPUT.PUT_LINE ( 'Original string: ' || input_string);
   key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);
   DBMS_OUTPUT.PUT_LINE ( 'key_bytes_raw: ' || key_bytes_raw);

encrypted_raw := DBMS_CRYPTO.ENCRYPT
      (
         src => UTL_I18N.STRING_TO_RAW (input_string,  'AL32UTF8'),
         typ => encryption_type,
         key => key_bytes_raw
      );
   DBMS_OUTPUT.PUT_LINE ('Encrypted string: ' || encrypted_raw);
 
   decrypted_raw := DBMS_CRYPTO.DECRYPT
      (
         src => encrypted_raw,
         typ => encryption_type,
         key => key_bytes_raw
      );
   output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
 
   DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);
END;
/

==>
Original string: Secret Message
key_bytes_raw  : 2D9AB3BE8CDFBCD942162D0F6C90956C503E432D5128BE26116C39BA4DAC6B96
Encrypted string: 51E36E4576F951A940B671394B2FDC05
Decrypted string: Secret Message

------------------
透明数据加密常见问题解答

TDE 有哪些相关的开销? 
与未加密的表空间相比,加密的表空间不会要求更高的存储空间。

与列级 TDE 相关的开销分为两方面:存储和性能。在性能方面,与加密或解密常用属性(如信用卡号码)相关的开销估计为 5%。当索引基于加密列构建时,索引的创建将使用密文。如果经 TDE 加密的列已建立索引并为 SQL 语句引用,Oracle 将对 SQL 语句中用到的值进行透明加密并使用密文进行索引查询。TDE 相关的存储开销可能会很大,这是因为每个加密值都有额外 20 个字节的完整性检查。此外,TDE 会将加密值填充到 16 个字节,所以如果信用卡号码要求 9 个字节的存储空间,加密该号码将要求额外 7 个字节的存储空间。最后,如果为加密值指定了 salt,该 salt 将要求额外 16 个字节的存储空间。总之,加密表中的一列将要求每行有 33 到 48 个字节的额外存储空间。

--------------------------------------------------------------------------------

数据在网络上依然是加密状态吗? 
使用 TDE 加密后的数据在离开数据库前会首先进行解密。不过,这些数据可以通过 Oracle 的网络加密解决方案在网络上进行加密,该方案和 TDE 一同包含在 Oracle Advanced Security 选件中。Oracle 的网络加密解决方案可以对 Oracle SQL*Net 上传送的所有数据进行加密。

--------------------------------------------------------------------------------

任何人只要获得应用程序的授权就能对数据进行解密吗? 
是的,TDE 在使客户能够在数据库内应用加密,而不影响现有的应用程序。以加密格式返回数据会破坏现有的应用程序。TDE 的优势是,加密不会产生传统数据库加密解决方案所产生的开销,传统的方案要求有触发器和视图。

--------------------------------------------------------------------------------

TDE 与 Oracle 提供的加密方法有何不同? 
Oracle 通过 Oracle8i 引入了 DBMS_OBFUSCATION_TOOLKIT。Oracle 10g 版本 1 引入了新的 DBMS_CRYPTO 程序包。这些程序包中的各种 API 可用于对数据库内的数据进行手动加密。不过,此应用程序必须管理加密密钥,并且要通过调用 API 进行要求的加密和解密操作。

--------------------------------------------------------------------------------

哪些加密算法可与 TDE 一同使用? 
TDE 支持 3DES168、AES128(表空间加密默认算法)、AES192(列级 TDE 默认算法)和 AES256。

--------------------------------------------------------------------------------

可以使用第三方加密算法代替 TDE 提供的算法吗? 
不可以,不能插入其他加密算法。

--------------------------------------------------------------------------------

TDE 的许可方式是什么? 
TDE 作为 Oracle Advanced Security 选件的一部分进行打包,该选件包含在 Oracle 企业版中。

--------------------------------------------------------------------------------

可以对带有外键约束的列使用 TDE 吗? 
使用表空间加密时,即使某个表在加密的表空间外部,外键的加密方式也和加密表空间中存储的所有其他元素相同。列级 TDE 不支持对外键约束中使用的列进行加密。这是因为单个表有它们自己的特殊加密密钥。

--------------------------------------------------------------------------------

可以对联接中使用的列进行加密吗? 
可以。即使联接条件的列已加密,联接表对于应用程序和用户也是透明的。

--------------------------------------------------------------------------------

TDE 支持哪些数据类型? 
由于表空间加密对整个表空间进行加密,在支持的数据类型上没有限制。

下面的数据类型可使用列级 TDE 进行加密:

varchar2         nvarchar2
  number                date
  binary_float          binary_double
  timestamp             raw
  char                  nchar
  SecureFile LOBs

--------------------------------------------------------------------------------

何时使用列级 TDE 或表空间加密? 
根据下面的指导原则确定具体方法的选择:

仅对因合规性原因需要加密的数据进行加密(PCI-DSS 的信用卡和帐户号码;用于类似于 CA SB 1386 这样的漏洞通知法律的地址、姓名和个人身份号码(驾驶证,身份证)),或者对其他您认为的关键数据进行加密,如薪水、研究结果、客户信息。 
如果您需要对外键列中的数据进行加密,或者您需要除 B 树外的索引,又或者您需要对列级 TDE 不支持的数据类型进行加密,可选择表空间加密。 
如果列级 TDE 能够满足您的安全和安规性要求,您可以根据性能测试结果进行选择

--------------------------------------------------------------------------------

加密密钥可以更改吗? 
表空间加密的万能密钥不能重新生成。变通方法是,创建一个新的加密表空间,备份当前表空间,将所有表和其他内容从旧的表空间转移到新表空间中,然后删除旧的加密表空间。

列级 TDE 使用一个两层密钥机制。当列级 TDE 应用到现有的应用程序表列上时,Oracle 数据字典中会创建并存储一个新的表钥(用于该表中所有列)。该表钥使用万能密钥加密。万能密钥在 TDE 进行初始化时生成,并存储在数据库外部的 Oracle 钱夹或符合 PKCS#11 的 HSM 设备中。万能密钥和列密钥均可基于公司的安全策略进行独立修改。Oracle 建议在修改万能密钥前后均对钱夹进行备份。

--------------------------------------------------------------------------------

可否在 HSM 设备中存储用于表空间加密的万能密钥? 
不可以。如果您从 10gR2 中的列加密移植到 11gR1 中的列和表空间加密,则必须首先在 11gR1 数据库上重新生成万能密钥,以自动将用于表空间加密的万能密钥添加到您的软件钱夹上,然后将列万能密钥移植到 HSM 设备上。

--------------------------------------------------------------------------------

可以加密现有表空间吗? 
不可以。变通方法是,创建一个新的加密表空间,备份当前表空间,将所有表和其他内容从旧的表空间转移到新表空间中,然后删除旧的加密表空间。

--------------------------------------------------------------------------------

压缩可否与表空间加密协同工作? 
可以,内容在压缩后进行加密。

--------------------------------------------------------------------------------

可传输的表空间可否与加密的表空间协同工作? 
可以。但条件是,要么目标数据库上必须有万能密钥;要么,如果已经使用了一个不同的万能密钥,使用 Oracle 数据泵对数据进行导出和导入,这可以通过转储文件的可选加密来完成。

--------------------------------------------------------------------------------

什么是钱夹? 
钱夹是一个容器,用于存储认证和签名证书,包括 TDE 万能密钥、PKI 私钥、许可证和 SSL 需要的信托证书。借助 TDE,可以在服务器上使用钱夹来保护 TDE 万能密钥。此外,Oracle 要求在 SSL 上通信的实体包含一个钱夹。除 Diffie-Hellman 外,该钱夹应当含有 X.509 版本 3 许可证、私钥、信托证书列表。

Oracle 提供两种类型钱夹:加密钱夹和自动打开的钱夹。我们为 TDE 推荐加密钱夹(文件名为 ewallet.p12)。数据库启动后和访问 TDE 加密数据前,需手动打开该钱夹。如果未打开该钱夹,查询受 TDE 保护的数据时数据库将返回错误。自动打开的钱夹(文件名是 cwallet.sso)在数据库启动时会自动打开。因此它适用于无人值守的 Data Guard 环境,在该环境中加密后的列会传送到二级站点。

--------------------------------------------------------------------------------

TDE 中的密钥管理功能如何? 
TDE 中的密钥管理包括下面的功能:

生成 
存储 
替换 
销毁 
生成 — 在 TDE 中生成万能密钥可以通过数据库中的随机数生成器 (RNG) 来完成,或者管理员可以自行提供最多 70 个字符的字符串。

存储 — 一种选择是将万能密钥存储在 Oracle 软件钱夹中。该文件应当受到适当 OS 许可的保护。根据 PKCS#5 标准,钱夹使用钱夹口令进行加密。钱夹口令不存储在任何地方,在 Oracle Enterprise Manager 11g 中,该口令可以在任意数量的用户或管理员间进行分割,他们必须以正确的顺序输入各自口令片断,而与此同时他们当中无人知道整个口令。该口令甚至可以保护万能密钥不被拥有“root”权限的用户使用。 
另一种选择是将用于列级 TDE 的 TDE 万能密钥存储在硬件安全模块 (HSM) 上。Oracle 数据库 11g 和 HSM 设备之间的通信基于标准的 PKCS#11 接口,它使得众多 HSM 厂商都可与 Oracle 进行互操作。一旦设备上生成了万能密钥,它将永远不会在未加密的情况下离开设备。

替换 — 通过简单的命令就可以创建新的 TDE 万能密钥。倾刻间,数据库中的所有列密钥都会用旧的万能密钥解密然后用新的列密钥进行加密。应用程序数据不会发生任何变化,因此该过程不会影响您数据库的可用性。对于备份和恢复操作,过期的万能密钥存储在钱夹中。

销毁 — 使用命令行实用程序“mkstore”可对万能密钥进行销毁。使用“mkstore”前要对钱夹进行备份,同时要谨慎使用该程序,因为很容易删除当前的万能密钥(该密钥不能替换或重新生成)。

--------------------------------------------------------------------------------

如何保护钱夹和 TDE 万能密钥? 
Oracle 数据库 11g 允许在符合 PKCS#11 标准的 HSM 设备上存储列级 TDE 万能密钥,万能密钥永远不会在未加密的情况下离开设备。

对软件钱夹(对于表空间加密和加密的转储文件以及使用基于软件的万能密钥所创建的备份而言,它是必需的)的访问应当通过文件级别的许可进行限制。加密该钱夹(基于 PKCS#5)的口令应当包含超过 10 个字母和数字字符。软件钱夹口令可通过 Oracle Wallet Manager 修改。改变钱夹口令不会影响 TDE 万能密钥(它们彼此无关)。钱夹口令甚至可以阻止拥有“root”权限并可访问钱夹文件的用户获取 TDE 万能密钥。

--------------------------------------------------------------------------------

Oracle Wallet Manager 在哪个默认位置寻找钱夹? 
在 Unix 和 Linux 中,其位置是

/etc/ORACLE/WALLETS/<Oracle software owner user name>
通常转换为

/etc/ORACLE/WALLETS/oracle

--------------------------------------------------------------------------------

可否使用 Oracle Wallet Manager (OWM) 为 TDE 创建加密钱夹和万能密钥 
不能。如果您使用 Oracle Wallet Manager 创建加密钱夹,则无法包含 TDE 所需的万能密钥。只有以下 SQL 命令:

SQL> alter system set encryption key identified by "wallet_password";
能够创建软件钱夹(若其不存在),并为其添加一个万能密钥。

SQL> alter system set encryption key identified by "userID:password";
能够在 HSM 设备内创建一个万能密钥。用户 ID 和口令是 HSM 设备内所创建的用户的证书,用于支持与 Oracle 数据库的通信。在此之前,需要将 HSM 厂商的库放到存档的目录中,同时需要在 sqlnet.ora 中将字符串“METHOD=FILE”改为“METHOD=HSM”。

如果您希望升级到某个 HSM 设备后继续使用相同的万能密钥,使用:

SQL> alter system set encryption key identified by "userID:password"

migrate using "wallet_password";
                                      
--------------------------------------------------------------------------------

如何创建自动打开的钱夹? 
自动打开的钱夹 ('cwallet.sso') 需要利用现有的加密钱夹 ('ewallet.p12') 创建,这样万能密钥就能在自动打开的钱夹中使用了。

您可以在 Oracle Wallet Manager (OWM) 中打开加密钱夹,选中“Auto Login”复选框,然后选择“Save”将自动打开的钱夹写到磁盘上,也可以使用命令行工具“orapki”:

orapki wallet create -wallet <wallet_location> -auto_login
两种情况都要求提供钱夹口令。

--------------------------------------------------------------------------------

使用 Oracle 安全备份时,如何避免将 Oracle TDE 钱夹备份到 RMAN 数据库备份所在的磁带上? 
RMAN 将数据库文件、重做日志等添到备份文件中,因此加密钱夹或自动打开的钱夹不会成为数据库备份的一部分。Oracle 安全备份 (OSB) 使用数据集来定义待备份的操作系统文件。OSB 自动排除自动打开的钱夹 ('cwallet.sso')。加密钱夹 ('ewallet.p12') 不会被自动排除。您需要使用排除数据集语句来指定备份过程中需要跳过的文件:

exclude name ewallet.p12
有关 EXCLUDE 关键字的详细说明

--------------------------------------------------------------------------------

什么是 Oracle 安全备份 (OSB)? 
OSB 为 Oracle 数据库提供优化的、高效的磁带备份解决方案。OSB 能够以加密的格式在磁带上存储数据,从而防范备份磁带被盗窃。

--------------------------------------------------------------------------------

可否使用 Oracle 安全备份对发送至磁盘的备份进行加密? 
不能。不过,Oracle RMAN 可与 Oracle Advanced Security 一起使用,以便对磁盘上的数据库备份进行加密。

--------------------------------------------------------------------------------

TDE 可否与 Data Guard 和 Oracle RAC 协同工作? 
可以。TDE 可以与 Data Guard(物理或逻辑备份)和真正应用集群 (RAC) 协同工作,但前提是,您必须将包含万能密钥的钱夹复制到其他实例中,同时要将各个实例上的钱夹打开,以使这些实例均可使用该万能密钥。

--------------------------------------------------------------------------------

是否有其他不能与列级 TDE 协同工作的数据库特性? 
当数据经过 SQL 层时,列级 TDE 会对数据进行透明地加密和解密。Oracle 的某些特性会跳过 SQL 层,因此不能利用 TDE:

Materialized View Logs
  Sync. and async. CDC (change data capture)
  Classical LOBs (SecureFile LOBs  
                                        are supported)
                                      
--------------------------------------------------------------------------------

可否使用带有直接路径的 SQL*Loader 将数据加载到包含加密列的表中? 
可以。SQL*Loader 语法、.dat 文件和 .ctl 文件不会有任何变化。如果目标表包含有加密的列,数据将在加载时进行透明加密。以下简单示例说明了如何使用带有直接路径的 SQL*Loader。只需将 ulcase6.sql 中的一行从

sal number(7,2),
更改为

sal number(7,2) encrypt no salt,
并使用 SQL*Loader 的正确语法:

sqlldr USERID=scott/tiger CONTROL=ulcase6.ctl LOG=ulcase6.log DIRECT=TRUE

--------------------------------------------------------------------------------

在重新生成万能密钥和/或列密钥后如何恢复数据?

在创建备份后到将其恢复前,万能密钥已发生更改。 
在这种情况下,恢复包含加密列的表对用户而言是透明的。TDE 钱夹对过期万能密钥的历史进行了记录,同时自动将正确的万能密钥应用到备份数据上。这就是为什么经常备份钱夹(备份到与加密数据不同的位置)如此重要的原因。 
在创建备份后到将其恢复前,全部或部分加密列的列密钥已重新生成: 
如果已使用 RMAN 在磁盘上创建备份文件,除非指示 RMAN 执行加密操作,否则文件不会被加密。当文件被读取回时,它的列会使用新的列密钥重新加密,而不论 RMAN 是否对文件进行了加密。

--------------------------------------------------------------------------------

如何加密超大型表(包含数十亿行)中的列? 
对现有表中的列进行加密仅允许对该表进行 Read 访问,而不允许进行 DML 操作。由于有数十亿行,这一可用性有限的窗口会持续很长时间。联机重新定义仅需要一个持续时间非常短的窗口对原始表进行锁定。该时间长度与加密数据的数量或重新定义的复杂性无关,并且对用户和应用程序是透明的。

--------------------------------------------------------------------------------

加密列中的现有数据后再查看数据库文件,有时仍能看到某些明文值。为什么? 
这种情况与即使已删除表或文件、但仍然会在磁盘上看到数据的情况相同。在一个表的生命周期内,数据可能会在表空间内分段、重新整理、排序、复制和移动。这会在数据库文件中留下数据的“虚副本”。在加密现有列时,仅最新的“有效”副本被加密,这就将旧的明文版本留在了“虚副本”中。如果直接访问包含表空间的数据文件,从而绕过数据库的访问控制(例如,带有十六进制编辑器的数据库),那么在那些块被数据库覆盖之前,有时就会看到旧的明文值。为使风险最小化,请遵循下面的建议:

在新的数据文件中创建一个新的表空间 (CREATE TABLESPACE ... ) 
对原始表空间和数据文件中的明文值进行加密 (ALTER TABLE ...ENCRYPT) 
对包含加密列的所有表执行步骤 2 
将原始表空间中的所有表移到新的数据文件中 (ALTER TABLE ....MOVE... ) 
删除原始表空间 (DROP TABLESPACE)不要使用“and datafiles”参数,Oracle 推荐使用更强大的方法进行 OS 级操作,参见步骤 6 
针对您的平台使用“shred”、“eraser”、“SDelete”或其他命令,以便在 OS 级别上删除旧数据文件

建议您使用第 6 步操作来降低数据库文件出现虚副本的概率,不论这些副本是由操作系统生成还是由存储固件生成。