데이터베이스에 비밀번호를 저장하는 가장 좋은 방법


474

인증이 필요한 프로젝트 (사용자 이름 및 비밀번호)를 작업 중입니다.

또한 데이터베이스에 연결되므로 사용자 이름과 비밀번호를 저장할 것이라고 생각했습니다. 그러나 데이터베이스에있는 테이블의 텍스트 필드처럼 암호를 갖는 것은 좋은 생각이 아닙니다.

C #을 사용하고 2008 Express 서버에 연결하고 있습니다. 이 유형의 데이터를 저장하는 가장 좋은 방법은 무엇입니까?

추신 : 나는 합리적인 이유를 제공 할 수 있다면이 정보가 데이터베이스에 저장되지 않는다는 생각에 개방적입니다.


1
무엇을하든 암호화를 사용하는 경우 이전에 언급 한 포스터처럼 키를 코드에 저장하지 마십시오. 그건 나쁜 연습입니다.
Woody

12
'암호를 올바르게하는 방법?' 중요한 질문입니다. 어려운 문제이며 실수는 중대한 결과를 초래합니다 (테스코와 링크드 인에게 일어난 일을 상기하십시오). 이 질문은 programmers.stackexchange.com
Panic

2
표준을 고수하는 것이 좋습니다. en.wikipedia.org/wiki/PBKDF2 참조 언어로만 구현하면됩니다
Boris Treukhov

5
이 질문은 보안 포럼에서 광범위하게 답변됩니다 : security.stackexchange.com/questions/211/…
gioele

답변:


405

일반 텍스트 필드에 비밀번호를 저장하는 것은 끔찍한 아이디어입니다. 그러나 location이 진행 되는 한 데이터베이스에 비밀번호 표시 를 저장하는 대부분의 경우 (그리고 솔직히 반대의 예는 생각할 수 없습니다) 대부분의 경우 올바른 조치입니다. 표현함으로써 당신이 해시 (모든 사용자 달라야) 소금 안전한 단방향 알고리즘 및 저장 사용하여 암호 원하는 것을 의미 하는 것이 , 원래 암호를 버리고합니다. 그런 다음 암호를 확인하려면 동일한 해싱 알고리즘과 솔트를 사용하여 값을 해시하고 데이터베이스의 해시 값과 비교합니다.

그래서, 당신이 이것에 대해 생각하고 좋은 질문이지만 좋은 질문이지만, 실제로는 적어도 이러한 질문들과 중복됩니다.

솔트 비트에 대해 좀 더 명확하게 설명하기 위해 단순히 암호를 해시하고 저장하는 위험은 침입자가 데이터베이스를 보유하더라도 레인보우 테이블 이라고 알려진 것을 사용 하여 "암호 해독"할 수 있다는 것입니다. 암호 (무지개 레인보우 테이블에 표시되는 암호). 이 문제를 해결하기 위해 개발자는 암호에 소금 을 추가하여 올바르게 수행하면 무지개 공격을하기가 불가능 해집니다. 일반적인 오해는 모든 암호에 동일하고 긴 문자열을 동일하게 추가하는 것입니다. 이것은 끔찍한 것은 아니지만 모든 암호에 고유 한 소금을 추가하는 것이 가장 좋습니다. 자세한 내용을 읽으십시오.


40
암호를 다른 곳에 저장하는 대신 데이터베이스에 암호를 저장하는 것을 의미했습니다. 문맥에서 문장을 꺼내면 일반 암호 저장을 지원하는 것처럼 보입니다. 나머지 암호를 읽으면 분명히 그렇지 않습니다.
Paolo Bergantino 2016 년

14
뿐만 아니라 내가 말한, 나는 소금과 같은 더 ... 논의 게시물의 과다에 그를 감독이다
파올로 Bergantino

1
@Paolo Bergantino : 게시물에 오타가 없습니까? "대부분의 경우 데이터베이스에 암호를 저장하는 것은 (그리고 솔직히 어떤 반례도 생각할 수 없다) 할 것입니다." ??? 귀하의 의견을 contrdict 것
미치 밀을

3
Paolo의 말은 직접 모순됩니다. 비밀번호의 소금에 절인 해시는 비밀번호가 아닙니다. 데이터베이스에 소금에 절인 해시를 저장하면 데이터베이스에 암호가 저장되지 않습니다. 대답의 본문은 완벽하게 적합하지만 첫 번째 문장은 매우 오도됩니다.
Robert Rossney

