developer tip

데이터베이스에 암호를 저장하는 기본 방법

optionbox 2020. 10. 16. 07:21
반응형

데이터베이스에 암호를 저장하는 기본 방법


데이터베이스 (바람직하게는 SQL Server 2005)에 암호를 저장하는 데 선호하는 방법 / 데이터 유형은 무엇입니까? 여러 응용 프로그램에서이 작업을 수행 한 방식은 먼저 .NET 암호화 라이브러리를 사용한 다음 데이터베이스에 binary (16)로 저장하는 것입니다. 이것이 선호되는 방법입니까, 아니면 다른 데이터 유형을 사용하거나 16보다 더 많은 공간을 할당해야합니까?


나는 암호에 상응하는 솔트 해시를 데이터베이스에 저장하고 암호 자체는 저장하지 않고 항상 사용자가 전달한 해시와 생성 된 해시를 비교합니다.

리터럴 암호 데이터를 어디에 든 저장하는 것은 너무 위험합니다. 이로 인해 복구가 불가능하지만 누군가 암호를 잊거나 잃어버린 경우 몇 가지 검사를 실행하여 새 암호를 만들 수 있습니다.


선호하는 방법 : DB에 비밀번호를 저장하지 마십시오. 해시 만합니다. 맛에 소금을 넣으십시오.


문자열로 저장된다는 점을 제외하고는 설명한 것과 동일합니다. I Base64는 암호화 된 이진 값을 인코딩합니다. 할당 할 공간의 양은 암호화 알고리즘 / 암호화 강도에 따라 다릅니다.

나는 당신이 잘하고 있다고 생각합니다 (당신이 Salt 를 사용한다면 ).


  1. bcrypt (nounce + pwd)와 같이 솔트 된 암호의 해시를 저장합니다. CPU 집약적으로 조정될 수 있기 때문에 SHA1 또는 MD5보다 bcrypt를 선호 할 수 있으므로 무차별 대입 공격이 더 길어집니다.
  2. 몇 번의 로그인 오류 후 로그인 양식에 보안 문자 추가 (무차별 대입 공격 방지)
  3. 애플리케이션에 "비밀번호 분실"링크가있는 경우 이메일로 새 비밀번호를 보내지 않는지 확인하십시오. 대신 사용자가 새 비밀번호를 정의 할 수있는 (보안) 페이지 링크를 보내야합니다 (확인 후에 만 ​​가능). 예를 들어 사용자의 생년월일과 같은 일부 개인 정보). 또한 응용 프로그램에서 사용자가 새 암호를 정의하도록 허용하는 경우 사용자에게 현재 암호를 확인하도록 요구해야합니다.
  4. 그리고 분명히 로그인 양식 (일반적으로 HTTPS 사용)과 서버 자체를 보호합니다.

이러한 조치를 통해 사용자의 암호는 다음으로부터 상당히 잘 보호됩니다.

  1. => 오프라인 사전 공격
  2. => 라이브 사전 공격
  3. => 서비스 거부 공격
  4. => 온갖 공격!

해시 함수의 결과는 0 ~ 255 (또는 8 비트 데이터 유형의 부호에 따라 -128 ~ 127) 범위의 일련의 바이트이므로 원시 바이너리 필드로 저장하는 것이 가장 적합합니다. , 가장 간결한 표현이며 추가 인코딩 및 디코딩 단계가 필요하지 않습니다.

일부 데이터베이스 또는 드라이버는 이진 데이터 유형을 잘 지원하지 않거나 때로는 개발자가 익숙하지 않아 편하게 느낄 수 없습니다. 이 경우 Base-64 또는 Base-85와 같은 바이너리-텍스트 인코딩을 사용하고 결과 텍스트를 문자 필드에 저장할 수 있습니다.

필요한 필드의 크기는 사용하는 해시 함수에 의해 결정됩니다. MD5는 항상 16 바이트를 출력하고 SHA-1은 항상 20 바이트를 출력합니다. 해시 기능을 선택하면 변경하려면 기존의 모든 암호를 재설정해야하므로 일반적으로 해시 기능을 사용하지 않습니다. 따라서 가변 크기 필드를 사용하는 것은 아무것도 사지 않습니다.


해싱을 수행하는 "가장 좋은"방법과 관련하여 해당 주제에 대한 다른 SO 질문에 대한 많은 답변을 제공하려고했습니다.


