Oracle 12c 哈希加密



我想存储用户表密码的哈希数据。所以我想知道用户密码字段的数据类型是什么。如何将数据插入用户密码列并从用户表中从验证用户检索。

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.Hashpassword
生成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

最新更新