40
@Robert : 그것은 사소한 의미 론적 게임에 위험에 가까워 지지만 그래도 고칠 것입니다 ...
Paolo Bergantino

54

배경 당신은 결코 ... 정말 ... 사용자의 암호를 알아야합니다. 수신 사용자가 계정의 비밀번호를 알고 있는지 확인하기 만하면됩니다.

해시 : 강력한 해시 기능을 통해 해시 된 (단방향 암호화) 사용자 비밀번호를 저장합니다. "c # 암호화 암호"를 검색하면 많은 예제가 제공됩니다.

해시 함수가 생성하는 것에 대한 아이디어 는 온라인 SHA1 해시 작성자 를 참조하십시오 (그러나 SHA1을 해시 함수로 사용하지 말고 SHA256과 같은 강력한 것을 사용하십시오).

이제 해시 된 비밀번호는 사용자 (및 데이터베이스 도둑)가 해당 해시를 원래 비밀번호로 되돌릴 수 없어야 함을 의미합니다.

사용 방법 : 그러나 데이터베이스에 저장된이 으스스한 암호를 어떻게 사용합니까?

사용자가 로그인하면 사용자 이름과 비밀번호를 원래 텍스트로 전달합니다. 동일한 해시 코드를 사용하여 입력 한 비밀번호를 해시하여 저장된 버전을 가져옵니다.

따라서 두 개의 해시 비밀번호 (사용자 이름에 대한 데이터베이스 해시 및 입력 및 해시 비밀번호)를 비교하십시오. 해시를 비교하여 "입력 한 내용"과 "원래 사용자가 암호를 입력 한 내용"이 일치하는지 알 수 있습니다.

추가 크레딧 :

질문 : 데이터베이스가 있다면 John the Ripper와 같은 크래커를 사용하여 저장된 해시 비밀번호와 일치하는 것을 찾을 때까지 해시를 시작할 수 없습니까? (사용자가 짧고 사전 단어를 선택했기 때문에 ... 쉽습니다)

답 : 예 ... 가능합니다.

따라서 비밀번호를 '소금'해야합니다. 소금에 관한 Wikipedia 기사를 참조하십시오

참조 "어떻게 소금 해시 데이터에"C # 예제


14
md5와 sha1은 둘 다 깨졌습니다. 아마도 SHA2 계열과 같은 더 강력한 알고리즘을 사용해야 할 것입니다.
Paolo Bergantino 2016 년

3
감사합니다 Paolo-당신이 맞습니다. SHA2는 MD5 및 SHA1을 사용하는 것처럼 쉽게 사용할 수 있으므로 더 강력한 해시 알고리즘을 사용하십시오.
joej 2016 년

5
SHA-1은 깨지지 않았습니다. 그러나 브루스 슈나이어 (Bruce Schneier)는 다음과 같습니다.
Ian Boyd

2
"그래서, 당신은 당신의 암호를 '소금'해야합니다 ..."그러나 소금은 보통 암호와 함께 데이터베이스에 저장됩니다. 그러면 어떻게 도움이됩니까? 테 공격자는 단순히 자신이 테스트하고있는 사전 공격 문구에 소금을 추가하기 만하면됩니다. 중복 암호를 공개하지 않는 것보다 더 안전합니까?
trusktr

4
@joej "당신은 절대로 ... 정말 ... 사용자의 암호를 알아야 할 필요가 없습니다."-그것은 매우 짧은 가정입니다. 검색 할 수있는 방식으로 암호를 저장해야하는 많은 종류의 응용 프로그램이 있습니다. 예를 들어, 사용자가 제공하고 업데이트 한 저장된 자격 증명을 사용하여 다른 시스템에 자주 로그인해야하는 응용 프로그램입니다.
Francisco Zarabozo

29

sha-512와 같은 보안 알고리즘을 사용하여 키로 강화 된 솔트 해시입니다.


6
제 생각에는 암호를 저장하기 위해 항상 느린 알고리즘 (예 : Blowfish)을 사용해야합니다. 이 문서는 security.stackexchange.com/questions/211/… 보다 나은 답변 입니다. 이 페이지는 검색 결과에서 여전히 높게 표시되므로 여기에 넣으면됩니다.
Dynom

2
암호 저장에 대한이 조언을 따르면 잘못 수행 될 수 있습니다.
mlissner

27

