Programing

비밀번호 로그인에 솔트를 어떻게 구현합니까?

lottogame 2021. 1. 8. 07:47
반응형

비밀번호 로그인에 솔트를 어떻게 구현합니까?


로그인 시스템에 솔트를 구현하고 싶지만 이것이 작동하는 방식에 대해 약간 혼란 스럽습니다. 나는 그 뒤에있는 논리를 이해할 수 없습니다. 나는 md5가 단방향 알고리즘이고 내가 만난 모든 기능이 모든 것을 함께 해시하는 것처럼 보인다는 것을 이해합니다. 이 경우 비교를 위해 어떻게 암호를 되 찾을 수 있습니까? 내 가장 큰 질문은 단순히 암호를 해싱하는 것보다 사용자의 암호를 솔팅하는 것이 더 안전하다는 것입니다. 데이터베이스가 손상 될 경우 솔트와 함께 해시가 데이터베이스에 있습니다. 이것이 해커에게 필요한 전부가 아닙니까?

나는 또한 다른 개발자가 말한 다른 게시물을 발견했습니다.

"솔트와 알고리즘이 데이터베이스 와 별도로 저장되었는지 확인하십시오. "

데이터베이스에 소금을 저장하고 싶습니다. 내가 할 경우 이것이 정말로 문제입니까?

나는 이것이 어떻게 작동하는지 이해하고 모범 사례가 무엇인지 이해하는 데 도움을 찾고 있습니다. 어떤 도움이라도 대단히 감사합니다.


편집 : 나는 모든 사람들의 반응과 아이디어에 감사하고 싶습니다. 지금은 좀 더 혼란 스러울 지 모르지만, 확실히 저에게는 학습 경험이었습니다. 다시 한번 감사드립니다.


해시 함수는 항상 동일한 입력 문자열에 대해 동일한 값을 반환합니다. 내 사용자 (Alice)가 암호를 가지고 있다고 가정 해 보겠습니다 secret. secret사용하여 해싱 md5()하면 다음 해시로 이어집니다.

5ebe2294ecd0e0f08eab7690d2a6ee69

사전 (일반적인 단어 및 비밀번호 목록) 또는 해당 서비스를 제공하는 다양한 사이트 중 하나를 이용하여 공격자 (몰 로리)는 자신의 사전에서 비밀번호가 비밀임을 알면 쉽게 알아낼 수 있습니다 5ebe2294ecd0e0f08eab7690d2a6ee69 = secret.

해싱 전에 솔트 처리하는 과정은 솔트를 모르고 사전 공격을 사용하기 어렵게 만듭니다. 다음을 고려하세요:

<?php
$salt = '@!#%$@#$@SADLkwod,sdaDwqksjaoidjwq@#@!';
$hash = md5($salt . 'secret');

결과 해시는 현재 b58ad809eece17322de5024d79299f8a이지만 Alice의 암호는 여전히 secret입니다. 이제 Mallory가 소금에 절인 해시를 손에 넣으면 사전에서 답을 찾지 못할 가능성이 있습니다. 만약 그렇다면, 사전은 그녀에게 잘못된 답을 줄 것입니다.

데이터베이스에 정적 솔트를 저장하지 마십시오. 응용 프로그램의 구성과 함께 저장하는 것이 좋습니다 (웹에서 사용할 수 없어야 함).

동적 솔트를 사용하려는 경우 데이터베이스를 사용해야합니다. 기존 유효한 데이터의 널이 아닌 열을 사용하여 솔트를 빌드하십시오 (비밀 암호화 키를 기반으로하는 blowfish로 암호화 된 사용자 이름 문자열은 일반적으로 암호화로 안전합니다). 소금에 별도의 컬럼을 사용하지 마십시오. 기존 열을 사용할 수없는 경우 해시와 동일한 열에 솔트를 통합하십시오. 예를 들어 128 비트 솔트에는 처음 32자를 사용하고 160 비트 해시에는 마지막 40자를 사용합니다. 다음 함수는 이러한 해시를 생성합니다.

function seeded_sha1($string, $seed_bits) {
    if(($seed_bits % 8) != 0) {
        throw new Exception('bits must be divisible by 8');
    }

    $salt = '';
    for($i = 0; $i < $seed_bits; $i+=8) {
        $salt .= pack('c', mt_rand());
    }

    $hexsalt = unpack('h*hex', $salt);

    return $hexsalt['hex'] . sha1($salt . $string);
}

function compare_seeded_sha1($plain, $hash) {
    $sha1 = substr($hash, -40);
    $salt = pack('h*', substr($hash, 0, -40));

    $plain_hash = sha1($salt . $plain);
    return ($plain_hash == $sha1);
}

공격자가 SQL 주입을 사용하여 데이터베이스에 침입하는 경우, 적어도 검색 한 해시는 애플리케이션 구성에 액세스 할 수 없기 때문에 유용하지 않습니다. 서버가 루팅되면 무엇을하든 거의 게임 오버입니다.

