time ()은 좋은 소금입니까?
내가 직접 작성하지 않은 코드를보고 있습니다. 이 코드는 SHA512로 암호를 해시하려고 시도 time()
하고 솔트처럼 사용합니다 . 가 time()
너무 단순 염이 또는이 코드의 안전은?
답변과 의견에 감사드립니다. 새로운 독자를 위해 여기에 요약하겠습니다.
- 솔트는 각 사용자마다 달라야하므로 2 명의 사용자가 동시에 등록하면 솔트가 고유하지 않습니다. 이것은 문제이지만 큰 문제는 아닙니다.
- 하지만 솔트는 사용자와 어떤 식 으로든 관련이 없어야하므로 time ()은 좋은 솔트가 아닙니다.
- " 무작위로 균등하게 분포 된 높은 엔트로피 솔트를 사용하십시오. "-한 입이 많으니 어떤 코드가
random, evenly distributed, high entropy
솔트를 생성 할 수 있습니까?
좋아, 그래서 내가 time ()을 32 자 길이의 임의의 문자열로 바꾸는 방법은 무엇입니까? 임의의 문자열은 알파벳 문자 집합에 대해 32 번 반복하여 생성 될 수 있습니다. 그게 좋을까요?
짧은 대답:
아니, time()
좋은 소금이 아닙니다.
긴 대답 :
Salt Generation 및 오픈 소스 소프트웨어에 대한 내 답변에서 복사
소금이란 무엇입니까?
솔트는 해시 알고리즘의 입력에 추가되는 고정 길이의 임의 의 바이트 집합입니다.
솔팅 (또는 시드)이 왜 유용한가요?
해시에 임의의 솔트를 추가하면 동일한 암호가 여러 다른 해시를 생성 할 수 있습니다. 솔트는 일반적으로 해시 함수의 결과와 함께 데이터베이스에 저장됩니다. 해시를 솔팅하는 것은 여러 가지 이유로 좋습니다.
- 솔팅은 미리 계산 된 공격의 난이도 / 비용을 크게 증가시킵니다 ( 무지개 테이블 포함 ).
- 솔팅은 동일한 암호가 동일한 해시를 생성하지 않도록합니다. 이렇게하면 두 사용자가 동일한 암호를 가지고 있는지 확인할 수 없습니다. 그리고 더 중요한 것은 동일한 사람이 다른 시스템에서 동일한 암호를 사용하는지 확인할 수 없다는 것입니다.
솔팅은 암호의 복잡성을 증가시켜사전및생일 공격의 효율성을 크게 감소시킵니다.(솔트 가 해시와 별도로 저장된 경우에만 해당됩니다 ).- 적절한 솔팅 은 더 이상 실용적이지 않은 지점까지 사전 계산 공격에 대한 스토리지 요구를 크게 증가시킵니다. (128 비트 값으로 해시 된 16 비트 솔트를 사용하는 8 자의 대소 문자 구분 영숫자 암호는 무지개 감소없이 200 엑사 바이트 미만을 차지합니다 .)
소금이 비밀 일 필요는 없습니다.
솔트는 비밀 키가 아니라 각 인스턴스에 고유 한 해시 함수를 만들어 솔트가 '작동'합니다. 솔트 해시를 사용하면 해시 함수 가 하나 가 아니라 가능한 모든 솔트 값에 대해 하나씩 있습니다. 이것은 공격자가 하나의 암호를 공격하는 비용의 N 배 미만으로 N 개의 해시 된 암호를 공격하는 것을 방지 합니다. 이것이 소금의 요점입니다. "비밀 솔트"는 솔트가 아니라 "키"라고하며 더 이상 해시를 계산하지 않고 메시지 인증 코드 (MAC)를 의미합니다. MAC 컴퓨팅은 까다로운 사업이며 (단순히 키와 값을 해시 함수에 두드리는 것보다 훨씬 더 까다 로움) 완전히 다른 주제입니다.
솔트 는 사용되는 모든 인스턴스에 대해 무작위 여야합니다 . 이렇게하면 공격자가 모든 솔트 해시를 개별적으로 공격해야합니다.
솔트 (또는 솔팅 알고리즘)의 비밀에 의존하는 경우 보안을 통한 보안 영역에 들어갑니다 (작동하지 않음). 아마도 당신은 소금의 비밀에서 추가적인 보안을 얻지 못할 것입니다. 따뜻하고 은은한 안정감이 느껴집니다. 따라서 시스템을 더 안전하게 만드는 대신 현실에서주의를 분산시킵니다.
그렇다면 소금은 왜 무작위이어야합니까?
기술적으로 소금은 고유 해야합니다 . 솔트의 요점은 각 해시 된 암호에 대해 구별된다는 것입니다. 이것은 전세계를 의미 합니다 . 요청에 따라 고유 한 솔트를 배포하는 중앙 조직이 없기 때문에 예측할 수없는 랜덤 생성기로 무작위 선택, 가급적 충돌을 일으킬 수있을만큼 충분히 큰 솔트 공간 (동일한 것을 사용하는 두 개의 인스턴스)에 의존하는 차선책에 의존해야합니다. 소금 값).
사용자 ID와 같이 "아마도 고유 한"데이터에서 솔트를 추출하려고 시도하는 것이 좋지만 이러한 체계는 종종 일부 불쾌한 세부 사항으로 인해 실패합니다.
예를 들어 사용자 ID 를 사용 하는 경우 다른 시스템을 공격하는 일부 악당은 리소스를 풀링하고 사용자 ID 1 ~ 50에 대해 미리 계산 된 테이블을 만들 수 있습니다. 사용자 ID는 시스템 전체에서 고유 하지만 전 세계적으로는 아닙니다 .
사용자 이름 에도 동일하게 적용됩니다 . Unix 시스템 당 하나의 "루트"가 있지만 세계에는 많은 루트가 있습니다. "루트"에 대한 레인보우 테이블은 수백만 시스템에 적용될 수 있기 때문에 노력할 가치가 있습니다. 더 나쁜 것은 또한 많은 "bob"이 있고 많은 사람들이 sysadmin 교육을받지 않고 있다는 것입니다. 그들의 암호는 매우 약할 수 있습니다.
고유성은 또한 일시적입니다. 때때로 사용자가 비밀번호를 변경합니다. 각각의 새 비밀번호 에 대해 새 솔트 를 선택해야합니다. 그렇지 않으면 공격자가 이전 암호의 해시를 얻고 새 암호의 해시를 동시에 모두 공격 할 수 있습니다.
암호 학적으로 안전하고 예측할 수없는 PRNG에서 얻은 임의의 솔트를 사용하는 것은 일종의 과잉 일 수 있지만 적어도 모든 위험으로부터 사용자를 보호 할 수 있습니다. 공격자가 개별 소금이 무엇인지 알지 못하도록 막는 것이 아니라 상당한 수의 잠재적 표적에 사용될 크고 뚱뚱한 표적을주지 않는 것입니다. 무작위 선택은 대상을 실제처럼 얇게 만듭니다.
결론적으로:
무작위로 고르게 분포 된 높은 엔트로피 염을 사용하십시오. 새 암호를 만들거나 암호를 변경할 때마다 새 솔트를 사용하십시오. 해시 된 암호와 함께 솔트를 저장합니다. 큰 솔트를 선호합니다 (최소 10 바이트, 바람직하게는 16 이상).
솔트는 나쁜 암호를 좋은 암호로 바꾸지 않습니다. 공격자는 자신이 깰 때마다 최소한 사전 공격 가격을 지불 할 것 입니다.
유용한 출처 :
stackoverflow.com : 암호 해시를위한 비 랜덤 솔트
Bruce Schneier : Practical Cryptography (책)
Matasano 보안 : Rainbow Tables로 충분 함
usenix.org : Unix crypt는 1976 년부터 솔트를 사용
했습니다 . owasp.org : 솔트를 추가하는 이유
openwall.com : 소금면책 조항 :
저는 보안 전문가가 아닙니다. (이 답변은 Thomas Pornin에 의해 검토 되었지만 )
보안 전문가가 잘못된 것을 발견하면이 위키 답변을 댓글로 작성하거나 편집하십시오.
당신의 랜덤 솔트를위한 좋은 소스로 보이는 것에 관해서는
또한 읽어보십시오 : 난수 생성을위한 가장 안전한 시드는 무엇입니까?
전용 하드웨어 기반 임의 생성기가없는 경우 임의 데이터를 얻는 가장 좋은 방법은 운영 체제에 문의하는 것입니다 (Linux에서는 이것을 호출 /dev/random
하거나 /dev/urandom
[장점과 문제가 모두 있습니다. 독을 선택하십시오]. Windows에서는을 호출하십시오. CryptGenRandom()
)
어떤 이유로 위에서 언급 한 임의 소스에 액세스 할 수없는 경우 PHP에서 다음 기능을 사용할 수 있습니다.
From the source of phpass v0.3
<?php
/**
* Generate pseudo random bits
* @copyright: public domain
* @link http://www.openwall.com/phpass/
* @param int $length number of bits to generate
* @return string A string with the hexadecimal number
* @note don't try to improve this, you will likely just ruin it
*/
function random_bits($entropy) {
$entropy /= 8;
$state = uniqid();
$str = '';
for ($i = 0; $i < $entropy; $i += 16) {
$state = md5(microtime().$state);
$str .= md5($state, true);
}
$str = unpack('H*', substr($str, 0, $entropy));
// for some weird reason, on some machines 32 bits binary data comes out as 65! hex characters!?
// so, added the substr
return substr(str_pad($str[1], $entropy*2, '0'), 0, $entropy*2);
}
?>
업데이트 됨
정말 좋은 소금은 아니지만 가장 단호하고 수완이 풍부한 공격자를 제외한 모든 공격자를 물리 칠 수있을만큼 좋습니다. 좋은 소금에 대한 요구 사항은 다음과 같습니다.
- 사용자마다 다름
- long enough (at the very least alphanumeric 8 characters) to make the concatenation of salt and (potentially weak) password too long for a brute force attack.
time()
values are not really long enough, since they have 10 characters, but only digits.
Also, sometimes two users may get the same value when they are created within the same second. But that's only a problem if you have situations where many users are automatically created within the same second.
In any case, far more important than a perfect salt is using a good hash function, and SHA512 is one of the best we have available right now.
This post may veer a little too far away from your original question, but I hope you find it useful;
Security is about raising barriers and hurdles; defence in depth. There is no truly secure hashing solution, just ones that are hard to break. It's like putting in a burglar alarm and window locks in your house - make your site less attractive to break into than someone else's.
Salt for a crypt algorithm is only a small part of the security problem. A single salt simply means that there is one less thing to figure out when trying to break the password for multiple users. A low-entropy salt (such as the server's time) makes it a little bit harder, and a high-entropy salt makes it harder still. Which of these to use, and whether it's something you need to worry about primarily depends upon both the sensitivity of the data you're protecting, but also what other security measures you have in place. A site that just gives a personalised weather forecast for a selected city obviously has less sensitive data than one which has your home address, mother's maiden name, date of birth and other info which could be used for identification purposes.
So here's the rub; a high entropy salt is still a bad salt if it's easily obtainable.
In the real world, storing a salt in the database (random or not) is probably less secure than using a constant salt and burying it away from private eyes in a file inaccessible via the web browser. Whilst a unique and high entropy salt is harder to guess, if you've allowed root login from any server on MySql and set the password to 'password' it doesn't really matter! Constrast how easy it is to crack the database versus getting a valid login to your server - which is possibly more difficult to do discretely as you can put fail2ban and a plethora of other attack vector watchers in place depending upon your setup.
You can combine the two approaches by storing the location of a file containing a user-specific salt in the database, rather than the salt itself. Whether having to crack both the file system and the database is warranted depends whether the sensitivity of the data you are trying to protect warrants this overhead.
Another, alternative, recommendation from security experts is to store the username in a separate database (and ideally different technology) to the password, and reference between the two using a UUID. E.g. use both MySQL and SQLite. This means that both databases have to be cracked (and is also why, to go down a separate rabbit hole for the sake of an example, you should not store user details and credit card numbers in the same database since one is of no use without the other).
Note that Algorithms like SHA-512 and Blowfish can return the salt as part of their hash. Be careful with these as if you store the complete hash you give away the algorithm, which means there's two less thing for the hackers to figure out (the salt also gives away the algorithm).
Make sure you enforce strong passwords and usernames, so dictionary attacks will fail; I know of dictionaries for all 6-alphanumeric combinations of username/ password entries for MD5 and I suspect that there are more than this available for all sorts of algorithms. With the explosion of low-cost cloud and CPGPU computing, the size and complexity of available dictionaries is going to explode.
Ultimately, the most secure way is never to programatically generate a salt but require a user to enter it along with their username and password over a SSL link (so can't be snooped), but never store it. This is the approach taken by credit card companies; i.e. the 3-digit CSV security key on your credit card which you have to enter each and every time you buy online, since it should never be stored in any database. If you really want to generate the salt, send it to them separately (e.g. via SMS message or Email) and still make them enter it manually each time. With this approach, although more secure, you need to contrast the complexity against whether users will just stop using the site as you've made it too difficult for them to be bothered with it.
All of the above still relies on the fact that you also have protection in place against session hijacking, cross-site scripting, etc., etc. The world's strongest password algorithm is irrelevant if all I need to do is to calculate a valid PHPSESSID for a logged-in user and hijack it!
I am not a security expert, but have read up on this as much as I reasonably can do. The fact that there are so many books on the subject indicates how big the answer to your question really is.
A couple of really great books you might like to try which I've found invaluable are;
Web Application Vulnerabilities Detect, Exploit, Prevent - ISBN-13: 978-1-59749-209-6
Preventing Web Attacks with Apache - ISBN-13: 978-0-321-32128-2
No, time() is not a good salt
It's best not to reinvent the wheel when it comes to authentication, but to answer your question, no. The problem with time():
- It's predictable and it correlates to potentially discoverable things. These issues make it easier to cross-match different hashed results.
- There aren't very many possible values. Since the high-order bits don't change, it's an even narrower salt than it first appears.
- Using it repeats previous mistakes. If this app were the first one to use time() as a salt, at least it would require a new attack.
Yes.
It seems that a unix timestamp, stored in the user database as a "Member since" field going to be decent salt.
However, salt question is most negligible one. There are much more important things you have to pay attention to:
Most likely not a password nor salt or hashing algorithm going to be weakest part of your site. Some lame file injection or XSS or CSRF surely is. So, don't make a too big deal of it.
Speaking of a true random string of 32 char long in the typical web-application is like speaking about 32-inch armored door in the wooden barn.Speaking of passwords, most ever important thing is password complexity. With weak password no salt nor hashing algorithm, even super-ingenious-incredible-hard one, could help. It's a pain to ask users to use complex password, but without it everything else becomes a piece of crap.
So, your first concern should be password complexity. 12-16 characters of different case, including numbers and punctuation is a requirement.As for the salt,
I see no benefit in using time, as you have to store it along with other user data. Better use a email - it's random enough and you have it already anyway. Don't forget to rehash a password if user changes their email.it seems that unix timstamp going to be a decent salt, no need to use email or anything else.
Update
As I can see, many people still unable to get the point.
Like that guy from the comments, saying
Many users use weak passwords (we should educate them, or at least keep trying), but that is no excuse; they still deserve good security
They deserve, no doubt. But with weak password the mission. is. impossible.
If your password is weak, then no salt will protect it.
While salt is not that important to spend a 10-kilobyte text on the topic.
Salt is use to prevent rainbow attacks by breaking the match between the password and precomputed hash. So the main task for a salt is to be different for each user/password record. Quality of randomization of the salt doesn't matter much as long as the salt is different for different users.
the date when a member joins a forum/website is generally openly access able , which would be same as time() hence making your salt useless.
No! Never use the current time as the salt. You can use something like 'SecureRandom' in java to generate a random salt that is secure. Always use an unpredictable random number as the salt.
Using time as the salt will help you to remove collisions only upto a certain extent(because two users can sypply the same passwords at the same time), but still make the passwords recoverable.
The user name should be sufficient enough and perhaps the registration time stamp, but you should store it somewhere in the database. Anyway every value you use to salt your password hash, should be stored some way, so you can recalculate the hash.
Is salting with user name + a time stamp secure enough? It should be. For cracking SHA512 Hashes normally Rainbow Tables are used. A user name + a time stamp should be a salt which is uniquq enough, so there is no way there is some Rainbow Table on the net which contains precalculated hashes with passwords, which are salted this way.
ReferenceURL : https://stackoverflow.com/questions/4983915/is-time-a-good-salt
'development' 카테고리의 다른 글
Android 환경 설정 키를 저장할 위치 (0) | 2020.12.30 |
---|---|
키별로 정렬 된 사전의 키 / 값 쌍 반복 (0) | 2020.12.30 |
MVVM 모델에서 모델은 INotifyPropertyChanged 인터페이스를 구현해야합니까? (0) | 2020.12.30 |
동적 메모리 할당은 널리 사용되는 구현에서 C와 C ++에서 다릅니 까? (0) | 2020.12.30 |
데이터베이스 연결 문자열에 최대 풀 크기를 설정해야합니까? (0) | 2020.12.30 |