我想存储用户表密码的哈希数据。所以我想知道用户密码字段的数据类型是什么。如何将数据插入用户密码列并从用户表中从验证用户检索。
SysUsers Table column: (USERID NUMERIC, USERNAME VARCHAR(50), USERPASSWORD [Data_Type]).
Insert: INSERT INTO SYSUSERS(USERID, USERNAME, USERPASSWORD) VALUES(1, 'John', _____)
Retreive Data: SELECT * FROM SYSUSERS WHERE USERNAME = 'John' AND USERPASSWORD = ____
要安全地存储密码,必须满足以下几个条件:
- 存储密码的哈希值,而不是密码本身
- 使用加盐密码防止字典攻击
- 使用慢速哈希函数防止暴力攻击
请参阅安全加盐密码哈希。
此外,我建议使用散列函数和编码,这些散列函数和编码也可以在其他平台上实现,因为有一天,你会想要从 Oracle 迁移,或者你可能希望在应用程序服务器(而不是数据库中(对密码进行散列。
经过验证的密码哈希函数是PBKDF2。甲骨文甚至使用它来存储用户的密码。但是,没有可用的直接实现。
Mike Pargeter在Oracle的PBKDF2中发布了PL/SQL实现:
CREATE OR REPLACE FUNCTION pbkdf2
( p_password IN VARCHAR2
, p_salt IN VARCHAR2
, p_count IN INTEGER
, p_key_length IN INTEGER
)
RETURN VARCHAR2
IS
l_block_count INTEGER;
l_last RAW(32767);
l_xorsum RAW(32767);
l_result RAW(32767);
BEGIN
l_block_count := ceil(p_key_length / 20); -- 20 bytes for SHA1.
FOR i IN 1..l_block_count
LOOP
l_last := utl_raw.concat(utl_raw.cast_to_raw(p_salt), utl_raw.cast_from_binary_integer(i, utl_raw.big_endian));
l_xorsum := NULL;
FOR j IN 1..p_count
LOOP
l_last := dbms_crypto.mac(l_last, dbms_crypto.hmac_sh1, utl_raw.cast_to_raw(p_password));
IF l_xorsum IS NULL
THEN
l_xorsum := l_last;
ELSE
l_xorsum := utl_raw.bit_xor(l_xorsum, l_last);
END IF;
END LOOP;
l_result := utl_raw.concat(l_result, l_xorsum);
END LOOP;
RETURN rawtohex(utl_raw.substr(l_result, 1, p_key_length));
END pbkdf2;
/
请注意,该函数以十六进制编码字符串的形式返回结果。这就是您想要的方式,以便您可以在需要时迁移到另一个系统。
要生成盐,请使用加密随机函数并将其与密码哈希一起存储,以便进行密码验证:
rawtohex(DBMS_CRYPTO.RANDOMBYTES(32))
存储密码的一种方法是使用A one-way hash function
单向哈希函数是在一个中工作的哈希函数 方向。从输入数据计算哈希值很容易,但是 很难生成散列为特定值的数据。 因此,单向哈希函数可以很好地确保数据 正直
您可以为密码列raw datatype
使用DBMS_CRYPTO.Hash
从password
生成raw
值使用UTL_RAW.COMPARE
检查密码字匹配项。
演示
CREATE TABLE UserTable(
usertId NUMBER(10) PRIMARY KEY ,
username NVARCHAR2(50) NOT NULL,
password RAW(500) NOT NULL
);
/
--Create table, executed in 106 ms
INSERT INTO UserTable
SELECT 1, 'John', DBMS_CRYPTO.hash(utl_raw.cast_to_raw('abcd123'), 3)
FROM dual;
--Insert - 1 row(s), executed in 37 ms
SELECT
usertId, username
FROM UserTable
WHERE UTL_RAW.COMPARE(password, DBMS_CRYPTO.hash(utl_raw.cast_to_raw('abcd123'), 3)) = 0;
--USERTID USERNAME
--1 John
SELECT
usertId, username
FROM UserTable
WHERE UTL_RAW.COMPARE(password, DBMS_CRYPTO.hash(utl_raw.cast_to_raw('ABCD123'), 3)) = 0;
--no row selected