Note: There are other types of attack possible on md5() which is why you use more secure hashing algorithm, sha1() for example. Or, even better, use the Portable PHP password hashing framework, which has been designed with security in mind and is backwards compatible with pretty much any PHP version.

require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hashed stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

The point of a salt is to prevent attackers from amortizing the cost of a brute force attack across sites (or better yet, when using a different salt for each user: all users of a site) through precomputed rainbow tables.

With plain hashing, an attacker can compute such a table once (a very long, costly operation) and then use it to quickly find passwords for any site. When a site uses one fixed salt, the attacker has to compute a new table specifically for that site. When a site uses a different salt for each user, the attacker can stop bothering with rainbow tables - he'll have to brute-force each single password separately.

Storing the salts separately is not necessary to gain this advantage. In theory it would be even more secure because it would neutralize the weakness of dictionary or short passwords. In practice, it's not worth bothering with because at the end of the day, you need access to the salts somewhere to check passwords. Also, trying to separate them would lead to more complex systems - and the more complex a system is, the more opportunities for security holes there are.

Edit: My concrete recommendations:

  • Generate long pseudorandom salt for each user and store in in the DB
  • Use a bcrypt-based hash
  • ideally, don't implement it yourself, use an existing library instead

Forget about using salts (partly for the reason you mention), use bcrypt instead:

For a good explanation see: http://codahale.com/how-to-safely-store-a-password/


The other answers are good, so I'll just throw in a minor point that nobody else has mentioned. You don't want to use the same salt for every password because then if two people have the same password, they'll have the same hash. That's exposing information that an attacker can exploit.

You could use the same salt for every user along with Juraj's good idea to combine the password with other non-changing database fields (unique to a user). But watch out because this information gets tied to the password. If you were to hash the username + password together to guarantee a unique hash, you wouldn't be able to change the username without creating a new user and requiring them to set a new password.

As an example of having a unique salt per user and storing it alongside the password hash, I'll point out /etc/shadow on your typical Linux system.

root@linux:/root# cat /etc/shadow | grep root
root:$1$oL5TTZxL$RhfGUZSbFwQN6jnX5D.Ck/:12139:0:99999:7:::

Here, the oL5TTZxL is the salt and RhfGUZSbFwQN6jnX5D.Ck/ is the hash. The plain-text password is root in this case, and the hash algorithm my system uses is the MD5-based BSD password algorithm. (newer systems than mine have better hash algorithms)


You don't get the password out for comparison. You encrypt the password when they attempt a login and compare the stored value with the newly encrypted value.


As you mentioned, hashing algorithms work only one-way (or only if they are strong enough :-D)

For your question about salting I would recommend to hash a password with a static salt string and some dynamic data from database, which should not change after once created

This is a very secure way of storing passwords, as even if database is compromised, hackers/crackers still need to get your static string hash and need to guess how you applied all the salting..

For example let's say you have a users table with these columns:

id
username
password
created_at

columns id and created_at after once filled should never be changed..

so when you are hashing user's password you can do as simple as:

<?php
    $staticSalt = '!241@kadl;ap][';
    $userPass = 'my new pass';
    // assuming $user variable is already populated with DB data
    // we will generate new hash from columns and static salt:
    $genPass = sha1($user['id'] . $userPass . $user['created_at'] . $staticSalt);
?>

I hope this one helps :) cheers


Hashing passwords is meant to keep those passwords secret from your own administrator(s).

1) Keeping plain text passwords in your database would be fine except your passwords may be used by the administrator to gain access to some other system.

2) You can use a single global salt, which is combined with the passwords (by prepending or XORing them) and then hashing for storage in the database. But that is vulnerable to a malicious administrator AND a rainbow table designed for that one salt.

3) You can have a separate salt for each user: The database will be used to store the salt, and the hash derived from the password/salt combination. This will prevent a rainbow attack, but brute force attacks will still be possible.

4) Finally, you can keep your hash function a secret by using a velocity-limited hardware hashing solution.

That is as good as you can do. Because of human nature, passwords have a limited domain and are vulnerable to brute force attacks. We are trying to prevent administrators getting a hold of user passwords, and then using them on other systems they should not have access to.

Some other notes:

a) You can use bcrypt on the password/salt combination to slow down the attacker’s brute force attack. But since we are assuming administrators, they can be patient.

b) Keeping the salt separate from the password hash is not an effective defense, we are assuming administrators after all.

c) Using existing data as a salt is a little better, but I doubt existing data has as much entropy a random salt has.


Salting a user's password is possibly safer than just hashing the password because it can protect against precomputation attacks.

For instance, if a hacker gets access to your database, and the passwords are not salted, then he can look up the hashes in his database of hashes (see http://en.wikipedia.org/wiki/Rainbow_table) to get the original passwords.

ReferenceURL : https://stackoverflow.com/questions/2188507/how-do-i-implement-salt-into-my-login-for-passwords

반응형