질문자 :luiscubal
현재 MD5는 부분적으로 안전하지 않다고 합니다. 이를 고려하여 비밀번호 보호를 위해 어떤 메커니즘을 사용해야 하는지 알고 싶습니다.
이 질문 은 "이중 해싱"이 암호를 한 번만 해싱하는 것보다 덜 안전합니까? 여러 번 해싱하는 것이 좋은 생각일 수 있다고 제안하는 반면 개별 파일에 대한 암호 보호를 구현하는 방법은 무엇입니까? 소금 사용을 제안합니다.
나는 PHP를 사용하고 있습니다. 안전하고 빠른 암호 암호화 시스템을 원합니다. 암호를 백만 번 해싱하면 더 안전할 수 있지만 더 느릴 수도 있습니다. 속도와 안전 사이의 균형을 잘 맞추는 방법은 무엇입니까? 또한 결과가 일정한 수의 문자를 갖는 것을 선호합니다.
- 해싱 메커니즘은 PHP에서 사용할 수 있어야 합니다.
- 안전해야합니다
- 소금을 사용할 수 있습니다. (이 경우 모든 소금이 다 좋은가? 좋은 소금을 만드는 방법은 없을까?)
또한 데이터베이스에 두 개의 필드(예: MD5를 사용하는 필드와 SHA를 사용하는 필드)를 저장해야 합니까? 그것이 더 안전해질까요 아니면 안전하지 않게 만들까요?
충분히 명확하지 않은 경우 안전하고 빠른 암호 보호 메커니즘을 사용하기 위해 어떤 해싱 기능을 사용하고 좋은 솔트를 선택하는 방법을 알고 싶습니다.
내 질문을 제대로 다루지 못하는 관련 질문:
PHP에서 SHA와 MD5의 차이점은 무엇입니까?
단순 암호 암호화
asp.net용 키, 비밀번호를 저장하는 안전한 방법
Tomcat 5.5에서 솔트 암호를 구현하는 방법
면책 조항 : 이 답변은 2008년에 작성되었습니다.
그 이후로 PHP는 우리에게 password_hash
및 password_verify
를 제공했으며 도입 이후 권장되는 비밀번호 해싱 및 확인 방법입니다.
대답의 이론은 여전히 좋은 읽을 거리입니다.
TL;DR
하지마
- 사용자가 암호에 입력할 수 있는 문자를 제한하지 마십시오. 바보들만 이런 짓을 합니다.
- 암호의 길이를 제한하지 마십시오. 사용자가 supercalifragilisticexpialidocious가 포함된 문장을 원하면 사용을 막지 마십시오.
- 비밀번호에서 HTML 및 특수 문자를 제거하거나 이스케이프 처리하지 마십시오.
- 사용자의 암호를 일반 텍스트로 저장하지 마십시오.
- 사용자가 비밀번호를 잃어버렸고 임시 비밀번호를 보낸 경우를 제외하고 사용자에게 비밀번호를 이메일로 보내지 마십시오.
- 절대 어떤 방식으로든 암호를 기록하지 마십시오.
- SHA1 , MD5 또는 SHA256으로 비밀번호를 해시하지 마십시오! 최신 크래커 는 초당 600억 및 1800억 해시를 초과할 수 있습니다(각각).
- bcrypt와 hash() 의 원시 출력을 혼합하지 마십시오. 16진수 출력을 사용하거나 base64_encode를 사용하십시오. (이것은 보안을 심각하게 약화시킬 수
\0
을 포함할 수 있는 모든 입력에 적용됩니다.)
도스
- 가능하면 scrypt를 사용하십시오. 할 수 없으면 bcrypt하십시오.
- SHA2 해시와 함께 bcrypt 또는 scrypt를 사용할 수 없는 경우 PBKDF2를 사용하십시오.
- 데이터베이스가 손상되면 모든 사람의 비밀번호를 재설정합니다.
- 합리적인 8-10자의 최소 길이를 구현하고 최소 1개의 대문자, 1개의 소문자, 숫자 및 기호가 필요합니다. 이렇게 하면 암호의 엔트로피가 향상되어 크랙이 더 어려워집니다. (일부 토론에 대해서는 "좋은 암호는 무엇입니까?" 섹션을 참조하십시오.)
어쨌든 해시 암호를 사용하는 이유는 무엇입니까?
암호 해싱의 목적은 간단합니다. 데이터베이스를 손상시켜 사용자 계정에 대한 악의적인 액세스를 방지하는 것입니다. 따라서 암호 해싱의 목표는 해커나 크래커가 일반 텍스트 암호를 계산하는 데 너무 많은 시간이나 비용을 들이는 것을 방지하는 것입니다. 그리고 시간/비용은 당신의 무기고에서 최고의 억제력입니다.
사용자 계정에 대해 훌륭하고 강력한 해시를 원하는 또 다른 이유는 시스템의 모든 암호를 변경할 수 있는 충분한 시간을 주기 위해서입니다. 데이터베이스가 손상된 경우 데이터베이스의 모든 암호를 변경하지 않더라도 최소한 시스템을 잠그는 데 충분한 시간이 필요합니다.
Whitehat Security의 CTO인 Jeremiah Grossman은 최근 암호를 복구한 후 자신의 암호 보호를 무차별 대입해야 하는 White Hat Security 블로그에 다음과 같이 말했습니다.
흥미롭게도 이 악몽을 겪으면서 암호 크래킹, 저장 및 복잡성에 대해 몰랐던 많은 것을 배웠습니다. 암호 저장이 암호 복잡성보다 훨씬 더 중요한 이유를 알게 되었습니다. 암호가 저장되는 방법을 모르는 경우 실제로 의존할 수 있는 것은 복잡성뿐입니다. 이것은 암호 및 암호 전문가에게 일반적인 지식일 수 있지만 평균적인 InfoSec 또는 웹 보안 전문가에게는 매우 의심스럽습니다.
(나를 강조한다.)
어쨌든 좋은 암호는 무엇입니까?
엔트로피 . (내가 Randall의 관점에 완전히 동의하는 것은 아닙니다.)
간단히 말해서 엔트로피는 암호 내에서 얼마나 많은 변화가 있는지입니다. 비밀번호가 소문자 로마자일 경우 26자입니다. 그것은 많은 변화가 아닙니다. 영숫자 암호는 36자로 더 좋습니다. 그러나 기호와 함께 대문자와 소문자를 허용하는 것은 대략 96자입니다. 그냥 편지보다 훨씬 낫습니다. 한 가지 문제는 비밀번호를 기억하기 쉽게 만들기 위해 엔트로피를 줄이는 패턴을 삽입한다는 것입니다. 앗!
암호 엔트로피는 쉽게 근사 됩니다. 전체 범위의 ASCII 문자(약 96개의 입력 가능한 문자)를 사용하면 문자당 6.6개의 엔트로피가 생성되며, 이는 암호에 대해 8개의 문자로 미래 보안을 위해 여전히 너무 낮습니다(엔트로피의 52.679비트). 그러나 좋은 소식은 더 긴 암호와 유니코드 문자가 있는 암호는 실제로 암호의 엔트로피를 증가시키고 해독하기 어렵게 만든다는 것입니다.
Crypto StackExchange 사이트에서 암호 엔트로피에 대한 더 긴 토론이 있습니다. 구글 검색을 잘하면 많은 결과가 나옵니다.
코멘트에서 나는 X 많은 문자, 숫자, 기호 등으로 X 길이의 암호 정책을 적용, 실제로 암호 방식은 예측함으로써 엔트로피 감소시킬 수 있다고 지적 @popnoodles, 함께 이야기했다. 동의합니다. 무작위성은 가능한 한 진정으로 무작위로 항상 가장 안전하지만 가장 기억에 남는 솔루션입니다.
내가 말할 수 있는 한, 세계 최고의 비밀번호를 만드는 것은 Catch-22입니다. 기억나지 않거나, 너무 예측 가능하거나, 너무 짧거나, 너무 많은 유니코드 문자(Windows/모바일 장치에서 입력하기 어려움), 너무 긴 등입니다. 어떤 암호도 우리의 목적에 진정으로 적합하지 않으므로 암호를 보호해야 합니다. 포트 녹스에 있었다.
모범 사례
Bcrypt 및 scrypt 는 현재 모범 사례입니다. Scrypt 는 시간이 지나면 bcrypt보다 나을 것이지만 Linux/Unix 또는 웹 서버에서 표준으로 채택되지 않았으며 아직 게시된 알고리즘에 대한 심층적인 검토도 없습니다. 그러나 여전히 알고리즘의 미래는 유망해 보입니다. Ruby로 작업 하는 경우 도움이 될 scrypt gem 이 있으며 Node.js에는 이제 자체 scrypt 패키지가 있습니다. Scrypt 확장 또는 Libsodium 확장(둘 모두 PECL에서 사용 가능)을 통해 PHP에서 Scrypt를 사용할 수 있습니다.
bcrypt를 사용하는 방법을 이해하거나 자신에게 좋은 래퍼를 찾거나 레거시 구현을 위해 PHPASS 와 같은 것을 사용 하려면 crypt 함수에 대한 문서를 읽는 것이 좋습니다. 15~18회가 아니라면 최소 12회의 bcrypt를 권장합니다.
bcrypt가 가변 비용 메커니즘과 함께 복어의 주요 일정만 사용한다는 것을 알았을 때 bcrypt 사용에 대한 생각이 바뀌었습니다. 후자는 복어의 이미 값비싼 키 일정을 늘려서 암호를 무차별 대입하는 비용을 증가시킵니다.
평균 관행
이 상황을 더 이상 상상할 수 없습니다. PHPASS 는 PHP 3.0.18 ~ 5.3을 지원하므로 상상할 수 있는 거의 모든 설치에서 사용할 수 있습니다. 환경이 bcrypt를 지원하는지 확실하지 않은 경우 사용해야 합니다.
그러나 bcrypt 또는 PHPASS를 전혀 사용할 수 없다고 가정합니다. 그럼?
환경/응용 프로그램/사용자 인식이 허용할 수 있는 최대 라운드 수로 PDKBF2 를 구현해 보십시오. 내가 추천하는 가장 낮은 숫자는 2500 라운드입니다. 또한 작업을 재현하기 어렵게 만드는 데 사용할 수 있는 경우 hash_hmac() 을 사용해야 합니다.
미래의 관행
PHP 5.5에 등장하는 것은 bcrypt 작업의 모든 고통을 추상화 하는 완전한 암호 보호 라이브러리입니다. 우리 대부분은 가장 일반적인 환경, 특히 공유 호스트에서 PHP 5.2 및 5.3에 갇혀 있지만 @ircmaxell은 PHP 5.3.7과 역호환되는 향후 API에 대한 호환성 계층을 구축했습니다.
암호화 요약 및 면책조항
실제로 해시된 암호를 해독 하는 데 필요한 계산 능력은 존재하지 않습니다. 컴퓨터가 암호를 "크랙"하는 유일한 방법은 암호를 다시 만들고 암호를 보호하는 데 사용되는 해싱 알고리즘을 시뮬레이션하는 것입니다. 해시의 속도는 무차별 대입이 가능한 능력과 선형적으로 관련이 있습니다. 설상가상으로 대부분의 해시 알고리즘은 더 빠르게 수행하기 위해 쉽게 병렬화할 수 있습니다. 이것이 bcrypt 및 scrypt와 같은 비용이 많이 드는 구성표가 중요한 이유입니다.
당신이 눈 앞에 사용자를 보호하기 위해 최선의 노력을해야합니다 있도록 가능한 모든 공격 위협이나 도로를 예견하고, 수 없습니다. 그렇지 않으면 너무 늦을 때까지 공격을 받았다는 사실조차 놓칠 수 있으며 책임은 귀하에게 있습니다 . 그런 상황을 피하려면 처음부터 편집증적인 행동을 하십시오. 자신의 소프트웨어(내부적으로)를 공격하고 사용자 자격 증명을 도용하거나 다른 사용자의 계정을 수정하거나 데이터에 액세스하려고 시도합니다. 시스템의 보안을 테스트하지 않으면 자신 외에 다른 사람을 비난할 수 없습니다.
마지막으로: 저는 암호학자가 아닙니다. 내가 말한 것은 모두 내 의견이지만, 나는 그것이 좋은 상식과 많은 독서에 기초한 것이라고 생각합니다. 가능한 한 편집증적이 되고 가능한 한 침입하기 어렵게 만든 다음, 여전히 걱정이 되는 경우 화이트햇 해커나 암호 작성자에게 연락하여 코드/시스템에 대해 어떻게 말하는지 확인하십시오.
Robert K훨씬 더 짧고 안전한 대답 - 자신의 암호 메커니즘을 전혀 작성하지 말고 시도되고 테스트된 메커니즘을 사용하십시오.
- PHP 5.5 이상: password_hash() 는 좋은 품질이며 PHP 코어의 일부입니다.
- PHP 4.x(구식): OpenWall의 phpass 라이브러리는 WordPress, Drupal 등에서 사용되는 대부분의 사용자 정의 코드보다 훨씬 뛰어납니다.
대부분의 프로그래머는 취약점을 도입하지 않고 암호화 관련 코드를 안전하게 작성할 수 있는 전문 지식이 없습니다.
빠른 자체 테스트: 암호 확장이란 무엇이며 얼마나 많은 반복을 사용해야 합니까? 답을 모른다면 password_hash()
사용해야 합니다. 암호 확장은 이제 훨씬 빠른 CPU와 GPU 및 FPGA 를 사용하여 초당 수십억 개의 추측 속도로 암호를 해독하기 때문에 암호 메커니즘의 중요한 기능이기 때문입니다. (GPU 포함).
2012년 기준으로 5대의 데스크탑 PC에 설치된 25개의 GPU를 사용하여 6시간 안에 모든 8자 Windows 암호를 해독할 수 있습니다. 이것은 무차별 대입입니다. 즉 , 특수 문자를 포함하여 모든 8자 Windows 암호를 열거하고 확인하는 것이며 사전 공격이 아닙니다. 최신 GPU를 사용하면 물론 더 많은 암호를 해독하거나 더 적은 수의 GPU를 사용할 수 있습니다. 또는 합리적인 비용으로 몇 시간 동안 클라우드에서 GPU를 임대할 수 있습니다.
또한 일반 CPU에서 실행되고 매우 빠른 Windows 암호에 대한 많은 레인보우 테이블 공격이 있습니다.
이 모든 것은 Windows 가 Windows 10에서도 여전히 암호를 솔트하거나 확장하지 않기 때문입니다. 이것은 2021년에도 여전히 유효합니다. Microsoft와 같은 실수를 하지 마십시오!
또한보십시오:
-
password_hash()
또는 phpass
가 가장 좋은 방법인 이유에 대해 자세히 설명하는 훌륭한 답변입니다. - bcrypt, scrypt 및 PBKDF2를 포함한 주요 알고리즘에 대해 권장되는 '작업 요소'(반복 횟수)를 제공하는 좋은 블로그 기사.
RichVel나는 암호를 두 가지 다른 방식으로 저장하지 않을 것입니다. 왜냐하면 시스템은 최소한 사용 중인 해시 알고리즘 중 가장 약한 것만큼 취약하기 때문입니다.
Tom HaighPHP 5.5부터 PHP에는 암호 해싱 및 확인을 위한 간단하고 안전한 기능인 password_hash() 및 password_verify()가 있습니다.
$password = 'anna'; $hash = password_hash($password, PASSWORD_DEFAULT); $expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20)); password_verify('anna', $hash); //Returns true password_verify('anna', $expensiveHash); //Also returns true password_verify('elsa', $hash); //Returns false
경우 password_hash()
사용되며, 이는 임의의 염을 생성하고, 출력 된 해시를 포함한다 (사용 된 비용 및 알고리즘에 따라). password_verify()
그 해시 판독에 사용되는 염 및 암호화 방식을 결정하고, 검증하고이를 대 제공된 일반 텍스트 암호.
PASSWORD_DEFAULT
제공하면 설치된 PHP 버전의 기본 해싱 알고리즘을 사용하도록 PHP에 지시합니다. 정확히 어떤 알고리즘이 미래 버전에서 시간이 지남에 따라 변경되어 항상 가장 강력한 가용 알고리즘 중 하나가 될 것인지를 의미합니다.
비용이 증가하면(기본값은 10) 해시를 무차별 대입하기가 더 어려워지지만 해시를 생성하고 이에 대한 암호를 확인하는 것이 서버의 CPU에 더 많은 작업을 수행할 것임을 의미합니다.
기본 해싱 알고리즘이 변경될 수 있지만 사용된 알고리즘이 해시에 저장되고 password_verify()
선택하기 때문에 이전 해시는 계속해서 잘 검증됩니다.
AlliterativeAlice질문에 대한 답변을 받았지만 해싱에 사용되는 솔트는 무작위여야 하며 첫 번째 답변에서 제안한 이메일 주소와 같지 않아야 함을 반복하고 싶습니다.
자세한 설명은 http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/에서 확인할 수 있습니다.
최근에 나는 임의의 비트로 소금을 넣은 암호 해시가 추측할 수 있거나 알려진 소금으로 소금을 넣은 것보다 더 안전한지 여부에 대해 토론했습니다. 봅시다: 암호를 저장하는 시스템과 임의의 솔트를 저장하는 시스템이 손상된 경우 공격자는 솔트뿐만 아니라 해시에도 액세스할 수 있으므로 솔트가 무작위인지 여부는 중요하지 않습니다. 공격자는 해시를 해독하기 위해 미리 계산된 레인보우 테이블을 생성할 수 있습니다. 여기에 흥미로운 부분이 있습니다. 미리 계산된 테이블을 생성하는 것은 그리 간단하지 않습니다. WPA 보안 모델의 예를 살펴보겠습니다. WPA 암호는 실제로 무선 액세스 포인트로 전송되지 않습니다. 대신 SSID(Linksys, Dlink 등과 같은 네트워크 이름)로 해시됩니다. 이것이 어떻게 작동하는지에 대한 아주 좋은 설명이 여기에 있습니다. 해시에서 비밀번호를 검색하려면 비밀번호와 솔트(네트워크 이름)를 알아야 합니다. Church of Wifi는 이미 상위 1000개의 SSID와 약 100만 개의 비밀번호가 있는 해시 테이블을 미리 계산했습니다. 모든 테이블의 크기는 약 40GB입니다. 사이트에서 읽을 수 있듯이 누군가 3일 동안 15개의 FGPA 어레이를 사용하여 이러한 테이블을 생성했습니다. 피해자가 SSID를 "a387csf3"으로, 비밀번호를 "123456"으로 사용하고 있다고 가정하면 해당 테이블에 의해 크랙됩니까? 아니요! .. 그럴 순 없어. 암호가 약하더라도 테이블에는 SSID a387csf3에 대한 해시가 없습니다. 이것이 무작위 소금의 아름다움입니다. 미리 계산된 테이블에서 번성하는 크래커를 억제할 것입니다. 결단력 있는 해커를 막을 수 있습니까? 아마 아닐 것입니다. 그러나 임의의 소금을 사용하면 추가 방어 계층이 제공됩니다. 이 주제에 대해 이야기하는 동안 임의의 솔트를 별도의 시스템에 저장하는 추가 이점에 대해 논의하겠습니다. 시나리오 #1: 암호 해시는 시스템 X에 저장되고 해싱에 사용되는 솔트 값은 시스템 Y에 저장됩니다. 이러한 솔트 값은 추측할 수 있거나 알려져 있습니다(예: 사용자 이름). 시나리오 #2: 암호 해시는 시스템 X에 저장되고 솔트 값은 다음 작업에 사용됩니다. 해싱은 시스템 Y에 저장됩니다. 이러한 솔트 값은 무작위입니다. 추측할 수 있듯이 시스템 X가 손상된 경우 별도의 시스템에서 임의의 솔트를 사용하는 것이 큰 이점이 있습니다(시나리오 #2). 공격자는 해시를 해독할 수 있도록 덧셈 값을 추측해야 합니다. 32비트 솔트를 사용하면 추측된 각 암호에 대해 2^32= 4,294,967,296(약 42억)의 반복이 필요할 수 있습니다.
Gaurav Kumarcrypt()
주위에 래퍼를 제공하는 암호 해싱 API 가 포함되어 있다는 점을 지적하고 싶습니다. 이 API는 암호 해시를 해시, 확인 및 다시 해시하는 작업을 크게 단순화합니다. 저자는 또한 발표했다 호환 기능 팩 (당신은 단순히 하나의 password.php 파일의 형태로 require
이상 PHP 5.3.7과를 사용하는 사람들을 위해, 사용을) 지금이 권리를 사용하고 싶습니다.
지금은 BCRYPT만 지원하지만 다른 암호 해싱 기술을 포함하도록 쉽게 확장하는 것을 목표로 하고 기술과 비용이 해시의 일부로 저장되기 때문에 선호하는 해싱 기술/비용을 변경해도 현재 해시가 무효화되지 않습니다. 자동으로 검증할 때 올바른 기술/비용을 사용합니다. 또한 자신의 솔트를 명시적으로 정의하지 않은 경우 "보안" 솔트 생성을 처리합니다.
API는 네 가지 기능을 제공합니다.
-
password_get_info()
- 주어진 해시에 대한 정보를 반환합니다. -
password_hash()
- 비밀번호 해시 생성 -
password_needs_rehash()
- 주어진 해시가 주어진 옵션과 일치하는지 확인합니다. 해시가 현재 기술/비용 체계를 준수하는지 확인하는 데 유용하여 필요한 경우 다시 해시할 수 있습니다. -
password_verify()
- 암호가 해시와 일치하는지 확인합니다.
현재 이 함수는 PASSWORD_BCRYPT 및 PASSWORD_DEFAULT 암호 상수를 허용하며, 이는 현재 동의어입니다. 차이점은 PASSWORD_DEFAULT가 "더 새롭고 강력한 해싱 알고리즘이 지원될 때 최신 PHP 릴리스에서 변경될 수 있음"입니다. 로그인 시 PASSWORD_DEFAULT 및 password_needs_rehash()를 사용하면(필요한 경우 다시 해시) 해시가 거의 또는 전혀 작업 없이 무차별 대입 공격에 대해 합리적으로 탄력적임을 보장해야 합니다.
편집 : 나는 이것이 Robert K의 답변에 간략하게 언급되어 있음을 깨달았습니다. 보안을 모르는 사람들을 위해 작동 방식과 사용 용이성에 대한 추가 정보를 제공한다고 생각하기 때문에 이 답변을 여기에 남길 것입니다.
JonoCoetzee저는 거의 모든 PHP 프로젝트에서 매우 쉽게 구현할 수 있는 간단한 단일 파일 PHP 클래스인 Phpass를 사용하고 있습니다. H를 참조하십시오.
기본적으로 Phpass에서 구현된 가장 강력한 사용 가능한 암호화를 사용했습니다. 이 암호화는 bcrypt
이며 Wordpress와 같은 프레임워크에 역호환성을 제공하기 위해 MD5까지 다른 암호화로 폴백합니다.
반환된 해시는 그대로 데이터베이스에 저장될 수 있다. 해시 생성을 위한 샘플 용도는 다음과 같습니다.
$t_hasher = new PasswordHash(8, FALSE); $hash = $t_hasher->HashPassword($password);
암호를 확인하려면 다음을 사용할 수 있습니다.
$t_hasher = new PasswordHash(8, FALSE); $check = $t_hasher->CheckPassword($password, $hash);
rabudde기억해야 할 사항
PHP용 비밀번호 암호화에 대해 많은 말이 나왔고 대부분은 매우 좋은 조언이지만 비밀번호 암호화를 위해 PHP를 사용하는 프로세스를 시작하기 전에 다음이 구현되었거나 구현할 준비가 되었는지 확인하십시오.
섬기는 사람
항구
아무리 암호화를 잘해도 PHP와 DB를 실행하는 서버를 제대로 보호하지 못하면 아무런 소용이 없습니다. 대부분의 서버는 비교적 동일한 방식으로 작동하며 ftp 또는 셸을 통해 원격으로 액세스할 수 있도록 할당된 포트가 있습니다. 활성 상태인 원격 연결의 기본 포트를 변경했는지 확인하십시오. 이렇게 하지 않으면 사실상 공격자가 시스템에 액세스하는 단계를 한 단계 덜 수행하게 됩니다.
사용자 이름
세상에서 좋은 모든 것을 위해 사용자 이름 admin, root 또는 이와 유사한 것을 사용하지 마십시오. 또한 유닉스 기반 시스템을 사용하는 경우 루트 계정 로그인에 액세스할 수 있도록 설정하지 마십시오. 항상 sudo 전용이어야 합니다.
비밀번호
사용자에게 해킹을 피하기 위해 좋은 암호를 만들라고 지시하고 똑같이 하십시오. 뒷문을 활짝 열어놓은 상태에서 앞문을 잠그려고 온갖 수고를 들인다는 것이 무슨 소용인가.
데이터 베이스
섬기는 사람
이상적으로는 DB와 APPLICATION이 별도의 서버에 있기를 원합니다. 비용으로 인해 항상 가능한 것은 아니지만 공격자가 시스템에 완전히 액세스하려면 두 단계를 거쳐야 하므로 어느 정도 안전합니다.
사용자
항상 응용 프로그램에 DB에 액세스할 수 있는 고유한 계정이 있어야 하고 필요한 권한만 부여하십시오.
그런 다음 응용 프로그램이 아닌 서버의 어느 곳에도 저장되지 않은 별도의 사용자 계정을 만드십시오.
항상 그렇듯이 루트 또는 이와 유사한 것을 만들지 마십시오.
비밀번호
모든 좋은 암호와 동일한 지침을 따르십시오. 또한 동일한 시스템의 SERVER 또는 DB 계정에서 동일한 비밀번호를 재사용하지 마십시오.
PHP
비밀번호
절대로 DB에 비밀번호를 저장하지 말고 해시와 고유한 솔트를 저장하십시오. 그 이유는 나중에 설명하겠습니다.
해싱
단방향 해싱!!!!!!!!! 같은 방법으로 두 해시를 비교합니다. 즉, 공격자가 DB에 액세스하더라도 실제 암호가 무엇인지 모르고 결과 해시만 알 수 있습니다. 이는 최악의 시나리오에서 사용자를 위한 더 많은 보안을 의미합니다.
좋은 해싱 기능이 많이 있지만( password_hash
, hash
등...) 해시가 효과적이려면 좋은 알고리즘을 선택해야 합니다. (bcrypt 및 이와 유사한 알고리즘은 괜찮은 알고리즘입니다.)
해싱 속도가 핵심인 경우 느릴수록 무차별 대입 공격에 대한 저항이 커집니다.
해싱에서 가장 흔한 실수 중 하나는 해시가 사용자에게 고유하지 않다는 것입니다. 이것은 주로 염이 고유하게 생성되지 않기 때문입니다.
염장
암호는 항상 해시 전에 솔트 처리해야 합니다. 솔팅은 비밀번호에 임의의 문자열을 추가하여 유사한 비밀번호가 DB에서 동일하게 나타나지 않도록 합니다. 그러나 소금이 각 사용자에게 고유하지 않은 경우(즉, 하드 코딩된 소금을 사용하는 경우) 소금을 거의 쓸모 없게 만든 것입니다. 일단 공격자가 하나의 비밀번호 솔트를 알아내면 모든 솔트를 가지고 있기 때문입니다.
솔트를 생성할 때 솔트하는 암호에 고유한지 확인한 다음 완료된 해시와 솔트를 모두 DB에 저장합니다. 이렇게 하면 공격자가 액세스 권한을 얻기 전에 각 솔트와 해시를 개별적으로 크랙해야 합니다. 이는 공격자에게 더 많은 작업과 시간을 의미합니다.
비밀번호를 만드는 사용자
사용자가 프론트엔드를 통해 암호를 생성하는 경우 이는 서버로 보내야 함을 의미합니다. 이는 암호화되지 않은 암호가 서버로 전송되고 공격자가 듣고 액세스할 수 있는 경우 PHP의 모든 보안이 가치가 없다는 것을 의미하기 때문에 보안 문제가 발생합니다. 항상 데이터를 안전하게 전송하십시오. 이것은 SSL을 통해 이루어지지만 SSL이 완벽하지 않더라도 지치십시오(OpenSSL의 Heartbleed 결함이 그 예입니다).
또한 사용자가 보안 암호를 만들도록 하십시오. 간단하고 항상 수행해야 하며 사용자는 결국 이에 대해 감사하게 생각합니다.
마지막으로, 어떠한 보안 조치도 취하지 않아도 100% 안전하지 않으며, 보호하는 기술이 더 발전할수록 공격이 더 고도화됩니다. 그러나 이러한 단계를 따르면 사이트가 더 안전해지고 공격자가 쫓는 것이 훨씬 덜 바람직합니다.
다음은 비밀번호에 대한 해시와 솔트를 쉽게 생성하는 PHP 클래스입니다.
http://git.io/mSJqpw
wmfranciaGoogle은 SHA256을 PHP에서 사용할 수 있다고 말합니다.
반드시 소금을 사용해야 합니다. 임의의 바이트를 사용하는 것이 좋습니다(문자와 숫자로 제한하지 않음). 일반적으로 선택하는 기간이 길수록 안전하고 느려집니다. 64바이트는 괜찮을 것 같아요.
AticusFinch결국, 이중 해싱은 수학적으로 아무런 이점도 제공하지 않습니다. 그러나 실제로는 레인보우 테이블 기반 공격을 방지하는 데 유용합니다. 다시 말해, 솔트를 사용하여 해싱하는 것보다 더 많은 이점이 없습니다. 이는 애플리케이션이나 서버에서 프로세서 시간이 훨씬 적게 소요됩니다.
Maxhttps://crackstation.net/hashing-security.htm 에서 이 문제에 대한 완벽한 주제를 찾았습니다. 이점을 얻으시기 바랍니다. 여기에 시간 기반 공격에 대한 예방 기능도 제공하는 소스 코드가 있습니다.
<?php /* * Password hashing with PBKDF2. * Author: havoc AT defuse.ca * www: https://defuse.ca/php-pbkdf2.htm */ // These constants may be changed without breaking existing hashes. define("PBKDF2_HASH_ALGORITHM", "sha256"); define("PBKDF2_ITERATIONS", 1000); define("PBKDF2_SALT_BYTES", 24); define("PBKDF2_HASH_BYTES", 24); define("HASH_SECTIONS", 4); define("HASH_ALGORITHM_INDEX", 0); define("HASH_ITERATION_INDEX", 1); define("HASH_SALT_INDEX", 2); define("HASH_PBKDF2_INDEX", 3); function create_hash($password) { // format: algorithm:iterations:salt:hash $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM)); return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" . $salt . ":" . base64_encode(pbkdf2( PBKDF2_HASH_ALGORITHM, $password, $salt, PBKDF2_ITERATIONS, PBKDF2_HASH_BYTES, true )); } function validate_password($password, $good_hash) { $params = explode(":", $good_hash); if(count($params) < HASH_SECTIONS) return false; $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]); return slow_equals( $pbkdf2, pbkdf2( $params[HASH_ALGORITHM_INDEX], $password, $params[HASH_SALT_INDEX], (int)$params[HASH_ITERATION_INDEX], strlen($pbkdf2), true ) ); } // Compares two strings $a and $b in length-constant time. function slow_equals($a, $b) { $diff = strlen($a) ^ strlen($b); for($i = 0; $i < strlen($a) && $i < strlen($b); $i++) { $diff |= ord($a[$i]) ^ ord($b[$i]); } return $diff === 0; } /* * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt * $algorithm - The hash algorithm to use. Recommended: SHA256 * $password - The password. * $salt - A salt that is unique to the password. * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000. * $key_length - The length of the derived key in bytes. * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise. * Returns: A $key_length-byte key derived from the password and salt. * * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt * * This implementation of PBKDF2 was originally created by https://defuse.ca * With improvements by http://www.variations-of-shadow.com */ function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) { $algorithm = strtolower($algorithm); if(!in_array($algorithm, hash_algos(), true)) die('PBKDF2 ERROR: Invalid hash algorithm.'); if($count <= 0 || $key_length <= 0) die('PBKDF2 ERROR: Invalid parameters.'); $hash_length = strlen(hash($algorithm, "", true)); $block_count = ceil($key_length / $hash_length); $output = ""; for($i = 1; $i <= $block_count; $i++) { // $i encoded as 4 bytes, big endian. $last = $salt . pack("N", $i); // first iteration $last = $xorsum = hash_hmac($algorithm, $last, $password, true); // perform the other $count - 1 iterations for ($j = 1; $j < $count; $j++) { $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); } $output .= $xorsum; } if($raw_output) return substr($output, 0, $key_length); else return bin2hex(substr($output, 0, $key_length)); } ?>
Jason OOO나는 일반적으로 사용자 ID(또는 다른 사용자별 정보)와 함께 SHA1과 salt를 사용하고 때로는 추가로 상수 salt를 사용합니다(그래서 소금에 2 부분이 있습니다).
SHA1은 이제 다소 손상된 것으로 간주되지만 MD5보다 훨씬 낮은 수준입니다. 소금(모든 소금)을 사용하면 일반 레인보우 테이블 을 사용하여 해시를 공격하는 것을 방지할 수 있습니다(일부 사람들은 해시를 검색하여 일종의 레인보우 테이블로 Google을 사용하는 데 성공하기도 했습니다). 공격자는 솔트를 사용하여 무지개 테이블을 생성할 수 있으므로 사용자별 솔트를 포함해야 합니다. 그렇게 하면 전체 시스템에 대한 레인보우 테이블이 아니라 시스템의 모든 레코드에 대해 레인보우 테이블을 생성해야 합니다! 이러한 유형의 염분을 사용하면 MD5도 상당히 안전합니다.
rmeador예측 가능한 미래에는 SHA1 과 소금으로 충분해야 합니다(물론 Fort Knox 용으로 코딩하는지 또는 쇼핑 목록에 대한 로그인 시스템을 코딩하는지에 따라 다름). SHA1이 충분하지 않으면 SHA256을 사용하십시오.
솔트의 개념은 말하자면 해싱 결과를 균형에서 벗어나게 하는 것입니다. 예를 들어 빈 문자열의 MD5 해시는 d41d8cd98f00b204e9800998ecf8427e
것으로 알려져 있습니다. 따라서 충분한 메모리를 가진 사람이 해당 해시를 보고 그것이 빈 문자열의 해시라는 것을 알게 된다면. 문자열이 (문자열 "로 말하자면 소금에 절인 경우 그러나 MY_PERSONAL_SALT
")는 '빈 문자열'(즉, "해시 MY_PERSONAL_SALT
")가된다 aeac2612626724592271634fb14d3ea6
역 추적에 따라서 비 명백한. 내가 말하려는 것은 소금을 사용하지 않는 것보다 소금을 사용하는 것이 더 낫다는 것입니다. 따라서 어떤 소금을 사용해야 하는지 아는 것은 그다지 중요하지 않습니다.
실제로 이 작업을 수행하는 웹 사이트가 있습니다. (md5) 해시를 제공할 수 있으며 특정 해시를 생성하는 알려진 일반 텍스트를 뱉어냅니다. 일반 md5 해시를 저장하는 데이터베이스에 액세스할 수 있는 경우 이러한 서비스에 대한 관리자의 해시를 입력하고 로그인하는 것은 사소한 일입니다. 그러나 암호가 솔트화된 경우 그러한 서비스는 효과적인.
또한 이중 해싱은 결과 공간을 줄이기 때문에 일반적으로 나쁜 방법으로 간주됩니다. 인기 있는 모든 해시는 고정 길이입니다. 따라서 이 고정 길이의 유한한 값만 가질 수 있으며 결과는 덜 다양해집니다. 이것은 다른 형태의 염장으로 간주 될 수 있지만 권장하지는 않습니다.
Henrik Paul좋아, fity에서 우리는 소금 소금이 필요하므로 고유해야하므로 생성하게하십시오.
/** * Generating string * @param $size * @return string */ function Uniwur_string($size){ $text = md5(uniqid(rand(), TRUE)); RETURN substr($text, 0, $size); }
또한 해시가 필요합니다. sha512를 사용하고 있습니다. 최고이며 PHP에 있습니다.
/** * Hashing string * @param $string * @return string */ function hash($string){ return hash('sha512', $string); }
이제 이 기능을 사용하여 안전한 암호를 생성할 수 있습니다.
// generating unique password $password = Uniwur_string(20); // or you can add manual password // generating 32 character salt $salt = Uniwur_string(32); // now we can manipulate this informations // hashin salt for safe $hash_salt = hash($salt); // hashing password $hash_psw = hash($password.$hash_salt);
이제 $hash_psw 변수 값과 $salt 변수를 데이터베이스에 저장해야 합니다.
승인을 위해 동일한 단계를 사용합니다...
고객의 비밀번호를 보호하는 가장 좋은 방법입니다...
마지막 2단계에서 Ps 자신의 알고리즘을 사용할 수 있지만 나중에 사용자에게 권한을 부여해야 할 때 이 해시된 암호를 생성할 수 있는지 확인하십시오...
shalvasoft출처 : http:www.stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords