IT TIP

솔트 생성 및 오픈 소스 소프트웨어

itqueen 2020. 10. 30. 21:18
반응형

솔트 생성 및 오픈 소스 소프트웨어


내가 알기로 소금을 생성하는 가장 좋은 방법은 소스 코드에 저장된 몇 가지 비밀 공식 (또는 마법 상수)을 사용하는 것입니다.

저는 오픈 소스로 출시 할 계획 인 프로젝트를 진행하고 있지만, 문제는 소스와 함께 소금 생성을위한 비밀 공식이 제공되므로 사이트에서 레인보우 테이블 공격을 실행할 수 있다는 것입니다.

많은 사람들이이 문제를 먼저 고민해 왔고 모범 사례가 무엇인지 궁금합니다. 코드가 오픈 소스라면 솔트가 쉽게 리버스 엔지니어링 될 수 있기 때문에 솔트가 전혀없는 것 같습니다.

생각?


실제로 솔트는 각 항목에 대해 고유해야합니다. 공격자가 소금이 무엇인지 계산할 수 있다고해도 무지개 테이블을 만들기가 매우 어렵습니다. 이는 솔트가 해시되기 전에 비밀번호에 추가되기 때문에 레인보우 테이블에 포함해야하는 총 항목 수에 효과적으로 추가되어 비밀번호 필드에 대해 가능한 모든 값 목록을 갖기 때문입니다.


솔팅 해시에 대한 질문이 꽤 정기적으로 나오고 주제에 대해 약간의 혼란이있는 것 같아서이 답변을 확장했습니다.


소금이란 무엇입니까?

솔트는 해시 알고리즘의 입력에 추가되는 고정 길이의 임의 의 바이트 집합입니다.


솔팅 (또는 시드)이 왜 유용한가요?

해시에 임의의 솔트를 추가하면 동일한 암호가 여러 다른 해시를 생성 할 수 있습니다. 솔트는 일반적으로 해시 함수의 결과와 함께 데이터베이스에 저장됩니다. 해시를 솔팅하는 것은 여러 가지 이유로 좋습니다.

  1. 솔팅은 미리 계산 된 공격의 난이도 / 비용을 크게 증가시킵니다 ( 무지개 테이블 포함 ).
  2. 솔팅은 동일한 암호가 동일한 해시를 생성하지 않도록합니다. 이렇게하면 두 사용자가 동일한 암호를 가지고 있는지 확인할 수 없습니다. 그리고 더 중요한 것은 동일한 사람이 다른 시스템에서 동일한 암호를 사용하는지 확인할 수 없다는 것입니다.
  3. 솔팅은 암호의 복잡성을 증가시켜 사전 생일 공격 의 효율성을 크게 감소시킵니다 . (솔트 해시와 별도로 저장된 경우에만 해당됩니다 ).
  4. 적절한 솔팅 은 더 이상 실용적이지 않은 지점까지 사전 계산 공격에 대한 스토리지 요구를 크게 증가시킵니다. (128 비트 값으로 해시 된 16 비트 솔트를 사용하는 8 자의 대소 문자 구분 영숫자 암호는 무지개 감소없이 200 엑사 바이트 미만을 차지합니다 ).


소금이 비밀 일 필요는 없습니다.

솔트는 비밀 키가 아니라 각 인스턴스에 고유 한 해시 함수를 만들어 솔트가 '작동'합니다. 솔트 해시를 사용하면 해시 함수 하나 가 아니라 가능한 모든 솔트 값에 대해 하나씩 있습니다. 이는 공격자가 하나의 암호를 공격하는 비용의 N미만으로 N 개의 해시 된 암호를 공격하는 것을 방지 합니다. 이것이 소금의 요점입니다. "비밀 솔트"는 솔트가 아니라 "키"라고하며 더 이상 해시를 계산하지 않고 메시지 인증 코드 (MAC)를 의미합니다. MAC 컴퓨팅은 까다로운 비즈니스이며 (단순히 키와 값을 해시 함수에 두드리는 것보다 훨씬 더 까다 롭습니다) 완전히 다른 주제입니다.

솔트 는 사용되는 모든 인스턴스에 대해 무작위 여야합니다 . 이렇게하면 공격자가 모든 솔트 해시를 개별적으로 공격해야합니다.
솔트 (또는 솔팅 알고리즘)의 비밀에 의존하는 경우 보안을 통한 보안 영역에 들어갑니다 (작동하지 않음). 아마도 당신은 소금의 비밀에서 추가적인 보안을 얻지 못할 것입니다. 따뜻하고 은은한 안정감이 느껴집니다. 따라서 시스템을 더 안전하게 만드는 대신 현실에서주의를 분산시킵니다.


그렇다면 소금은 왜 무작위이어야합니까?

기술적으로 소금은 고유 해야합니다 . 솔트의 요점은 각 해시 된 암호에 대해 구별된다는 것입니다. 이것은 전세계를 의미 합니다 . 요청에 따라 고유 한 솔트를 배포하는 중앙 조직이 없기 때문에 예측할 수없는 랜덤 생성기로 무작위 선택, 가급적 충돌을 일으킬 수있을만큼 충분히 큰 솔트 공간 (동일한 것을 사용하는 두 개의 인스턴스)에 의존하는 차선책에 의존해야합니다. 소금 값).

