级别: 中级 Bill Winter (bwinter@us.ibm.com), 顾问 IT 专家, IBM
2006 年 2 月 06 日 最近的政府法规和市场需求更多地要求对数据资源进行加密。数据加密是帮助应用程序开发人员满足更高安全性要求的重要工具。本文描述 IBM UniData® 和 UniVerse® 数据库产品中提供的加密选项,并展示如何使用它们在 U2 应用程序中使用数据加密。
在过去几年中,数据安全越来越多地成为应用程序开发人员和 IT 从业人员感兴趣的话题。对于很多公司来说,这种兴趣是由于新的政府法规导致的。例如在美国,联邦法律如健康保险可携性及责任性法(Health Insurance Portability and Accountability Act,HIPAA)和格让姆-里奇-比利法案(Gramm-Leach-Bliley Act),加上州和地方法律如 California Senate Bill 1386 法案,都促使数据安全成为一个重大问题。身份窃取事件的显著增多,人们对个人数据保密的日益关注,以及客户和供应商的普遍需要,都导致了对安全性的需要。公司希望通过一些途径来更好地保护他们的数据资源不会受到未经授权的访问。数据加密是帮助解决数据安全问题的流行而又强大的工具。
UniData 和 UniVerse 数据库产品(合称 U2)提供了先进的加密技术,可以帮助应用程序开发人员满足数据安全需求。这些数据安全需求可以很方便地划分为保障 “传输中的数据” 的安全(例如在客户机与服务器之间移动的数据或者在公共或专用网络上传输的数据)和保障 “静态的数据” 的安全(存储在磁盘介质、备份磁带、CD-ROM 或其他静态介质上的数据)。U2 数据库产品提供了适合解决这两类需求的加密选项。
什么是加密?
加密(encryption)是指通过使用一种叫做 cipher(加密)的算法将数据从它的初始格式,即 “明文(plaintext)” 转换成一种不可读的格式,即 “密文(ciphertext)” 的过程。而解密(decryption)是一个逆过程。在解密时,密文被重新转换成相应的明文。加密的目的是使未经授权的查看者即使可以访问到密文,也不能读到敏感信息。数千年来,人们长期使用加密来保护数据。例如传说中恺撒大帝就曾使用简单的替换加密来防止未经授权者读懂消息。现代密码术则使用以硬件或软件实现的数学上的高级算法来加密和解密数据。这些算法可以分为几类,其中有两类算法常用于保护传输中的数据和静态的数据:
对称密钥加密
在对称密钥加密中,明文的加密过程是这样的:将一个固定的文本,即 “密钥” 和明文一起提交给加密算法,然后加密算法返回密文。密文的解密则通过将密钥和密文提交给一个解密算法来完成。由于加密和解密都使用相同的密钥,因此这种算法被称作 “对称密钥加密”。对称密钥加密有时也被称为秘密密钥加密,因为密文的安全取决于密钥能否被保密。
对称密钥算法可以进一步分为块加密(block ciphers)和流加密(stream ciphers)。块加密是一次加密成块的数据,一般是 64 位(8 字节)的文本。而流加密则加密位 “流” —— 理论上讲增量是一个位,但实现时通常每次作用于明文的一个字节 —— 将连续生成的 “密钥流” 与明文相组合。
块加密有以下几种方式:
- 电子密码本(Electronic Code Book,ECB): 在 ECB 模式中,每块明文都是独立于其他块加密的。虽然这样做比较高效(可以并行执行多个数据块的加密),但这种方法有一个很大的问题。例如,在 ECB 模式中,对相同明文块的加密总是产生相同的密文块,这为某些类型的密码分析攻击打开了方便之门。ECB 方式通常被认为不适合保护敏感数据。
- 密码块链接(Cipher Block Chaining,CBC): 在 CBC 模式中,文本块是连续加密的,在加密当前明文块之前,用前一次块加密的结果修改当前明文块。这个过程改进了加密的一些特征(例如,相同的明文块不会产生相同的密文块),但是由于其加密过程是连续的,CBC 方式不支持加密的并行化。CBC 方式使用一个称作初始化向量(Initialization Vector,IV)的附加文本来开始链接过程。IV 用于修改被加密的第一个明文块。
- 密码反馈(Cipher Feedback,CFB): 在 CFB 模式中,先加密前一个块,然后将得到的结果与明文相结合产生当前块,从而有效地改变用于加密当前块的密钥。这里密钥的值是不断变化的,这个过程与流加密类似,但是性能则远不如流加密。与 CBC 方式一样,这里要使用一个初始化向量作为加密过程的种子。
- 输出反馈(Output Feedback,OFB): 在 OFB 方式中,使用一个种子或 IV 来开始加密过程。加密种子后,将加密结果与明文块结合产生密文。之后被加密的种子再度被加密,如此重复此过程,直到遍及全部明文。同样,结果类似于流加密。
公共密钥加密
在公共密钥加密,也称非对称密钥加密中,加密和解密过程要用到两个密钥:一个用于加密数据的 “公(public)” 钥和一个用于解密数据的 “私” 钥。任何需要将数据安全地发送给私钥持有者的人首先获得公钥。由于只有通过私钥才能解密密文,因此用于加密的密钥通常不需要保密。这比起对称密钥加密来有一个很大的优点,那就是消息的发送方不需要与相应的接收方交换需保密的密钥。只有消息的接收方需要持有一个保密的密钥。
公共密钥加密的主要缺点是速度。公共密钥算法与对称密钥算法相比非常慢,所以对于需要考虑响应时间的应用程序,采用公共密钥算法是不实际的。因此,用于保护传输中的数据的加密应用程序,例如安全套接字层(Secure Sockets Layer)协议常常结合使用公共密钥算法和对称密钥算法。发送方和接收方使用公共密钥算法进行协商,并交换双方都可以接受的保密的密钥。然后使用这个密钥加上对称密钥算法在双方之间传输消息。对于保护静态数据的应用程序,公共密钥算法与对称密钥算法相比没有优势,因为解密密钥需要保密,这与对称密钥算法一样。通常检索数据的能力与存储数据的能力一样重要,因此在保护静态数据时通常需要用到保密的密钥。如果被加密的数据范围相对比较小的话,公共密钥算法也比较容易受到选择明文攻击。
例如,假设大学的分数是用公共密钥算法加密的。分数有以下几种常见的值:A、B、C、D 和 F。由于加密密钥是公开的,攻击者可以用已知的加密密钥加密这 5 个值,并建立一个查找表,其中存放相应的密文,这样不必真正解密这些密文就可以读出任何人的分数。将类似的技术应用于信用卡号或社会保险号也不会困难多少 —— 只不过是多花点时间,采用更大的查找表而已。因此,一般采用对称密钥算法来保证静态数据的安全。
保障传输中的数据的安全
随着基于 Internet 的应用程序的增多,使用加密来保护传输中的数据已经变得相当普遍。客户期望通过安全的通信在网络上传输信用卡号、银行帐号和其他敏感信息。
最常用于保证 Internet 上通信安全的协议是安全套接字层(Secure Sockets Layer,SSL)协议,该协议最初是由 Netscape 开发的,之后被软件开发人员广泛采用。SSL 使用一个公共密钥基础设施来协商出一个双方都能接受的对称密钥加密,并在通信两端之间交换双方同意的加密密钥。然后,双方同意的加密算法使用这些密钥来加密双方之间传输的数据,从而为安全通信建立了一个通道。
U2 数据库为它们的很多应用程序编程接口(API)和通信协议实现了 SSL 支持。U2 对 SSL 的支持是基于由 OpenSSL 项目开发的一套库的。UniData 6.1 和 UniVerse 10.1 在以下方面提供了受 SSL 保障的通信支持:
- UniObjects for Java (UOJ): UOJ 是 Java 开发人员使用的面向记录的编程工具箱。通过配置 UOJ 可以使其支持 Java 客户机程序与 U2 服务器之间由 SSL 保障的连接。
- JDBC: JDBC 是 Java 应用程序使用结构化查询语言(SQL)访问 U2 时所使用的面向记录集的接口。
- CallHTTP: CallHTTP 是 BASIC 应用程序通过标准超文本传输协议(HTTP)与 Web 服务器交互时使用的接口。
- Socket(套接字): U2 套接字接口是使用 TCP/IP 套接字协议开发应用程序时所使用的低级 BASIC API。CallHTTP API 建立在套接字接口之上。
- Telnet: U2 SSL telnet 服务提供到 U2 服务器的安全 telnet 连接。到这个实用程序的连接需要一个知道 SSL 的 telnet 客户机,例如当前版本(6.0 或更高版本)的 IBM wIntegrate® 终端仿真产品。IBM SBClient™ 终端仿真客户机将在 5.3.8 版时支持 SSL secure telnet。
UniData 7.1 扩展了客户机 SSL 支持,从而包括 ODBC、OLE DB 和 UniObjects。对这些接口的 SSL 支持将被添加到 UniVerse 的未来版本中。
保障静态数据的安全
采用加密方法保障静态数据安全的做法目前相对来说仍不是很常见。此外,将加密应用于静态数据的技术差别较大,主要差别在于算法的选择和实现加密的位置和方式。
目前使用的算法范围很广,有低级的、容易出问题的算法,如 ROT13(这是一种移位加密算法,通过将每个字母字符加 13 来打乱数据),也有业界标准算法,如 DES (Data Encryption Standard) 和 AES (Advanced Encryption Standard)。这些算法可能被应用到计算机系统中的不同层次上:
- 硬件: 最近几年,用于保障数据安全的基于硬件的加密选项已迅速变得更加流行。使用外部存储系统的服务器,例如 Network Attached Storage 或 Storage Area Networks,就可以选择安装加密器件,这种加密器件能透明地加密和解密出入存储器的数据。其中一些设备据说还能作用于 Direct Attached Storage(例如 RAID 阵列)。Decru、NeoScale 和 Vormetric 等公司都能提供这些器件,它们实现了非常快的加密 —— 通常被声称速度达到或接近 “线速”。它们还常常包括高级的密钥管理设施,除了用于处理一般的数据加密外,还可用于控制密钥的创建和分发、密钥的循环和密钥的销毁。
当然,硬件加密也存在不足之处。主要的缺点是实现基于硬件的加密成本较高。目前加密器件的价格达数万美元,还不包括安装和培训,所以对于较小的公司来说没有吸引力。
- 操作系统: 很多操作系统现在都支持加密文件系统。例如 Microsoft 在 Windows 2000 操作系统中引入了 Windows Encrypting File System (EFS)。Linux 和 UNIX 系统有很多可选择的加密文件系统,包括来自意大利 Salerno 大学的 Cryptographic File System 和 Transparent Cryptographic File System (TCFS),以及来自 Stony Brook 大学的 NCryptfs。经过配置后,这些文件系统透明地基于在用户级分配和维护的密钥来加密和解密存储在它们上面的文件。由于这些文件系统会加密传进来的任何东西,并解密从中读出的任何东西,包括所有内部文件结构和被请求的数据,因此应用程序的性能是一个大问题。
- 数据库: 很多数据库制造商都随数据库引擎提供了加密函数。例如,IBM DB2® Universal Database™ 包括一个用于加密或解密嵌入在 SQL
SELECT、INSERT 和 UPDATE 语句中的数据的标量函数,使得开发人员可以将加密构建在他们的应用程序当中。类似地,Oracle 提供了 DBMS_OBFUSCATION_TOOLKIT,这是一个 PL/SQL 包,开发人员通过它可以使用各种不同的加密算法,并且从 Oracle 10g 开始,Oracle 还提供 DBMS_CRYPTO 工具箱,这是一个经过更新和增强的加密包。Microsoft SQL Server 2005 包括一些 Transact SQL 函数,这些函数可用于将加密添加到应用程序中。除了本地数据库函数外,各大第三方软件公司还推出了支持数据库级加密的插件实用程序。
- 应用程序: 也许最常见的将加密应用于静态数据的一层是应用程序调用适当的加密函数。这些加密函数可能是开发工具箱附带的库函数,也可能是从第三方供应商那里购买的插件库。通过在应用程序层实现加密,开发人员可以指定加密哪些字段,从而减少靠加密保障数据安全时所产生的性能影响。
UniData 和 UniVerse 在数据库/应用程序级提供了加密服务。通过一个 BASIC 函数 ENCRYPT,开发人员可以使用密码学中任意强大的对象密钥加密算法加密和解密数据。ENCRYPT 支持直接指定密钥,或者根据用户提供的密码短语生成密钥。被加密的数据或者以二进制字符串的形式返回,或者以 Base64 编码的字符串返回,后者对于确保加密的字符串不包含系统定界字符很有用(在本文后面会更详细地讨论这个话题)。
ENCRYPT 调用 OpenSSL 加密库。当前嵌入式版本的 OpenSSL (0.9.6e) 支持的算法包括:
- Blowfish: Blowfish 是由 Bruce Schneier 创造的一种块加密算法,Bruce Schneier 是一名计算机安全顾问,同时也是标准参考 Applied Cryptography 的作者。Blowfish 是 OpenSSL 支持的最快的块加密算法。虽然 Blowfish 加密支持最长 448 位的密钥,但 OpenSSL 只为 Blowfish 实现了 128 位的密钥和 64 位的块大小。
- CAST: CAST 是由 Carlisle Adams 和 Stafford Tavares 创造的一种块加密算法。这种加密算法支持可变长度的密钥,但是 OpenSSL 为 CAST 实现的密钥长度限制在 128 位。CAST 也许是当前版本的 PGP 电子邮件安全程序中已知的最好的默认对称密钥算法。CAST 的专利由 Entrust Technologies 所有,但是 Entrust 允许他人将它用于商业或非商业用途,而不必交专利使用费。
- DES: DES,即数据加密标准,可能是世界上最常用的对称密钥加密算法。但是与其他算法相比,它显得比较慢,并且只支持 56 位密钥(实际上是 64 位的密钥,但是要每个字节减去一个 “奇偶” 位)。由于这些原因,DES 常常被更新的算法,例如 3DES 或 AES 替代。
- DESX: DESX (扩展的 DES)是由加密安全公司 RSA Security 在改进标准 DES 算法的基础上创造的,由于该算法支持更长的密钥,因而比标准 DES 算法更能抵抗恶意攻击。与 OpenSSL 支持的其他块加密算法不同,DESX 只有 CBC 一种方式。
- 3DES: Triple DES (常简称为 3DES 或 DES3)使用与 DES 相同的算法,但是通过采用更长的多达 192 位(除去每个字节的 1 个 “奇偶” 位,实际有效长度为 168 位),并重复调用 DES 算法,增强了算法的安全性。192 位的密钥被分成 3 个 64/56 位的密钥,明文首先以第一个密钥加密,接着以第二个密钥 “解密”,然后再以第三个密钥进行加密,如此经历三次 DES 加密。假设没有子密钥是相同的,那么其效果就等于用标准 DES 算法加密三次。或者,用户也可以提供一个两倍长度的密钥(128 位,有效长度 112 位),该密钥被分成两个 DES 密钥;之后,数据首先以第一个密钥加密,接着以第二个密钥解密,然后再次以第一个密钥加密。3DES 被认为是非常安全的,但是也很慢(显然所花的时间大约是 DES 算法本身的三倍,而 DES 就已经被认为是一种较慢的算法了)。
- IDEA: IDEA (International Data Encryption Algorithm) 是嵌入在最初版本的 PGP 中的对称块加密算法。Schneier 强烈支持 IDEA,称它是 “当前可用的最好、最安全的块加密算法”(Applied Cryptography, p. 319),但是应该注意,他的评语是在该算法与 Advanced Encryption Standard 算法相竞争并且后者被采纳之前作出的。IDEA 使用 128 位的密钥和 64 位的块大小。IDEA 是在美国、欧洲和日本受专利保护的算法,将它用于商业或非商业用途时需要得到许可。(IDEA 可以免费用于非商业应用,例如共享软件,但是仍然需要许可。)在使用 IDEA 之前,开发人员应该与专利所有者 MediaCrypt 进行核对,了解关于许可和专利限制的信息。
- RC2: RC2 ("RC" 代表 "Rivest Cipher" 或 "Ron's Cipher",它是根据其设计者 Ronald Rivest of MIT 和 RSA Security 命名的)是一种块加密算法,支持长达 128 位的密钥。在 OpenSSL 中,RC2 支持 128 位、64 位或 40 位的密钥(CBC 方式下只支持 64 位和 40 位密钥)。IBM DB2 标量加密和解密函数使用 RC2 作为加密算法。
- RC4: RC4 是由 RSA Security 创造的流加密算法。它支持长达 128 位的密钥。在 OpenSSL 中,RC4 可以用 128、64 或 40 位的密钥来调用。流加密算法作用于位流,而不是数据块,只能以一种方式调用 RC4。
- RC5: RC5 是由 RSA Security 创造的另一种块加密算法。虽然其密钥长度是可变的,但 OpenSSL 在 RC5 的实现中使用 128 位密钥。RC5 是受专利保护的算法。开发人员应该与 RSA Security 联系,了解关于获得 RC5 或其他由 RSA 开发的算法的许可的信息。
所有块加密算法(除了前面提到的 DESX、RC2-64 和 RC2-40 外)都支持 ECB、CBC、CFB 和 OFB 方式。注意,当前的 U2 文档只引用了 DES、3DES、RC2、RC4 和 RC5。关于其他算法的详细信息,请参阅 www.openssl.org 网站上的 OpenSSL 文档或由 Viega、Messier 和 Chandra 撰写的参考文献 Network Security with OpenSSL(见 参考资料。)
在 UniData 7.1 版本中,嵌入在 UniData 中的 OpenSSL 库被升级至 OpenSSL, Version 0.9.7。这次的升级添加了对 AES (Advanced Encryption Standard) 对称密钥加密算法的支持,可以通过 ENCRYPT. AES 来访问,该算法也称 Rijndael (其发音常常类似于 "rhine doll")算法,以它的开发者 Joan Daemen 和 Vincent Rijmen 命名,它正迅速成为用于开发新应用程序的最流行的对称密钥加密算法。AES/Rijndael 算法已经被美国国家标准技术院采纳为联邦信息处理标准(Federal Information Processing Standard, FIPS 197)。OpenSSL 0.9.7 只支持 ECB 和 CBC 方式下的 AES,密钥长度为 128、192 或 256 位。AES 中的块大小与密钥长度匹配(换句话说,如果用 256 位密钥调用 AES,则加密块大小也被设为 256 位)。
ENCRYPT 函数
ENCRYPT 函数的格式是:
ENCRYPT(Algorithm, Action, Data, DataLoc, Key, KeyLoc, KeyAction, Salt, IV, Result, ResultLoc)
函数参数的定义如表 1 所示:
表 1. ENCRYPT 函数的参数
| 参数 | 输入/输出 | 描述 |
|---|
| Algorithm | 输入 | 用于表明采用哪种加密算法的一个字符串 | | Action | 输入 | 1 - 加密 2 - 加密,Base64 编码 3 - 解密 4 - Base64 解码,然后解密 | | Data | 输入 | 或者为要处理的数据,或者为要处理的文件的名称 | | DataLoc | 输入 | 1 - 作为字符串提供的数据 2 - 作为文件名提供的数据 | | Key | 输入 | 实际的密钥或密码短语,或者一个包含密钥或密码短语的文件的文件名 | | KeyLoc | 输入 | 1 - 以字符串形式提供的密钥 2 - 以文件名形式提供的密钥 | | KeyAction | 输入 | 1 - 使用提供的密钥 2 - 根据密码短语得到密钥 | | Salt | 输入 | 包含 salt 值的字符串 | | IV | 输入 | 包含 IV 值的字符串 | | Result | 输出 | 结果数据或存储结果的文件的文件名 | | ResultLoc | 输入 | 1 - 返回字符串形式的结果 2 - 将结果返回到文件 |
用于指定不同加密算法的字符串在产品文档中有描述。这些字符串不是大小写敏感的。任何块加密算法的默认方式是 Cipher Block Chaining (CBC)。
Base64 编码是一种将二进制数据映射到一个可印刷字符集上的技术。Base64 编码使用由 ASCII 中 65 个字符组成的一个子集,包括大小写字母、数字和一些标点字符。Base64 encode/decode 选项对于防止意外生成的系统定界字符很有用。由于从 ENCRYPT 函数返回的字符串可能包含二进制字符,所以可能返回包含系统定界字符的密文,而这个定界字符之前是不存在的。如果使用该函数来加密一个记录中间的一个字段,那么 “意外” 插入的字段标记会打乱字段计数,之后就不可能一致地检索跟在错误后面的那些字段。但是可以使用其他方法来避免出现这种错误(例如将密文转换成 ASCII 十六进制表示形式),Base64 encode 选项是避免这种问题的既容易又有效的方法。
使用 Base64 编码时要注意的是,被编码的字符串返回时可能在后面带有换行字符,如果返回的字符串长度超过 65 字节,那么每过 65 字节就要插入一个换行字符。这些换行字符会影响到被加密数据的存储和显示。开发人员可能需要去掉换行字符,或者用 Base64 字符集以外的字符代替换行字符。在解码和解密数据之前,应该将换行字符放回密文中,以避免出现错误。
对提供给函数的字符串或文件,都可以执行加密和解密。文件选项很可能只适合一些专门的应用领域,在此情况下,整个数据文件将被发送到另一个位置,加密一个 U2 文件实际上将使得它无法从数据库访问,因为加密会打乱他的内部结构。因此,建议设置 DataLoc 和 ResultLoc 选项,以处理和返回字符串,而不是文件。
Salt 是一个可选参数,用于防止某些类型的密码分析攻击。如果不指定 Salt,那么该函数将在内部生成一个。如果指定 Salt,那么它必须是十六进制格式的。
IV(初始化向量)用于初始化某些块加密方式,对于这些方式,如果提供了实际的密钥的话,那么可能需要 IV。如果密钥是通过一个密码短语得到的,那么可以自动生成 IV。和 Salt 一样,IV 必须以十六进制格式来指定。
生成适当的密钥是与加密相关的一个更棘手的问题。生成的密钥应该是随机的二进制字符串,以使它们难于被记住。因此,更常见的做法是由应用程序向 ENCRYPT 函数提供一个密码短语,由该函数在内部生成实际的密码密钥。密码短语是由单词组成的句子或字符串,加密函数通过一个叫做 “密钥碾压(key crunching)” 的过程将密码短语转换成适当的密钥。密码短语的优点是用户不必记住像 "e6cl43985ae90a9b" 这样难记的加密密钥,而只需记住像
My name is Ozymandias, King of Kings: Look on my works, ye Mighty, and despair
这样的密码短语,后者要易记得多。这个摘自 Schneier 的 Advanced Cryptography 的例子使用雪莱的 “奥西曼迭斯” 中的两行诗作为密码短语。正如 Schneier 所说的,这个短语不大适合作为密码短语,因为雪莱的全部作品在网上都能找得到,因而可能受到对密钥的字典攻击。
下面是一个示例代码片段,这段代码用于加密和编码一个测试字符串(注意,这个例子中的密码短语显然不够强,不足以提供充分的安全保证):
清单 1. 调用 ENCRYPT 函数
Plaintext = "THIS IS PLAINTEXT" ;* Source to encrypt.
Algorithm = "DES" ;* Use DES CBC algorithm.
Action = 2 ;* Encrypt, then encode.
DataLoc = 1 ;* Data in string.
Key = "THIS IS A PASSPHRASE" ;* Key (as pass phrase).
KeyLoc = 1 ;* Key in string.
KeyAction = 2 ;* Derive key from pass phrase.
Salt = '' ;* Default Salt.
IV = '' ;* Default IV.
Result = '' ;* Initialize Result.
ResultLoc = 1 ;* Return as string.
ReturnCode = ENCRYPT(Algorithm,Action,Plaintext,DataLoc,Key,KeyLoc,KeyAction,
Salt,IV,Result,ResultLoc)
|
如果该函数调用成功,那么函数返回的值(在这个例子中是通过变量 ReturnCode)将为 0。如果返回结果不为 0,则表明在加密或解密过程中出现了错误。关于 ENCRYPT 函数的文档中列有错误代码。
在 U2 应用程序中实现加密
由于在相应的手册中完整地描述了如何将 SSL 应用于受支持的 U2 接口,因此这里不作详述。但是,本文对有关实现对称密钥加密来保护静态数据的一些值得讨论的问题进行了讨论。
什么东西应该加密?
在数据库应用程序中增加加密或多或少要降低性能。每次数据在被写入磁盘之前要进行加密,从磁盘中读出之前又要进行解密。注意,当一个选择子句引用被加密的字段时,需要加密或解密的还包括 SELECT 或 LIST 语句。因此建议只加密需要特别保护的数据。例如,只加密客户的信用卡信息,而公司名称、地址、联系人姓名等则不加密,这样也许就足够了。
被加密数据还常常会增加存储需求 —— 这也是要限制所加密数据量的另一个原因。由于块加密每次加密数个字节的数据,因此被加密的二进制字符串通常比源字符串最多要长一个块的长度。Base64 编码将明显增加这方面的开销,粗略估计,被加密和编码的数据在存储需求方面要增加 33%。所以在加密已经接近最大文件大小的文件中的数据时,要特别小心。
使加密对应用程序 “透明”
一般没有必要从 BASIC 程序中访问加密数据,而应该通过查询语言(UniQuery、RetrieVe、SQL)和基于 SQL 的 API(ODBC、OLE DB、JDBC)访问加密数据。因此,在实现加密时,应保证从应用程序获得的数据必要时将被解密。
解决这个问题的最直接的办法就是将加密/解密过程编写成子程序,以便在 BASIC 或字典记录(dictionary record)中进行调用。IBM U2 技术支持小组的 Joel Yates 推荐了一种特别优雅的做法,那就是使用一个称作 “用户出口(user exit)” 的结构来实现加密/解密例程。UniData 和 UniVerse 中包括了一些用户出口,以提供与更旧的 Pick 应用程序的向后兼容性。这种技术的漂亮之处就在于,加密/解密子程序实际上是在前面提到的一些实用程序(BASIC、UniQuery、RetrieVe 或 SQL)中被引用的,这种方式实际上和变换码是一样的。于是,调用加密/解密例程就变得像在内部格式和外部格式之间变换数据一样简单。
例如,假设加密/解密例程被编写成用户出口 UEC00 (用户出口的名称总是以 "U" 开头,后面跟上 4 位十六进制数字)。假设被编写成由 "input" 变换处理加密,由 "output" 变换处理解密,那么数据(在这个例子中是社会保险号)将由如下所示的语句进行加密:
SSN = ICONV(SSN,'UEC00') ;* Encrypt SSN。
在 BASIC 中,数据的解密就是通过 OCONV 函数调用用户出口:
SSN = OCONV(SSN,'UEC00') ;* Decrypt SSN.
为了使用 UniQuery、RetrieVe 或 SQL 将加密的数据显示为明文,需要一个字典记录,由字典记录将用户出口作为变换码来调用(在这个例子中,假设 SSN 是字段 5):
清单 2. 引用用户出口的字段记录
SSN
0001 D
0002 5
0003 UEC00
0004 Social Security Number
0005 11L
0006 S
|
对于不需要基于角色的访问控制,并且只实现一个加密密钥的简单应用程序,那么可以将一个用户出口用于所有加密和解密函数。而更高级的应用程序可能需要多个用户出口来实现不同的函数。
使用 SQL 或基于 SQL 的 API 更新 U2 数据库中的数据的应用程序将需要采用一种不同的技术来加密数据。由于 U2 SQL 依赖于字典记录来确定在列级上什么数据是可访问的,因此用 SQL 更新 U2 数据时,需要字典引用一个 “实际”(而不是 “虚”)字段。虚字段,例如引用 BASIC 子程序的字段,是不能使用 SQL 来更新的,因为数据库不能执行检索过程的反向工程。一个可行的办法是使用一个文件触发器来加密数据(不管数据如何被写到磁盘,都自动施加加密),并使用一个用户出口来解密数据。特别注意:不要在加密/解密子程序中将加密密钥 “硬编码” 成文字,因为可以看到源代码或目标代码的人很容易重新覆盖它。
在 Using UniData (UniData) 和 Guide for Pick Users (UniVerse) 手册中可以找到关于如何编写和调用用户出口的文档。
加密字段上的功能限制
加密数据可能影响对数据的处理。例如,在加密字段上建索引通常不可取。根据索引建立方式的不同,索引中可能包含字段的明文值,也可能包含密文值。显然,如果索引包含明文值,那么数据的安全就要受到危害。(如果 SSN 在索引中被存为明文,那么有什么理由加密雇员文件中的 SSN 呢?)另一方面,如果索引存储加密的值,那么这种索引使用起来就要困难得多,因为应用程序不得不使用加密的值来查询索引。B-树中求下一个值/前一个值的功能也将丢失,因为索引排序要基于密文值,而不是明文值。
同样,加密键字段也不可取。如果这样做的话,SELECT 处理将受影响,转换处理肯定也要受影响。如果加密较长的键,则可能超出长度限制。如果应用程序中某个键字段包含敏感数据(例如 SSN),那么最好重新设计文件,将此数据存储在记录中的加密字段中,并为这个键使用另一个值。
第三个有问题的地方是部分匹配搜索(例如 SELECT EMPLOYEE WITH NAME LIKE SM... 之类的命令)。在加密字符串上无法执行部分匹配搜索。在完全值匹配情况下,在 SELECT 语句中所搜索的值可以是被加密的值,而部分匹配则不同,我们无法加密一个部分匹配的字符串。使用值 "SMITH"、"SMYTH" 和 "SM" 将返回三种迥然不同的被加密的结果。
选择算法
在选择对称密钥算法时,最关心的问题就是安全性。加密算法所提供的保护应该适合于使用它的应用程序。如果某个加密算法没有大的设计缺陷,那么密钥长度就是安全性的决定因素。通常,较长的密钥比较短的密钥更安全(换句话说,更能抵抗攻击)。但是,不是说只需选择支持最长密钥的算法 —— 一个特定的应用程序可能不需要最高级别的安全性。但是,在选择所使用的加密算法时,还是应该考虑密钥长度。
很多政府规定使用较强的加密算法。例如,美国商务部工业安全局(Bureau of Industry and Security,BIS)必须审批出口到国外的软件中是否有较强的加密函数。这意味着只有某些算法能合法使用,或者必须限制密钥长度。在选择一种算法之前,应检查该算法的使用在软件安装地的所有司法中是否合法。
OpenSSL 库所支持的某些算法是受专利保护的,使用时可能需要获得许可。例如,在美国、日本和大多数欧洲国家,将 IDEA 算法用于商业或非商业目的时都需要得到许可。RSA Security 的算法通常或者是受专利保护的,或者被当作公司的商业机密,所以建议开发人员在使用 RC2、RC4 或 RC5is 之前与 RSA 联系。可取的做法是,在将任何加密算法放入到应用程序中之前都检查许可问题。
如果要与其他应用程序交换被加密的数据,那么兼容性可能是一个问题。例如,遗留应用程序常常采用标准 DES,这限制了必须与遗留系统交互数据的新应用程序的选择余地。客户、供应商或政府官员可能会要求只使用某些特定的算法、加密方式或密钥长度。
某些应用程序可能关心算法的速度。如前所述,DES 被认为是一种较慢的算法,而 3DES 则更慢。但是,由于大多数数据库应用程序一般只加密相当少的数据,因此在选择算法时算法的原始性能不是很重要的因素。通过测试不同的候选算法,有助于决定是否需要考虑性能。Schneier 在他的 Applied Cryptography 中提供了一个表,其中展示了不同的块加密算法的相对加密速度。在 OpenSSL 可执行文件中还内建了一个基准命令,该命令可用于测试不同加密算法的相对性能。
密钥管理
攻击者知道,侵入计算机系统的最简单的方式不是 “破解” 密码或访问码。最简单的方式是窃取它们 —— 例如从贴在一台终端上或桌子抽屉里的即时贴中获得,或者从某人那里骗取。
同样,危害现代加密的安全的最简单的方法是窃取密钥。如果使用得当 —— 使用足够长的密钥和不会泄漏关于明文的信息的加密方式 —— 大多数现代算法在密码分析攻击面向都有一定的安全性。因此,大多数攻击都是试图发现密钥。攻击者一旦获得密钥,即使不知道加密算法是什么,也可以在一个样本密文上依次尝试每种可能使用的算法,从而判断用于加密明文的组合是什么。
“密钥管理” 是一个术语,包括与生成和保护密钥相关的各种操作。具体来说,密钥管理涉及到生成适当的密钥、将密钥安全地分发给用户、密钥的周期性循环和对过期密钥的销毁。密钥管理实际上要困难得多,因此与选择所使用的算法相比,密钥管理更为重要。考虑一个这样的系统,所有信息是由数据库透明地加密或解密的。能访问系统整个备份的攻击者可以恢复备份,激活数据库,并立即获得对所有加密数据的全部访问权,而不必真正发现密钥或算法。
但是对密钥管理的全面讨论超出了本文的范围,所以这里只是考察一些必须关注的问题:
- 密钥生成: 就像不能使用您的名字作为密码一样,好的密钥(或密码短语)应该难于猜出。实际上,真正的密钥应该是随机位串,以保证攻击者不能靠有限范围的可能出现的密钥来实施暴力破解或字典攻击。密码短语不仅应该难于猜出,而且还应该很长。Schneier 建议一般为每 4 个字节的密钥使用 5 个英文单词,也就是说,为了生成用于 3DES 的 192 位密钥,需要一个包含大约 30 个单词的短语。
- 密钥分发: 密钥必须以一种安全的方式分发给用户。不要将密钥写在机房中的一张纸上,更不要将这张纸贴在系统管理员所在房间的墙上。这样做等同于前面提到的即时贴问题,同样糟糕的做法是将密钥存放在系统上一个文件中,而文件名又是类似于 KEYFILE 之类的东西。Yates 建议,U2 开发人员需要让用户在登录时输入密钥,然后将这些密钥装载到一个有名称的
COMMON 块中,这样密钥就不会存入磁盘。或者,使用一个密钥层次结构来保护存储在磁盘上的密钥。在最简单的实现中,使用一个主(master)密钥来保护加密和解密时实际使用的密钥,即工作密钥。攻击者即使获得包含工作密钥的文件,也不能使用工作密钥来解密密文,因为这些密钥本身是由主密钥加密过的。
- 密钥循环: 密钥应该周期性地更改。一个密钥使用的时间越长,就越有可能受到危害。注意,更改加密密钥时可能需要一个有效的维护窗口。所有已经被加密的数据需要用旧的密钥进行解密,然后用新的密钥加密。如果分阶段来做这件事,那么程序需要通过某种途径来知道一个特定记录中的数据是否已经被转换成新的密钥,还是没有转换。
- 密钥的销毁: 不再使用的密钥应该以一种安全的方式进行销毁。一个明显的原因是,攻击者如果获得用旧密钥加密的数据(例如通过窃取旧的备份磁带),就可能用被丢弃的密钥来解密该数据。还应考虑到这个问题的反面 —— 如果遗忘了旧的密钥,而且它们已经被销毁,那么就不能取回备份磁带或历史磁带上的加密数据。
现在您应该清楚了,恰当的密钥管理规程应该成为任何加密实现的核心设计部分。开发人员在实现企业加密计划时,设计小组中需要包括计算机安全专家。
结束语
加密不能彻底解决数据安全问题。但是,加密作为一种很有价值的工具,可以成为一个完整的数据安全解决方案中的一部分。IBM 最早的扩展关系数据库 UniData 和 UniVerse 在本地数据库功能中包括一些强大的加密工具,使得开发人员可以将健壮的数据加密构建在他们的 U2 应用程序中。
参考资料 学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
-
Fred Piper 和 Sean Murphy 撰写的 Cryptography: A Very Short Introduction (Oxford University Press, 2002):对现代密码术和加密原理作了简明扼要的介绍。
-
Bruce Schneier 的 Applied Cryptography(John Wiley 和 Sons, 1996):应用程序开发人员使用的关于密码术的标准参数。Schneier 的论文 “Why Cryptography Is Harder Than It Looks” 对实现加密解决方案的困难之处进行了有趣的讨论。
-
OpenSSL.org:OpenSSL 项目的主页。开发人员可以找到与 OpenSSL 相关的新闻和文档,还可以得到 OpenSSL 邮件列表。
-
John Viega、Matt Messier 和 Pravir Chandra 撰写的 Network Security with OpenSSL (O'Reilly, 2002):关于 OpenSSL 包的很好的参考资料。
-
美国政府计算机安全中心提供了关于 Advanced Encryption Standard 算法的信息,包括到 FIPS 197 标准文档的链接。
-
美国商务部 工业安全局 可以提供关于在软件中使用加密的法律方面的信息。
-
developerWorks 中国网站 DB2 专区: 发现更多为 DB2 UDB 开发人员和管理员准备的参考资料。
获得产品和技术
讨论
关于作者  | |  | Bill Winter 在 IBM 技术销售部工作,负责为 U2 ISV 和终端用户客户提供支持。他毕业于菩及海湾大学,现居住在西雅图。 |
对本文的评价
|