Сравнение входящих учетных данных с хешированным паролем Oracle - PullRequest
0 голосов
/ 11 октября 2018

У меня есть база данных Oracle.Я хотел бы зашифровать входящий пароль в C # и сравнить его со значением, хранящимся во встроенной таблице оракула, которая называется sys.user $, а именно в столбце "spare4".

Возможно ли это сделать?Я пытался зашифровать пароль, но он не генерирует тот же вывод, что и значение, сгенерированное в таблице базы данных Oracle, поэтому явно не хватает логики, которую применяет Oracle.Есть идеи?

Из того, что я понимаю, первые 40 символов - это хэшированный пароль, а последние 20 символов - это хэшированное значение соли.

В Oracle 11g и далее он использует соль (не знаю, какOracle генерирует это) и применяет к паролю, а затем хэширует его, используя SHA-1, чтобы сгенерировать часть S: значения spare4 согласно следующим блогам хэши паролей и Советы по запасным 4

Вот текущий код:

    public static string GenerateSaltedSHA1(string plainTextString, int saltSize)
    {
        HashAlgorithm algorithm = new SHA1Managed();
        var saltBytes = GenerateSalt(saltSize);
        var plainTextBytes = Encoding.ASCII.GetBytes(plainTextString);

        var plainTextWithSaltBytes = AppendByteArrays(plainTextBytes, saltBytes);
        var saltedSHA1Bytes = algorithm.ComputeHash((byte[]) plainTextWithSaltBytes);
        var saltedSHA1WithAppendedSaltBytes = AppendByteArrays(saltedSHA1Bytes, saltBytes);

        return Convert.ToBase64String(saltedSHA1WithAppendedSaltBytes);
    }

    private static byte[] GenerateSalt(int saltSize)
    {
        var rng = new RNGCryptoServiceProvider();
        var buff = new byte[saltSize];
        rng.GetBytes(buff);
        return buff;
    }

   private static byte[] AppendByteArrays(byte[] byteArray1, byte[] byteArray2)
    {
        var byteArrayResult =
            new byte[byteArray1.Length + byteArray2.Length];

        for (var i = 0; i < byteArray1.Length; i++)
            byteArrayResult[i] = byteArray1[i];
        for (var i = 0; i < byteArray2.Length; i++)
            byteArrayResult[byteArray1.Length + i] = byteArray2[i];

        return byteArrayResult;
    }

Я понимаю, что в Oracle есть функции в DBMS_CRYPTO, например, хеш, который можно использовать для создания хеша на основе определенного типа, например, MD5, SHA-1 и т. Д. В пароле и т. Д.

Если есть способы получше, тогда я открыт для предложений.

1 Ответ

0 голосов
/ 11 октября 2018

В случае, если мои комментарии были неясны (или не верны), вот небольшая инструкция SQL, которая сделает то, что вы ищете.Это работает на 12c - но не буду клясться, что будет работать со всеми параметрами безопасности.Если у вас есть S: part в sys.user$.spare4, это, вероятно, должно работать.

with trial as 
(SELECT name, 
-- The 1st 20 bytes (40 characters) of the "S" part are the hashed password
substr(substr(spare4,3,60),1,40) hashed_pwd, 
-- The last 10 bytes (20 characters) of the "S" part are the plaintext salt
substr(substr(spare4,3,60),-20) salt, 
-- I want to know if the password for user MYUSERNAME is "MYPASSWORDGUESS"...
'MYPASSWORDGUESS' trial_password
from sys.user$
where name = 'MYUSERNAME' ),
hashit as (
-- This SELECT adds the salt to our trial password and hashes it.
select name, 
       trial_password, 
       hashed_pwd, 
       salt,
       -- The "3" is for the SH1 algorithm
       sys.dbms_crypto.hash(
           utl_raw.cast_to_raw(trial_password) || cast (salt as raw(10) ),3) 
          hashed_salted_trial
from trial )
-- If the resulting hash matches what Oracle has stored in spare4, it is good.
SELECT name, 
       trial_password, 
       case when hashed_pwd = hashed_salted_trial 
           then 'Y' ELSE 'N' END password_match
from hashit
;

Обновите «MYUSERNAME» и «MYPASSWORDGUESS» по мере необходимости для вашей базы данных.

ОБНОВЛЕНИЕ

На основании моего исходного кода в C # естьЕсть ли эквивалентный способ сделать следующее в C #?sys.dbms_crypto.hash (utl_raw.cast_to_raw (trial_password) || cast (соль как raw (10)), 3)

utl_raw.cast_to_raw(trial_password) делает то же самое, что и Encoding.ASCII.GetBytes(plainTextString)в вашем посте.Цель каждого из них состоит в том, чтобы сделать предположение о пароле и преобразовать его в байт.

cast(salt as raw(10)) не имеет эквивалента в вашем сообщении.Подробнее об этом позже.

|| - это способ объединения RAW значений в Oracle.Он служит для той же цели, что и AppendByteArrays в вашем сообщении.

sys.dbms_crypto.hash(..., 3) - это то, как вы генерируете 160-битный хэш SHA-1 в Oracle.Я думаю, это то, что algorithm.ComputeHash делает в вашем посте.

Итак, единственное, чего вам не хватает в вашем коде, это эквивалент cast(salt as raw(10)).

Как мы уже говорили, вы не можетесоздать свою собственную соль для этого.Вы должны использовать соль, закодированную в user$.spare4.Это будут последние 20 символов части «S:» в этом поле.Это выглядит так: FA338B110F78548CCB44.Каждые два символа образуют шестнадцатеричный БАЙТ, который дает вам один байт вашей соли.Итак, в моем примере 1-й байт соли (заданный "FA") равен 15 (для "F") x16 + 10 (для "A") = 250.

Это, надеюсь, логика достаточнодля вас, чтобы реализовать в C #.Однако в этом нет необходимости, поскольку входное значение для соли может поступать только из user$.spare4 в базе данных Oracle.Так как вы все равно решили перейти в Oracle, просто

SELECT cast(substr(substr(spare4,3,60),-20) as RAW) FROM user$

так же просто, как просто

SELECT spare4 FROM user$

и все остальное в C #.Вы также можете позволить Oracle делать то, что у него хорошо получается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...