사용자 ID와 같이 "아마도 고유 한"데이터에서 솔트를 추출하려고 시도하는 것이 좋지만 이러한 체계는 종종 몇 가지 불쾌한 세부 사항으로 인해 실패합니다.

  1. 예를 들어 사용자 ID 를 사용 하는 경우 다른 시스템을 공격하는 일부 악당은 리소스를 풀링하고 사용자 ID 1 ~ 50에 대해 미리 계산 된 테이블을 만들 수 있습니다. 사용자 ID는 시스템 전체에서 고유 하지만 전 세계적으로는 아닙니다 .

  2. 사용자 이름 에도 동일하게 적용됩니다 . Unix 시스템 당 하나의 "루트"가 있지만 세상에는 많은 루트가 있습니다. "루트"에 대한 레인보우 테이블은 수백만 시스템에 적용될 수 있으므로 노력할만한 가치가 있습니다. 더 나쁜 것은 또한 많은 "bob"이 있고 많은 사람들이 sysadmin 교육을받지 않고 있다는 것입니다. 그들의 암호는 매우 약할 수 있습니다.

  3. 고유성은 또한 일시적입니다. 때때로 사용자가 비밀번호를 변경합니다. 각각의 새 비밀번호 에 대해 새 솔트 를 선택해야합니다. 그렇지 않으면 공격자가 이전 암호의 해시를 획득하고 새 암호의 해시를 동시에 모두 공격 할 수 있습니다.

암호 학적으로 안전하고 예측할 수없는 PRNG에서 얻은 임의의 솔트를 사용하는 것은 일종의 과잉 일 수 있지만 적어도 모든 위험으로부터 사용자를 보호 할 있습니다. 공격자가 개별 소금이 무엇인지 알지 못하도록 막는 것이 아니라 상당한 수의 잠재적 표적에 사용될 크고 뚱뚱한 표적을주지 않는 것입니다. 무작위 선택은 대상을 실제처럼 얇게 만듭니다.


결론적으로:

무작위로 고르게 분포 된 높은 엔트로피 염을 사용하십시오. 새 암호를 만들거나 암호를 변경할 때마다 새 솔트를 사용하십시오. 해시 된 암호와 함께 솔트를 저장합니다. 큰 솔트를 선호합니다 (최소 10 바이트, 바람직하게는 16 이상).

솔트는 나쁜 암호를 좋은 암호로 바꾸지 않습니다. 공격자는 자신이 깰 때마다 최소한 사전 공격 가격을 지불 할 것 입니다.


유용한 출처 :
stackoverflow.com : 암호 해시 용 비 무작위 솔트
Bruce Schneier : Practical Cryptography (책)
Matasano 보안 : 레인보우 테이블로 충분 함
usenix.org : Unix crypt는 1976 년부터 솔트를 사용
했습니다 . owasp.org : 솔트를 추가하는 이유
openwall.com : 소금

면책 조항 :
저는 보안 전문가가 아닙니다. (이 답변은 Thomas Pornin에 의해 검토 되었지만 )
보안 전문가가 잘못된 것을 발견하면이 위키 답변을 댓글로 작성하거나 편집하십시오.


Since Unix became popular, the right way to store a password has been to append a random value (the salt) and hash it. Save the salt away where you can get to it later, but where you hope the bad guys won't get it.

This has some good effects. First, the bad guys can't just make a list of expected passwords like "Password1", hash them into a rainbow table, and go through your password file looking for matches. If you've got a good two-byte salt, they have to generate 65,536 values for each expected password, and that makes the rainbow table a lot less practical. Second, if you can keep the salt from the bad guys who are looking at your password file, you've made it much harder to calculate possible values. Third, you've made it impossible for the bad guys to determine if a given person uses the same password on different sites.

In order to do this, you generate a random salt. This should generate every number in the desired range with uniform probability. This isn't difficult; a simple linear congruential random number generator will do nicely.

If you've got complicated calculations to make the salt, you're doing it wrong. If you calculate it based on the password, you're doing it WAY wrong. In that case, all you're doing is complicating the hash, and not functionally adding any salt.

Nobody good at security would rely on concealing an algorithm. Modern cryptography is based on algorithms that have been extensively tested, and in order to be extensively tested they have to be well known. Generally, it's been found to be safer to use standard algorithms rather than rolling one's own and hoping it's good. It doesn't matter if the code is open source or not, it's still often possible for the bad guys to analyze what a program does.


You can just generate a random salt for each record at runtime. For example, say you're storing hashed user passwords in a database. You can generate an 8-character random string of lower- and uppercase alphanumeric characters at runtime, prepend that to the password, hash that string, and store it in the database. Since there are 628 possible salts, generating rainbow tables (for every possible salt) will be prohibitively expensive; and since you're using a unique salt for each password record, even if an attacker has generated a couple matching rainbow tables, he still won't be able to crack every password.

You can change the parameters of your salt generation based on your security needs; for example, you could use a longer salt, or you could generate a random string that also contains punctuation marks, to increase the number of possible salts.


Use a random function generator to generate the salt, and store it in the database, make salt one per row, and store it in the database.

I like how salt is generated in django-registration. Reference: http://bitbucket.org/ubernostrum/django-registration/src/tip/registration/models.py#cl-85

salt = sha_constructor(str(random.random())).hexdigest()[:5]
activation_key = sha_constructor(salt+user.username).hexdigest()
return self.create(user=user,
           activation_key=activation_key)

He uses a combination of sha generated by a random number and the username to generate a hash.

Sha itself is well known for being strong and unbreakable. Add multiple dimensions to generate the salt itself, with random number, sha and the user specific component, you have unbreakable security!


In the case of a desktop application that encrypts data and send it on a remote server, how do you consider using a different salt each time?

Using PKCS#5 with the user's password, it needs a salt to generate an encryption key, to encrypt the data. I know that keep the salt hardcoded (obfuscated) in the desktop application is not a good idea.

If the remote server must NEVER know the user's password, is it possible to user different salt each time? If the user use the desktop application on another computer, how will it be able to decrypt the data on the remote server if he does not have the key (it is not hardcoded in the software) ?

참고URL : https://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software

반응형