【问题标题】:Select DBMS_CRYPTO password hashes in Oracle 11g在 Oracle 11g 中选择 DBMS_CRYPTO 密码哈希
【发布时间】:2012-09-17 19:01:05
【问题描述】:

我目前正在使用 DBMS_CRYPTO.HASH 对我的 Oracle 数据库中的密码字段进行哈希处理。然而,此时,我需要让我的 Java 应用程序能够以类似于 MySQL 的方式验证用户输入的密码。比如:

SELECT *
FROM user_login_table
WHERE password = SHA1('MyPassword');

我目前正在通过以下过程进行散列:

CREATE OR REPLACE PROCEDURE 
  MUNGAI.p_auth_insert_user (
    par_username in varchar2,
    par_password in varchar2,
    par_work in varchar2
  )
IS l_hash raw(2000);
  BEGIN
    l_hash :=
      dbms_crypto.hash(
        utl_i18n.string_to_raw(par_password || par_work || upper(par_username),
        'AL32UTF8'
      ),
      dbms_crypto.hash_sh1
    );

    INSERT INTO user_login_table (user_name, p_word, work_class)
    VALUES (par_username, l_hash, par_work);
  END p_auth_insert_user;
/

然后我执行如下过程,插入到表中:

EXEC MUNGAI.p_auth_insert_user('MUNGAI', 'gatungo', '999')

在我的情况下,有没有更好的方法来实现这一点?我正在使用 Oracle 11g,如果这很重要的话。

【问题讨论】:

标签: java oracle11g password-hash dbms-crypto


【解决方案1】:

我建议您在数据库外部的代码中进行哈希处理。这样,您就可以独立于数据库供应商,并且您只需将散列实现写入一个位置。 DB 列可以是常规的 varchar。

应该是这样的:

  1. 在添加用户/更改密码时,哈希在插入/更新之前为密码提供了正确的算法和盐。我建议至少 SHA-256。把盐也保存在哈希旁边!

  2. 在认证过程中,为用户获取hash和salt,用salt对提供的密码进行hash并与数据库中的hash进行比较。

哈希/加盐的技巧例如在这里:http://crackstation.net/hashing-security.htm

【讨论】:

  • 由于 Oracle 仅支持 SHA-1,因此您必须在外部获取 SHA-256。使用 Oracle 的一种方法是用 Java 编写代码,将其加载到数据库中并将其导出为 Java 存储过程。
【解决方案2】:

假设哈希密码存储在user_login_tableRAW 列中,您可以在SQL 语句中简单地调用dbms_crypto.hash。根据您进行初始哈希的方式(特别是您如何将纯文本密码转换为 RAW 以及您使用的算法和选项),这样的事情会起作用

select * 
  from user_login_table 
 where password = dbms_crypto.hash( utl_i18n.string_to_raw( 'MYPassword', 'AL32UTF8' ),
                                    <<whatever hash algorithm you want to use>> );

当然,作为良好编码实践的一般问题,您几乎肯定希望定义自己的哈希密码函数,以便您可以嵌入如何将字符串转换为RAW 的逻辑并指定哈希算法在一个地方。然后,您将从 SQL 语句中调用该新函数。这就是你可能会添加适当盐的功能。然后,您将使用该函数对表中的散列数据进行初始播种,并在将来验证密码散列。

我还假设您的实际查询除了密码之外还有一个关于 username 的谓词

select * 
  from user_login_table 
 where password = new_function_name( 'MYPassword' )
   and username = 'YourUserName'

否则,您发布的查询只会验证密码是否与数据库中某人的密码匹配,而不是尝试登录的特定人员。此外,如果两个人具有相同的密码哈希,它将返回多行。

因此,在您的具体情况下,我希望您希望创建一个新函数 hash_password

CREATE OR REPLACE function MUNGAI.hash_password(par_username in varchar2,
                              par_password in varchar2,
                              par_work in varchar2
                             )
  return raw
is
  l_hash raw(2000);
begin
  l_hash :=
   dbms_crypto.hash
     (utl_i18n.string_to_raw (par_password || par_work || upper(par_username),
                              'AL32UTF8'
                             ),
      dbms_crypto.hash_sh1
     );
  return l_hash;
end;

然后你会从你的插入过程中调用这个函数

CREATE OR REPLACE procedure MUNGAI.p_auth_insert_user (par_username in varchar2,
                              par_password in varchar2,
                              par_work in varchar2
                             )
is
  l_hash raw(2000);
begin
  l_hash := hash_password( par_username, par_password, par_work );

  insert into user_login_table
    (user_name, p_word, work_class)
   values
    (par_username, l_hash, par_work);
end p_auth_insert_user;
/

您的查询将是

select * 
  from user_login_table 
 where password = new_function_name( username, 
                                     'MYPassword', 
                                     <<whatever `par_work` is supposed to be>> )
   and username = 'YourUserName'

【讨论】:

  • 我想你明白了我的观点请检查我所做的编辑。我没有得到你说的那部分&lt;&lt;whatever hash algorithm you want to use&gt;&gt;
  • @Stanley - 这只是为了替换为您在更新中添加的dbms_crypto.hash_sha1 算法。我使用更新中的代码发布了一个更完整的示例。
猜你喜欢
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2015-11-30
相关资源
最近更新 更多