由于之前设计不合理的结构,我必须使用的当前数据库将用户的密码存储为文本。
现在,我正在构建一个必须使用这些密码的前端部分,我当然不希望发送未加密的密码。
我的想法是编写一个Oracle函数来加密和解密文本密码,并在存储过程中使用这些函数来返回加密数据。
Oracle最好的方法是什么?
答案 0 :(得分:7)
如果您想编写自己的函数来加密和解密数据,您只需要使用适当的参数调用DBMS_CRYPTO encrypt
和decrypt
方法(即选择加密算法) ,你的钥匙等。)。
当然,如果您编写自己的例程,假设您将密钥存储在数据库中或数据库可以访问的某个位置,那么您的安全性并不高。通过网络发送未加密的密码是不好的,但在数据库中存储未加密的密码通常要糟糕得多(如果数据库中有decrypt
方法可以访问密钥来解密数据,则加密密码) 。从数据库窃取数据通常比通过网络发送数据以查找密码容易得多。
当然,正确的答案是重新架构系统,以便您根本不存储密码。您应该存储不可逆的密码哈希值(您也可以使用DBMS_CRYPTO
包生成)。
答案 1 :(得分:6)
看看DBMS_CRYPTO
它有加密和解密内置数据的方法。比编写自己的方法更好。
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_crypto.htm
答案 2 :(得分:4)
这是使用(DBMS_CRYPTO
)加密密码的打包功能(成功实施) -
CREATE OR REPLACE
PACKAGE BODY encrypt_paswd
AS
G_CHARACTER_SET VARCHAR2(10) := 'AL32UTF8';
G_STRING VARCHAR2(32) := '12345678901234567890123456789012';
G_KEY RAW(250) := utl_i18n.string_to_raw
( data => G_STRING,
dst_charset => G_CHARACTER_SET );
G_ENCRYPTION_TYPE PLS_INTEGER := dbms_crypto.encrypt_aes256
+ dbms_crypto.chain_cbc
+ dbms_crypto.pad_pkcs5;
------------------------------------------------------------------------
--Encrypt a password
--Salt the password
------------------------------------------------------------------------
FUNCTION encrypt_val( p_val IN VARCHAR2 ) RETURN RAW
IS
l_val RAW(32) := UTL_I18N.STRING_TO_RAW( p_val, G_CHARACTER_SET );
l_encrypted RAW(32);
BEGIN
l_val := utl_i18n.string_to_raw
( data => p_val,
dst_charset => G_CHARACTER_SET );
l_encrypted := dbms_crypto.encrypt
( src => l_val,
typ => G_ENCRYPTION_TYPE,
key => G_KEY );
RETURN l_encrypted;
END encrypt_val;
END encrypt_paswd;
这使用encrypt_aes256
- “高级加密标准。分组密码。使用256位密钥大小。” ,chain_cbc
- “密码块链接。明文在加密之前与之前的密文块进行异或。”和pad_pkcs5
- “提供符合PKCS#5:基于密码的加密标准的填充”。
除此之外您还可以创建类似的解密功能。喜欢 -
FUNCTION decrypt_val( p_val IN RAW ) RETURN VARCHAR2
IS
l_decrypted RAW(32);
l_decrypted_string VARCHAR2(32);
l_user VARCHAR2(32);
BEGIN
SELECT user
INTO l_user
FROM dual;
if l_user = 'ADMIN' -- you can restrict usage of decrypt to certain db users only.
then
l_decrypted := dbms_crypto.decrypt
( src => p_val,
typ => G_ENCRYPTION_TYPE,
key => G_KEY );
l_decrypted_string := utl_i18n.raw_to_char
( data => l_decrypted,
src_charset => G_CHARACTER_SET );
RETURN l_decrypted_string;
else
RAISE_APPLICATION_ERROR(-20101, 'You are not authorized to use this function - decrypt_val()');
end if;
RETURN 'Unknown';
END decrypt_val;
您可以考虑使用wrap iname=package_name.pkb
在数据库中编译包之前包装该包,然后编译生成的plb
。
答案 3 :(得分:4)
或者你可以像这样http://mikepargeter.wordpress.com/2012/11/26/pbkdf2-in-oracle/使用密码哈希算法pbkdf2 我使用rfc https://www.ietf.org/rfc/rfc6070.txt验证了结果,它运行正常。
检查此链接以获得最少的迭代次数和key_size:PBKDF2 recommended key size? 请注意,结果是长度的两倍,因为它是十六进制编码的。
我们将这些列存储在db
中PASSWORD_HASH VARCHAR2(512 BYTE),
PASSWORD_SALT VARCHAR2(256 BYTE),
PASSWORD_ITERATIONS NUMBER(10),
PASSWORD_HASH_METHOD VARCHAR2(30 BYTE),
PASSWORD_CHANGED_DT DATE
散列,盐和迭代是为pbkdf2算法提供的 hash_method用于迁移目的 而changed_dt将使密码失效
答案 4 :(得分:0)
用户此代码肯定有效
DELIMITER $$
DROP PROCEDURE IF EXISTS `thread_updates` $$
CREATE PROCEDURE `thread_updates`()
BEGIN
DECLARE my_total INT DEFAULT NULL; -- Declare total
DECLARE my_counter INT DEFAULT 0; -- Declare counter starting at 0
DECLARE my_curr_id INT DEFAULT NULL;
-- DECLARE other vars
DECLARE fixer_cursor CURSOR FOR
SELECT DISTINCT(id)
FROM log
WHERE date >= '2018-01-01';
OPEN fixer_cursor;
SELECT FOUND_ROWS() INTO my_total; -- Get total number of rows
my_fixerloop: LOOP
FETCH fixer_cursor INTO my_curr_id;
IF my_counter >= my_total THEN -- Compare counter to total
CLOSE fixer_cursor;
LEAVE my_fixerloop;
END IF;
SET my_counter = my_counter + 1; -- Increment by one for each record
SELECT data FROM table WHERE id = my_curr_id; -- This may not exist
-- Do other stuff with 'data' or NULL from above
END LOOP;
END $$
DELIMITER ;