복붙노트

PHP 암호를위한 안전한 해시 및 소금

PHP

PHP 암호를위한 안전한 해시 및 소금

현재 MD5가 부분적으로 안전하지 않다고합니다. 이것을 고려하여 암호 보호에 사용할 메커니즘을 알고 싶습니다.

이 질문은 "이중 해싱"은 암호를 한 번 해시하는 것보다 덜 안전합니까? 여러 번 해시하는 것이 좋은 생각 일 수 있다고 제안하는 반면, 개별 파일에 대한 암호 보호를 구현하는 방법은 무엇입니까? 소금 사용을 제안합니다.

PHP를 사용하고 있습니다. 나는 안전하고 빠른 암호 암호화 시스템을 원한다. 백만 번 암호를 해싱하는 것이 더 안전 할 수도 있지만 느려질 수도 있습니다. 속도와 안전 사이의 균형을 어떻게 이루는가? 또한, 나는 그 결과가 일정한 수의 문자를 가지길 원합니다.

또한 데이터베이스에 두 개의 필드를 저장해야합니까 (하나는 MD5를 사용하고 다른 하나는 SHA를 사용합니다). 그것이 더 안전하거나 불공평하게 만들겠습니까?

내가 충분히 명확하지 않은 경우, 안전하고 빠른 암호 보호 메커니즘을 사용하기 위해 사용할 해싱 함수와 올바른 소금을 선택하는 방법을 알고 싶습니다.

내 질문에 대해 다루지 않는 관련 질문 :

PHP에서 SHA와 MD5의 차이점은 무엇입니까? 간단한 암호 암호화 asp.net에 대한 키, 암호 저장의 안전한 방법 Tomcat 5.5에서 소금에 절인 암호를 어떻게 구현합니까?