사용자 이름의 sha 해시, 웹 구성의 guid 및 varchar (40)로 저장된 암호를 사용합니다. 무차별 대입 / 사전을 원할 경우 GUID 용 웹 서버도 해킹해야합니다. 사용자 이름은 암호를 찾으면 전체 데이터베이스에 무지개 테이블을 만드는 것을 중단합니다. 사용자가 사용자 이름을 변경하려는 경우 동시에 비밀번호를 재설정합니다.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

단순한 암호 해시 또는 심지어 (salt + password)는 일반적으로 적절하지 않습니다.

보다:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

둘 다 bcrypt 알고리즘을 권장합니다. 대부분의 인기있는 언어에 대한 무료 구현은 온라인에서 찾을 수 있습니다.


데이터베이스에서 여러 해시를 사용할 수 있으며 약간의 추가 노력이 필요합니다. 나중에 추가 형식을 지원해야 할 가능성이 가장 멀다고 생각한다면 그만한 가치가 있습니다. 나는 종종 다음과 같은 암호 항목을 사용합니다.

{hashId} $ {salt} $ {해시 된 비밀번호}

여기서 "hashId"는 내부적으로 인식하기 위해 사용하는 숫자입니다. 예를 들어 특정 해시 패턴과 함께 SHA1을 사용하고 있습니다. "salt"는 base64로 인코딩 된 랜덤 솔트입니다. "해시 된 암호"는 base64로 인코딩 된 해시입니다. 해시를 마이그레이션해야하는 경우 이전 암호 형식을 사용하는 사람을 가로 채서 다음에 로그인 할 때 암호를 변경하도록 할 수 있습니다.

As others have mentioned you want to be careful with your hashes since it's easy to do something that's not really secure, e.g., H(salt,password) is far weaker than H(password,salt), but at the same time you want to balance the effort put into this with the value of the site content. I'll often use H(H(password,salt),password).

Finally, the cost of using base64-encoded passwords is modest when compared to the benefits of being able to use various tools that expect text data. Yeah, they should be more flexible, but are you ready to tell your boss that he can't use his favorite third party tool because you want to save a few bytes per record? :-)

Edited to add one other comment: if I suggested deliberately using an algorithm that burned even a 1/10th of a second hashing each password I would be lucky to just be laughed out of my boss's office. (Not so lucky? He would jot something down to discuss at my next annual review.) Burning that time isn't a problem when you have dozens, or even hundreds, of users. If you're pushing 100k users you'll usually have multiple people logging in at the same time. You need something fast and strong, not slow and strong. The "but what about the credit card information?" is disingenuous at best since stored credit card information shouldn't be anywhere near your regular database, and would be encrypted by the application anyway, not individual users.


If you are working with ASP.Net you can use the built in membership API.

It supports many types of storage options, inlcuding; one way hash, two way encryption, md5 + salt. http://www.asp.net/learn/security for more info.

If you dont need anything too fancy, this is great for websites.

If you are not using ASP.Net here is a good link to a few articles from 4guys and codeproject

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption.aspx


Since your question is about storage method & size I will address that.

Storage type can be either binary or text representation (base64 is the most common). Binary is smaller but I find working with text easier. If you are doing per user salting (different salt per password) then it is easier to store salt+hash as a single combined string.

The size is hash algorithm dependent. The output of MD5 is always 16 bytes, SHA1 is always 20 bytes. SHA-256 & SHA-512 are 32 & 64 bytes respectively. If you are using text encoding you will need slightly more storage depending on the encoding method. I tend to use Base64 because storage is relatively cheap. Base64 is going to require roughly 33% larger field.

If you have per user salting you will need space for the hash also. Putting it all together 64bit salt + SHA1 hash (160 bit) base64 encoded takes 40 characters so I store it as char(40).

Lastly if you want to do it right you shouldn't be using a single hash but a key derivation function like RBKDF2. SHA1 and MD5 hashes are insanely fast. Even a single threaded application can hash about 30K to 50K passwords per second thats up to 200K passwords per second on quad core machine. GPUs can hash 100x to 1000x as many passwords per second.With speeds like that brute force attacking becomes an acceptable intrusion method. RBKDF2 allows you to specify the number of iterations to fine tune how "slow" your hashing is. The point isn' to bring the system to its knees but to pick a number of iterations so that you cap upper limit on hash throughput (say 500 hashes per second). A future proof method would be to include the number of iterations in the password field (iterations + salt + hash). This would allow increasing iterations in the future to keep pace with more powerful processors. To be even more flexible use varchar to allow potentially larger/alternative hashes in the future.

The .Net implementation is RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

참고URL : https://stackoverflow.com/questions/615704/preferred-method-of-storing-passwords-in-database

반응형