최상의 보안 방법은 암호를 전혀 저장하지 않고 암호화 된 암호의 소금에 절인 해시 (암호 당 고유 한 소금으로)를 저장하는 것입니다.

그렇게하면 평문 암호를 검색하는 것이 (실제적으로) 불가능합니다.


11
웨인은 해시를 계산하기 전에 소금을 뿌려서 소금의 크기가 충분한 경우 무지개 테이블을 효과적으로 물리칩니다.
Mike Rosenblum

11
@ 웨인 하트먼 : 그렇지 않습니다. 솔트 값이 노출되면 해당 솔트 값에 대한 새 무지개 테이블을 생성해야합니다. 레인보우 테이블의 요점은 미리 해시 값을 계산하는 것입니다. 그리고 아무도 그의 특정 소금에 무지개 테이블을 갖지 않을 것입니다.
Ian Boyd

10

충분한 무지개 테이블 : 보안 암호 체계에 대해 알아야 할 사항 [데드 링크, 인터넷 보관소에 복사 ] 및 암호를 안전하게 저장하는 방법을 읽어 보는 것이 좋습니다 .

제 자신도 포함 된 많은 코더들은 보안과 해싱을 이해한다고 생각합니다. 슬프게도 우리 대부분은 그렇지 않습니다.


1
@Johan 링크가 깨져서 부끄러운 것 같습니다. 다음은 대안입니다. codahale.com/how-to-safely-store-a-password
zebrabox

6

사용자 이름과 비밀번호가 필요하다고 언급하면서 주제가 약간 벗어 났을 수 있으며 문제에 대한 나의 이해가 최고는 아니지만 OpenID가 고려해야 할 가치가 있습니까?

OpenID를 사용하는 경우 기술을 올바르게 이해하고 사용자가 이미 보유한 자격 증명을 사용할 수 있으므로 자격 증명을 전혀 저장하지 않아도 응용 프로그램과 관련된 새 ID를 만들 필요가 없습니다.

해당 응용 프로그램이 순전히 내부 용인 경우에는 적합하지 않을 수 있습니다.

RPX 는 OpenID 지원을 응용 프로그램에 통합 할 수있는 좋은 방법을 제공합니다.


나는 openID가 사람들의 얼굴을 흔드는 데 동의하지만이 응용 프로그램의 경우 회사의 사내 데이터베이스이므로 노인이 로그온하기를 원할 것입니다. 또한이 응용 프로그램이 제대로 작동하는 데 웹 액세스가 필요하지 않으므로 필요하지 않습니다.
Crash893 2016 년

3

시나리오에서 asp.net 멤버쉽을 볼 수 있으므로 데이터베이스에 사용자의 비밀번호를 해시 문자열로 저장하는 것이 좋습니다. 해시 된 수신 비밀번호와 데이터베이스에 저장된 비밀번호를 비교하여 사용자를 인증 할 수 있습니다.

이 목적을 위해 모든 것이 구축되었습니다. asp.net 멤버십을 확인하십시오.


1

해시를 되돌릴 필요가 없으면 MD5 / SHA1 암호를 사용합니다. 사용자가 로그인하면 제공된 비밀번호를 암호화하여 해시와 비교할 수 있습니다. 이 경우 누군가가 데이터베이스에 액세스하여 충돌이있는 해시를 보지 않는 한 해시 충돌은 거의 불가능합니다.


2
그것은 기본적으로 생겼습니다 - 나는 해싱을 위해 MD5를 사용하지 않을 mscs.dal.ca/~selinger/md5collision
zebrabox

3
실제로, 그것은 그렇게 부서지지 않았습니다. 그들이 할 수있는 일은 두 개의 다른 파일에 대해 동일한 해시 값을 찾는 것입니다. 그들이 할 수없는 것은 MD5를 뒤집어서 작동하는 암호를 얻는 것입니다.
waiwai933

2
글쎄, 그때도 그렇게 깨지지 않았을까? 동일한 해시를 생성하는 다른 비밀번호 만 입력하면됩니다. 원래 비밀번호를 몰라도됩니다. 이 문제를 해결하는 방법은 해싱 전에 비밀번호를 소금에 절인 경우입니다.
mjuarez 2013

2
@mjuarez MD5를 사용하기 전에 암호에 소금을 추가하면 다른 암호를 사용할 수 없기 때문에 충돌이 중요하지 않습니다
WiiMaxx
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.