해결법

  1. ==============================

    1.

    암호 해시의 목적은 간단합니다. 데이터베이스를 손상시켜 사용자 계정에 대한 악의적 인 액세스를 방지합니다. 따라서 암호 해싱의 목표는 일반 텍스트 암호를 계산하는 데 너무 많은 시간이나 비용을 들여 해커 나 크래커를 막는 것입니다. 그리고 시간 / 비용이 당신의 무기고에서 가장 좋은 방어벽입니다.

    사용자 계정에 양호하고 강력한 해시가 필요한 또 다른 이유는 시스템의 모든 암호를 변경할 충분한 시간을 제공하기 위해서입니다. 데이터베이스가 손상된 경우 데이터베이스의 모든 암호를 변경하지 않으면 최소한 시스템을 잠글 수있는 충분한 시간이 필요합니다.

    화이트 햇 시큐리티의 CTO 인 Jeremiah Grossman은 최근 패스워드를 복구 한 후에 그의 블로그에서 패스워드 보호를 무차별 적으로 파괴해야한다고 말했다 :

    (강조 광산.)

    엔트로피. (Randall의 견해에 완전히 동의하지는 않습니다.)

    간단히 말해서, 엔트로피는 암호 내에 얼마나 많은 변화가 있는지입니다. 암호가 소문자 로마자 일 경우에만 26 문자입니다. 그다지 변하지 않습니다. 36 자리 문자로 된 영숫자 암호가 더 좋습니다. 그러나 대문자와 소문자를 허용하려면 약 96 자입니다. 그것은 단순한 편지보다 훨씬 낫습니다. 한 가지 문제는 암호를 기억하기 쉽도록 패턴을 삽입함으로써 엔트로피를 줄이는 것입니다. 죄송합니다.

    암호 엔트로피는 쉽게 접근 할 수 있습니다. 전체 ASCII 문자 (약 96 개의 문자)를 사용하면 암호 당 8 자의 엔트로피가 6.6의 엔트로피를 산출하여 향후 보안을 위해 여전히 너무 낮습니다 (52.679 비트의 엔트로피). 그러나 좋은 소식은 더 긴 패스워드와 유니 코드 문자로 된 패스워드로 패스워드의 엔트로피를 증가시키고 크랙을 어렵게 만드는 것입니다.

    Crypto StackExchange 사이트에서 암호 엔트로피에 대한 더 자세한 논의가 있습니다. 좋은 Google 검색은 또한 많은 결과를 보여줍니다.

    X에서 많은 문자, 숫자, 기호 등을 사용하여 X 길이의 암호 정책을 적용하면 실제로 암호 체계를보다 예측 가능하게 만들어 엔트로피를 줄일 수 있다고 지적한 @popnoodles와 의견을 나누었습니다. 나는 동의한다. 가능한 임의의 임의적 인 임의성은 항상 가장 안전하면서도 가장 기억에 남는 솔루션입니다.

    지금까지 말했듯이 세계 최고의 암호를 만드는 것은 Catch-22입니다. 너무 기억하기 쉽고, 예측할 수없고, 너무 짧고, 너무 많은 유니 코드 문자 (Windows / 모바일 장치에 입력하기 힘들다), 너무 길거나 등등. 우리의 목적을 위해 암호가 실제로 충분하지 않으므로 암호를 보호해야합니다. 포트 녹스에 있었다.

    Bcrypt와 scrypt는 현재의 베스트 프랙티스입니다. Scrypt는 시간상 bcrypt보다 좋지만 Linux / Unix 또는 웹 서버는 표준으로 채택하지 못했으며 아직 게시 된 알고리즘에 대한 심층적 인 검토는하지 않았습니다. 그러나 여전히 알고리즘의 미래는 유망 해 보인다. Ruby로 작업하는 경우 도움이 될만한 scrypt gem이 있습니다. 이제 Node.js에는 자체 scrypt 패키지가 있습니다. Scrypt 확장자 또는 Libsodium 확장자를 통해 PHP에서 Scrypt를 사용할 수 있습니다 (둘 다 PECL에서 사용 가능함).

    필자는 bcrypt를 사용하는 방법을 이해하거나 더 나은 래퍼를 찾거나 더 많은 레거시 구현을 위해 PHPASS와 같은 것을 사용하려는 경우 crypt 함수에 대한 설명서를 읽는 것이 좋습니다. 적어도 15 회에서 18 회까지는 bcrypt를 12 회 이상 권장합니다.

    나는 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와 같은 값 비싼 계획이 중요한지입니다.

    모든 위협이나 공격 경로를 미리 예측할 수는 없으므로 사용자를 최우선으로 보호해야합니다. 그렇게하지 않으면 너무 늦을 때까지 공격 당했다는 사실을 놓칠 수도 있습니다 ... 그리고 당신은 책임이 있습니다. 이러한 상황을 피하려면 편집증 환자로 시작하십시오. 자신의 소프트웨어를 공격하여 (내부적으로) 사용자 자격 증명을 도용하거나 다른 사용자의 계정을 수정하거나 데이터에 액세스하십시오. 시스템의 보안을 테스트하지 않으면 자신을 제외한 모든 사람을 탓할 수 없습니다.

    마지막으로 : 저는 암호 작성자가 아닙니다. 제가 말한 것은 제 의견이지만, 저는 그것이 좋은 올 상식과 ... 많은 독서에 근거한다고 생각합니다. 가능한 한 편집성에 빠져들고, 가능한 한 방해하지 못하게하고, 여전히 걱정이된다면, 화이트 햇 해커 또는 암호 작성자에게 연락하여 코드 / 시스템에 대한 의견을 확인하십시오.

  2. ==============================

    2.

    훨씬 짧고 안전한 대답 - 자신의 암호 메커니즘을 전혀 쓰지 말고, 시험되고 검증 된 메커니즘을 사용하십시오.

    대부분의 프로그래머는 취약성을 도입하지 않고도 암호 관련 코드를 안전하게 작성하는 전문 지식이 없습니다.

    빠른 셀프 테스트 : 패스워드 스트레칭이란 무엇이며 얼마나 많은 반복을 사용해야합니까? 대답을 모르는 경우 password_hash ()를 사용해야합니다. 암호 확장은 이제 훨씬 빠른 CPU와 GPU 및 FPGA를 사용하여 초당 수십억의 추세로 암호를 해독하여 암호 메커니즘의 중요한 기능입니다. (GPU 포함).

    예를 들어 5 대의 데스크탑 PC에 설치된 25 개의 GPU를 사용하여 8 시간 동안 8 자짜리 Windows 암호를 모두 해독 할 수 있습니다. 이는 특수 문자를 포함하여 8 자로 된 모든 Windows 암호를 열거하고 검사하며 사전 공격이 아니기 때문에 무차별 적입니다. 그것이 2012 년이었습니다. 2018 년에는 더 적은 수의 GPU를 사용하거나 25 GPU로 더 빨리 깰 수있었습니다.

    또한 일반적인 CPU에서 실행되는 Windows 암호에 많은 무지개 테이블 공격이 있으며 매우 빠릅니다. 이 모든 것은 Windows가 여전히 Windows 10에서도 암호를 늘리거나 늘리지 않기 때문입니다. Microsoft와 같은 실수를 저 지르지 마십시오!

    참조 :

  3. ==============================

    3.

    두 가지 방법으로 암호 해시를 저장하지 않을 것입니다. 시스템은 적어도 사용중인 해시 알고리즘 중 가장 약한 것만큼 취약하기 때문입니다.

  4. ==============================

    4.

    PHP 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 ()가 해당 알고리즘을 선택하기 때문에 오래된 해시는 계속 정상적으로 확인됩니다.

  5. ==============================

    5.

    질문에 대한 대답은 있었지만, 해싱에 사용 된 소금은 첫 번째 대답에서 제안 된 것처럼 전자 메일 주소와 무관하게 반복되어야한다고 반복하고 싶습니다.

    자세한 설명은 http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/에서 확인할 수 있습니다.

  6. ==============================

    6.

    PHP 5.5에는 crypt () 주위에 래퍼를 제공하는 암호 해시 API가 포함되어 있습니다. 이 API는 암호 해시의 해시, 확인 및 재 해싱 작업을 크게 단순화합니다. 저자는 PHP 5.3.7 이상을 사용하는 사람들을 위해 (지금 사용하고 싶은 password.php 파일 형태로) 호환성 팩을 발표했다.

    현재는 BCRYPT 만 지원하지만 다른 암호 해싱 기술을 포함하도록 쉽게 확장 할 수 있으며 기술 및 비용이 해시의 일부로 저장되므로 원하는 해싱 기법 / 비용을 변경해도 현재 해시가 무효화되지는 않습니다. 자동으로 유효성을 검사 할 때 정확한 기술 / 비용을 사용합니다. 또한 자신이 명시 적으로 정의하지 않으면 "안전한"소금 생성을 처리합니다.

    API는 네 가지 기능을 제공합니다.

    현재이 함수들은 현재 동의어 인 PASSWORD_BCRYPT와 PASSWORD_DEFAULT 암호 상수를 받아들입니다. 그 차이점은 PASSWORD_DEFAULT가 더 새롭고 강력한 해싱 알고리즘이 지원 될 때 새로운 PHP 릴리스에서 변경 될 수 있다는 것입니다. 로그인시 PASSWORD_DEFAULT 및 password_needs_rehash ()를 사용하여 (필요한 경우 다시 해싱) 해시 작업을 거의 또는 전혀하지 않고 무차별 공격에 적절하게 복원 할 수 있어야합니다.

    편집 : 나는 방금 로버트 케이의 대답에 간략하게 언급 된 것을 깨달았다. 나는 그것이 작동하는 방법과 보안을 모르는 사람들에게 제공되는 사용의 용이성에 대한 약간의 정보를 제공한다고 생각하기 때문에이 대답을 남겨 둘 것입니다.

  7. ==============================

    7.

    거의 모든 PHP 프로젝트에서 매우 쉽게 구현할 수있는 간단한 단일 파일 PHP 클래스 인 Phpass를 사용하고 있습니다. The 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);
    
  8. ==============================

    8.

    기억해야 할 것

    PHP에 대한 암호 암호화에 관해서는 많은 이야기가있었습니다. 대부분은 좋은 조언이지만, 암호 암호화를 위해 PHP를 사용하기 전에 다음을 구현하거나 구현할 준비가되어 있는지 확인하십시오.

    섬기는 사람

    포트

    PHP와 DB를 실행하는 서버를 안전하게 보호하지 않으면 암호화가 아무리 훌륭해도 모든 노력은 쓸모가 없습니다. 대부분의 서버는 상대적으로 동일한 방식으로 작동하며 ftp 또는 셸을 통해 원격으로 액세스 할 수 있도록 포트가 할당되어 있습니다. 원격 연결이 활성화 된 기본 포트를 변경하십시오. 이렇게하지 않으면 침입자가 실제로 시스템에 액세스하는 단계를 한 단계 단축 할 수 있습니다.

    사용자 이름

    세상에서 좋은 모든 것을 사용자 이름 admin, root 또는 유사한 것으로 사용하지 마십시오. 또한 유닉스 기반 시스템에 있다면 루트 계정 로그인을 액세스 가능하게하지 마십시오. 항상 sudo 만 사용해야합니다.

    암호

    해킹 당하지 않도록 사용자에게 올바른 비밀번호를 알려주는 것도 마찬가지입니다. 백도어가 활짝 열려있을 때 현관 문을 잠그기위한 모든 노력을 기울이는 데 필요한 점은 무엇입니까?

    데이터 베이스

    섬기는 사람

    DB와 APPLICATION을 별도의 서버에 설치하는 것이 이상적입니다. 이는 비용 때문에 항상 가능하지는 않지만 침입자가 시스템에 완전히 액세스하려면 두 단계를 거쳐야하므로 몇 가지 안전을 허용합니다.

    사용자

    DB에 액세스하려면 응용 프로그램에 항상 자체 계정이 있어야하며 필요한 권한 만 부여하십시오.

    그런 다음 응용 프로그램이 아닌 서버의 어느 곳에도 저장되어 있지 않은 별도의 사용자 계정을 보유하십시오.

    항상이 루트 또는 이와 유사한 것을 만들지 마세요.

    암호

    모든 좋은 암호와 동일한 지침을 따르십시오. 또한 동일한 시스템의 SERVER 또는 DB 계정에서 동일한 암호를 다시 사용하지 마십시오.

    PHP

    암호

    절대 DB에 암호를 저장하지 말고 해시와 고유 한 소금을 저장하십시오. 이유는 나중에 설명하겠습니다.

    해싱

    한 번 해싱 !!!!!!! 절대 암호를 해싱 할 수 없도록 해시하지 마십시오. 해시는 한 가지 방법이어야합니다. 즉, 해시를 되돌려서 암호와 비교하지 말고 대신 입력 된 암호를 해시합니다 같은 방법으로 두 개의 해시를 비교합니다. 즉, 공격자가 DB에 액세스하더라도 실제로 암호가 무엇인지 알지 못하고 결과 해시 만 알 수 있습니다. 최악의 시나리오에서 사용자에게 더 많은 보안을 제공합니다.

    거기에 좋은 해싱 함수 (password_hash, 해시, 등등 ...) 밖에 많이 있지만 해시에 대한 효과적인 알고리즘을 선택해야합니다. (bcrypt와 비슷한 것들은 알맞은 알고리즘이다.)

    해싱 속도가 중요 할 때, Brute Force 공격에 대한 저항력은 낮아집니다.

    해싱에서 가장 흔한 실수 중 하나는 해시가 사용자에게 고유하지 않다는 점입니다. 소금이 유일하게 생성되지 않기 때문입니다.

    판매

    암호는 해시되기 전에 항상 소금을해야합니다. Salting은 암호에 임의의 문자열을 추가하여 DB에 동일한 암호가 나타나지 않도록합니다. 그러나 소금이 각 사용자에게 고유하지 않은 경우 (예 : 하드 코드 된 소금을 사용하는 경우) 소금을 쓸모 없게 만들었습니다. 한 번 공격자가 암호 소금을 알아 내면 그는 모두를 위해 소금을 가지고 있기 때문에.

    소금을 만들 때 소금에 고유 한 암호인지 확인한 다음 완성 된 해시와 소금을 DB에 저장하십시오. 이렇게하면 공격자가 액세스하기 전에 소금과 해시를 개별적으로 해킹해야합니다. 이는 공격자가 더 많은 작업과 시간을 가질 수 있음을 의미합니다.

    사용자가 암호를 생성합니다.

    사용자가 프론트 엔드를 통해 암호를 작성하면 서버로 보내야 함을 의미합니다. 이는 암호화되지 않은 암호가 서버로 전송되고 공격자가 PHP의 모든 보안이 무의미하다는 것을 경청하고 액세스 할 수 있다는 것을 의미하므로 보안 문제가 발생합니다. 항상 데이터를 안전하게 전송합니다. SSL을 통해 이루어 지지만 SSL이 완벽하지는 않습니다 (OpenSSL의 Heartbleed 결함이 이에 대한 예입니다).

    또한 사용자가 안전한 암호를 만들도록하십시오. 간단하고 항상 수행해야합니다. 사용자는 결국 그것을 감사하게됩니다.

    마지막으로 아무런 보안 조치를 취하지 않아도 100 % 보안을 유지할 수 있으므로 보호 할 기술이 진보할수록 더욱 발전합니다. 그러나이 단계를 따르면 사이트가 더 안전 해지고 공격자가 계속해서 나아갈 수 없게됩니다.

    다음은 패스워드 해시와 소금을 쉽게 생성하는 PHP 클래스입니다.

    http://git.io/mSJqpw

  9. ==============================

    9.

    Google은 SHA256을 PHP에서 사용할 수 있다고 말합니다.

    확실히 소금을 사용해야합니다. 난 임의의 바이트를 사용하는 것이 좋습니다 (그리고 문자와 숫자에 국한되지 않음). 일반적으로 선택할수록 안전하고 느립니다. 64 바이트는 괜찮을 것입니다.

  10. ==============================

    10.

    이 문제에 관해서는 여기에서 완벽한 주제를 찾았습니다 : https://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));
    }
    ?>
    
  11. ==============================

    11.

    결국, double-hashing은 수학적으로 이점을 제공하지 못합니다. 그러나 실제로는 레인보우 테이블 기반 공격을 막는 데 유용합니다. 즉, 소금으로 해싱하는 것보다 더 이상 이점이 없습니다. 이는 응용 프로그램이나 서버에서 프로세서 시간이 훨씬 단축됩니다.

  12. ==============================

    12.

    나는 보통 SHA1과 소금을 사용자 ID (또는 다른 사용자 특정 정보)와 함께 사용하며 때로는 일정한 소금을 추가로 사용합니다 (소금에 2 부분이 있습니다).

    SHA1은 이제 다소 손상된 것으로 간주되지만 MD5보다 훨씬 낮은 수준으로 간주됩니다. 소금 (소금)을 사용하면 일반 레인보우 테이블을 사용하여 해시를 공격하는 것을 방지 할 수 있습니다 (해석을 검색하여 일종의 무지개 테이블로 Google을 사용하는 사람들도 있습니다). 공격자는 소금을 사용하여 무지개 테이블을 생성 할 수 있으므로 사용자 별 소금을 포함시켜야합니다. 그렇게하면 시스템 전체에 대한 레코드가 아닌 각 레코드의 무지개 테이블을 생성해야합니다. 그 종류의 염분으로 MD5조차도 안전합니다.

  13. ==============================

    13.

    가까운 장래에 SHA1과 소금으로 충분할 것입니다 (당연히, Fort Knox 또는 쇼핑 목록의 로그인 시스템에 무엇을 코딩하고 있느냐에 따라 다릅니다). SHA1이 충분하지 않은 경우 SHA256을 사용하십시오.

    소금에 대한 아이디어는 해싱 결과를 균형을 잃어 버리는 것입니다. 예를 들어 빈 문자열의 MD5 해시는 d41d8cd98f00b204e9800998ecf8427e입니다. 따라서 메모리가 충분한 사람이 해시를보고 빈 문자열의 해시라는 것을 알고있는 경우 그러나 문자열이 소금으로 처리되면 (예 : 문자열 "MY_PERSONAL_SALT") '빈 문자열'(즉, 'MY_PERSONAL_SALT')의 해시는 aeac2612626724592271634fb14d3ea6이되며 따라서 역 추적을 수행 할 수 있습니다. 내가 말하려고하는 것은 소금을 사용하는 것이 낫다는 것보다 더 좋습니다. 따라서 사용할 소금을 아는 것이 중요하지 않습니다.

    실제로 이것을 수행하는 웹 사이트가 있습니다. 즉, (md5) 해시를 제공 할 수 있으며 특정 해시를 생성하는 알려진 일반 텍스트를 출력합니다. 일반 md5 해시를 저장하는 데이터베이스에 액세스하려면 해당 서비스에 대한 관리자의 해시를 입력하고 로그인하는 것이 사소한 것입니다. 그러나 비밀번호가 소금에 절인 경우 이러한 서비스는 효과적인.

    또한, 이중 해싱은 일반적으로 나쁜 방법으로 간주됩니다. 결과 공간이 줄어들 기 때문입니다. 모든 인기있는 해시는 고정 길이입니다. 따라서이 고정 길이의 유한 값만 가질 수 있으며 결과는 다양하지 않게됩니다. 이것은 다른 형태의 염분으로 간주 될 수 있지만, 나는 그것을 권장하지 않습니다.

  14. ==============================

    14.

    승인 우리는 소금이 필요합니다. 소금은 독특해야합니다. 그래서 그것을 생성 시키십시오

       /**
         * 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 단계는 자신의 알고리즘을 사용할 수 있습니다 ... 앞으로이 해시 된 암호를 생성 할 수 있는지 확인하십시오. 사용자에게 권한을 부여해야하는 경우 ...

  15. from https://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords by cc-by-sa and MIT lisence