programing

긴 패스워드(72자 이상)를 복어와 해시하는 방법

javaba 2022. 9. 16. 22:02
반응형

긴 패스워드(72자 이상)를 복어와 해시하는 방법

지난 주에 패스워드 해싱에 관한 기사를 많이 읽었는데 Blowfish는 현재 최고의 해싱 알고리즘 중 하나인 것 같습니다만, 이 질문의 주제는 그게 아닙니다!

72 문자 제한

복어는 입력한 비밀번호의 처음 72자만 고려합니다.

<?php
$password = "Wow. This is a super secret and super, super long password. Let's add some special ch4r4ct3rs a#d everything is fine :)";
$hash = password_hash($password, PASSWORD_BCRYPT);
var_dump($password);

$input = substr($password, 0, 72);
var_dump($input);

var_dump(password_verify($input, $hash));
?>

출력은 다음과 같습니다.

string(119) "Wow. This is a super secret and super, super long password. Let's add some special ch4r4ct3rs a#d everything is fine :)"
string(72) "Wow. This is a super secret and super, super long password. Let's add so"
bool(true)

보시다시피 처음 72자만 중요합니다.Twitter는 비밀번호를 저장하기 위해 복어 bcrypt(https://shouldichangemypassword.com/twitter-hacked.php)를 사용하고 있으며, 트위터 비밀번호를 72자를 초과하는 긴 비밀번호로 변경하고 처음 72자만 입력하면 계정에 로그인할 수 있습니다.

복어와 후추

"피퍼링" 비밀번호에 대해서는 많은 다른 의견들이 있다.어떤 사람들은 그것이 불필요하다고 말한다. 왜냐하면 비밀의 후추 문자열도 알려져 있고 공개되어 있기 때문에 해시를 강화하지 않는다고 가정해야 하기 때문이다.저는 별도의 데이터베이스 서버를 가지고 있기 때문에 데이터베이스만 유출되고 지속적인 후추는 유출되지 않을 가능성이 높습니다.

이 경우(피퍼가 유출되지 않음) 사전을 기반으로 공격을 더 어렵게 만듭니다(잘못된 경우 수정하십시오).만약 당신의 후추줄도 새나간다면: 그렇게 나쁘지 않다 - 당신은 여전히 소금을 가지고 있고 후추 없이 해시처럼 잘 보호된다.

그래서 나는 패스워드를 사용하는 것이 적어도 나쁜 선택은 아니라고 생각한다.

제안.

72자(및 후추)가 넘는 비밀번호에 대해 Blowfish 해시를 얻는 방법은 다음과 같습니다.

<?php
$pepper = "foIwUVmkKGrGucNJMOkxkvcQ79iPNzP5OKlbIdGPCMTjJcDYnR";

// Generate Hash
$password = "Wow. This is a super secret and super, super long password. Let's add some special ch4r4ct3rs a#d everything is fine :)";
$password_peppered = hash_hmac('sha256', $password, $pepper);
$hash = password_hash($password_peppered, PASSWORD_BCRYPT);

// Check
$input = substr($password, 0, 72);
$input_peppered = hash_hmac('sha256', $input, $pepper);

var_dump(password_verify($input_peppered, $hash));
?>

이것은, 다음의 질문에 근거하고 있습니다.password_verifyfalse

질문

더 안전한 방법은 무엇일까요?먼저 SHA-256 해시를 가져오거나(64자를 반환한다), 비밀번호의 첫 번째 72자만 고려합니까?

장점

  • 사용자는 처음 72자만 입력하여 로그인할 수 없습니다.
  • 후추는 글자 수 제한을 초과하지 않고 추가할 수 있습니다.
  • hash_hmac의 출력은 패스워드 자체보다 엔트로피가 클 수 있습니다.
  • 암호는 두 가지 다른 함수에 의해 해시됩니다.

단점

  • 복어 해시를 만드는 데 64자만 사용됩니다.


편집 1: 이 질문은 복어/bcrypt의 PHP 통합에 대해서만 설명합니다.댓글 감사합니다.

여기서의 문제는 기본적으로 엔트로피의 문제입니다.여기서부터 살펴보겠습니다.

문자당 엔트로피 수

바이트당 엔트로피 비트 수는 다음과 같습니다.

  • 16진수 문자
    • 비트: 4
    • 값: 16
    • 엔트로피 입력 72 문자: 288 비트
  • 영숫자
    • 비트: 6
    • 값: 62
    • 엔트로피 입력 72 문자: 432 비트
  • "공통" 기호
    • 비트: 6.5
    • 값: 94
    • 엔트로피 입력 72 문자: 468 비트
  • 전체 바이트 수
    • 비트: 8
    • 값: 255
    • 엔트로피 입력 72 문자: 576 비트

그래서 우리가 어떻게 행동하느냐는 우리가 기대하는 캐릭터에 달려있다.

첫 번째 문제

코드의 첫 번째 문제는 "페퍼" 해시 스텝이 16진수 문자를 출력하고 있다는 것입니다(네 번째 파라미터 이후부터).hash_hmac()

따라서 후추를 해시함으로써 비밀번호에 사용할 수 있는 최대 엔트로피를 2배(가능한 비트 수 576 ~288)까지 효과적으로 줄일 수 있습니다.

두 번째 문제

★★★★★★★★★★★★★★.sha256제공만 하다256애초에 엔트로피의 비트를요.즉, 576비트를 256비트로 줄이는 것입니다.해시 스텝 *immediate*는 매우 정의상 패스워드에서 가능한 엔트로피의 적어도 50%가 손실됩니다.

할 수 은 '어느 정도'로 바꾸면 .SHA51212%로 하다하지만 그것은 여전히 중요하지 않은 차이이다. 12% .1.8e19정말 큰 숫자네요그리고 그것이 그것을 감소시키는 요인입니다...

근본적인 문제

근본적인 문제는 72자를 초과하는 3가지 유형의 비밀번호가 있다는 것입니다.이 스타일 시스템이 고객에게 미치는 영향은 매우 다릅니다.

수 것 같습니다: 후추 입니다.SHA512생으로 하다

  • 고엔트로피 랜덤 패스워드

    패스워드의 큰 키를 생성하는 패스워드 생성기를 사용하는 사용자입니다.랜덤(인간이 선택하지 않고 생성)이며 문자당 엔트로피가 높습니다.이러한 타입에서는, 고바이트(문자 > 127)와 일부의 제어 문자를 사용합니다.

    이 그룹에 대해 해싱 함수는 사용 가능한 엔트로피를 현저하게 감소시킵니다.bcrypt

    그것에 대해 다시 말할게요.높은 엔트로피와 긴 암호를 사용하는 사용자의 경우, 이 솔루션은 암호 강도를 측정 가능한 양만큼 크게 낮춥니다.(72자 패스워드의 경우 62비트, 긴 패스워드의 경우 더 많은 엔트로피가 손실됩니다.)

  • 중간 엔트로피 랜덤 패스워드

    이 그룹은 공통 기호를 포함하지만 높은 바이트 또는 제어 문자를 포함하지 않는 암호를 사용하고 있습니다.이것들은 입력 가능한 패스워드입니다.

    그룹에서는 엔트로피를 조금 더 잠금 해제합니다(생성하지 않고 bcrypt 비밀번호에 더 많은 엔트로피를 허용합니다).내가 살짝 말할 때는 살짝 말하는 거야.손익분기점은 SHA512의 512비트를 초과했을 때 발생합니다.따라서 피크는 78자입니다.

    그것에 대해 다시 말할게요.이 암호 클래스의 경우 엔트로피가 부족해질 때까지 6자만 추가로 저장할 수 있습니다.

  • 낮은 엔트로피 비랜덤 암호

    랜덤으로 생성되지 않을 가능성이 높은 영숫자를 사용하고 있는 그룹입니다.성경 구절 같은 거요이러한 문구는 문자당 약 2.3비트의 엔트로피를 가집니다.

    이 그룹의 경우 해시를 통해 엔트로피를 대폭 잠금 해제할 수 있습니다(생성할 수는 없지만 bcrypt 비밀번호 입력에 더 많은 엔트로피를 할당할 수 있습니다).손익분기점은 엔트로피가 떨어지기 전에 약 223자입니다.

    다시 한 번 말해봐요.이 클래스의 패스워드에 대해서는, 사전에 해시를 실시하면 시큐러티가 큰폭으로 향상됩니다.

현실로 돌아가다

이러한 엔트로피 계산은 실제 세계에서는 그다지 중요하지 않습니다.중요한 것은 엔트로피 추측이다.그것이 공격자가 할 수 있는 일에 직접적인 영향을 미치는 것이다.그게 네가 최대화하고 싶은 거야

엔트로피를 추측하는 연구는 거의 없지만, 제가 지적하고 싶은 몇 가지 요점이 있습니다.

72개의 정확한 문자를 연속해서 무작위로 추측할 확률은 매우 낮습니다.파워볼 복권에 21번 당첨될 확률이 이번 충돌보다 더 높죠그만큼 큰 숫자라는 거죠

하지만 통계적으로 우연히 발견하지 못할 수도 있습니다.구문의 경우 처음 72자가 같을 가능성은 랜덤 패스워드보다 훨씬 높아집니다.하지만 여전히 낮은 수준입니다(캐릭터당 2.3비트 기준으로 파워볼 복권에 5번 당첨될 확률이 높습니다).

사실상

사실, 그건 별로 중요하지 않아요.어떤 사람이 첫 번째 72자를 맞힐 확률은 너무 낮아서 걱정할 필요가 없다.왜요?

예를 들어 한 구절을 받아들인다고 칩시다.만약 그 사람이 처음 72자를 맞힐 수 있다면, 그들은 정말 운이 좋거나 혹은 흔한 문구이다.그게 흔한 표현이라면, 유일한 변수는 그것을 얼마나 오래 만들 것인가이다.

예를 들어보자.성경에서 인용해보자(그것은 단지 긴 텍스트의 일반적인 소스이기 때문이지 다른 어떤 다른 이유 때문은 아니다).

이웃집을 탐내지 마라.너는 네 이웃의 아내나 그의 남종이나 여종이나 그의 소나 나귀나 네 이웃의 것을 탐하지 말아라.

. 73번 글자입니다.g neighbor's을 했다면 nei(비밀번호가 사용될 가능성이 높기 때문에) 나머지 부분을 계속 진행합니다.그래서 당신의 "해시"는 별로 추가되지 않았습니다.

BTW: 나는 절대 성경 인용문을 사용하는 것을 지지하지 않는다.사실은 정반대예요.

결론

먼저 해시를 해서 긴 비밀번호를 사용하는 사람들을 많이 도와주지는 못할 것입니다.당신이 확실히 도울 수 있는 그룹도 있어요.어떤 것들은 확실히 다치게 할 수 있어요.

하지만 결국, 그 어떤 것도 지나치게 중요하지 않다.우리가 다루고 있는 수치는 너무 높다.엔트로피의 차이는 크지 않을 것이다.

너는 bcrypt를 그대로 두는 것이 좋겠다.예방하려는 공격보다 해시를 망칠 가능성이 더 높습니다(말 그대로 이미 실행했으며, 이러한 실수를 한 첫 번째 또는 마지막이 아닙니다).

나머지 부지를 보호하는 데 집중해또한 비밀번호 엔트로피 미터를 등록 시 비밀번호 상자에 추가하여 비밀번호 강도를 나타냅니다(및 비밀번호가 너무 길어서 사용자가 변경을 원할 수 있는 경우 표시).

그건 적어도 내 0.02달러(혹은 0.02달러 이상일 수도 있음)...

"비밀" 페퍼를 사용하는 한:

말 그대로 하나의 해시함수를 bcrypt에 공급하는 연구는 없습니다.해도 알 수 없는할 수 는 "bcrypt" "peppered"를 실행하고 있음을 있습니다).hash1(hash2($value))는 충돌 저항성 및 프리이미지 공격에 대한 중대한 취약성을 노출할 수 있습니다).

이미 비밀키('페퍼')의 저장을 검토하고 있는 것을 고려하면, 잘 연구되고 이해되는 방법으로 그것을 사용하는 것은 어떨까요?해시를 저장하기 전에 암호화하는 것이 어떨까요?

기본적으로 패스워드를 해시한 후 해시 출력 전체를 강력한 암호화 알고리즘에 넣습니다.그런 다음 암호화된 결과를 저장합니다.

SQL-Injection 공격에서는 암호 키가 없기 때문에 유용한 정보가 유출되지 않습니다.그리고 키가 유출되면 공격자가 플레인 해시를 사용한 경우와 다를 바 없습니다(이러한 해시는 '프리 해시'를 사용한 경우에는 제공되지 않습니다).

참고: 이 작업을 선택한 경우 라이브러리를 사용하십시오.PHP의 경우 Zend Framework 2의Zend\Crypt할 수 없습니다.현시점에서는 이 방법밖에 추천하지 않습니다.그것은 강하게 검토되고 있으며, 당신을 위한 모든 결정을 내립니다(이것은 매우 좋은 일입니다).

예를 들어 다음과 같습니다.

use Zend\Crypt\BlockCipher;

public function createHash($password) {
    $hash = password_hash($password, PASSWORD_BCRYPT, ["cost"=>$this->cost]);

    $blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
    $blockCipher->setKey($this->key);
    return $blockCipher->encrypt($hash);
}

public function verifyHash($password, $hash) {
    $blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
    $blockCipher->setKey($this->key);
    $hash = $blockCipher->decrypt($hash);

    return password_verify($password, $hash);
}

모든 알고리즘을 잘 이해하고 잘 연구된 방식으로 사용하기 때문에 도움이 됩니다.주의:

아마추어에서 최고의 암호 기술자에 이르기까지 누구나 스스로 풀 수 없는 알고리즘을 만들 수 있습니다.

패스워드를 페퍼링 하는 것은 확실히 좋은 일이지만, 그 이유를 확인해 봅시다.

먼저 우리는 정확히 후추가 도움이 될 때 질문에 대답해야 한다.Pepper는 비밀번호만 보호하므로 공격자가 서버 자체에 액세스할 수 있는 경우에는 아무 소용이 없습니다.그러나 훨씬 쉬운 공격은 SQL-injection입니다. SQL-injection은 데이터베이스(해시 값에 대한 읽기 액세스)를 가능하게 합니다. SQL-injection 데모를 준비했습니다(다음 화살표를 클릭하여 준비된 입력을 얻습니다).

럼럼 후후 제제 제제 제? ???페퍼가 비밀에 부치는 한 사전 공격으로부터 취약한 암호를 보호합니다. '''1234 '이렇게'가 되는 죠.1234-p*deDIUZeRweretWy+.O이 패스워드는 훨씬 길 뿐만 아니라 특수문자가 포함되어 있어 사전에 포함되지 않습니다.

패스워드가 64~72자인 사용자가 있기 때문에 사용자가 어떤 패스워드를 사용할지 예측할 수 있습니다.아마 더 많은 사용자가 약한 패스워드를 입력할 것입니다(실제로 이것은 매우 드문 일입니다).

또 다른 포인트는 무차별 포스 범위입니다.sha256 해시 함수는 256비트 출력 또는 1을 반환합니다.2E77의 조합은 GPU의 경우에도 무리입니다(정확하게 계산하면 2013년에는 GPU에서 약 2E61년이 소요됩니다).그래서 후추를 바르면 정말 불이익을 받지 않습니다.해시 값은 체계적이지 않기 때문에 일반적인 패턴에서는 브루트 포싱 속도를 높일 수 없습니다.

추신: 제가 알기로는 72글자의 제한은 BCrypt 자체의 알고리즘에 한정되어 있습니다.내가 찾은 최고의 답은 이것이다.

P.P.S 당신의 예는 결함이 있다고 생각합니다. 완전한 비밀번호 길이로 해시를 생성하고 잘린 비밀번호로 검증할 수 없습니다.아마 해시 생성 및 해시 검증과 같은 방법으로 후추를 적용하려고 했을 것입니다.

Bcrypt는 고가의 Blowfish 키 설정 알고리즘을 기반으로 한 알고리즘을 사용합니다.

bcrypt에 권장되는 56바이트의 패스워드 제한(늘 종단 바이트 포함)은 Blowfish 키의 448비트 제한과 관련되어 있습니다.이 제한을 초과하는 바이트는 결과 해시에 완전히 혼합되지 않습니다.따라서 bcrypt 비밀번호에 대한 72바이트 절대 제한은 이들 바이트에 의한 해시에 대한 실제 영향을 고려할 때 관련성이 낮습니다.

사용자가 보통 55바이트 이상의 패스워드를 선택할 것으로 생각되는 경우 패스워드 테이블 위반 시 보안을 강화하기 위해 패스워드 확장 라운드를 항상 늘릴 수 있습니다(단, 추가 문자를 추가하는 것에 비해 많은 양의 패스워드가 필요합니다).사용자의 접근권이 매우 중요하기 때문에 일반적으로 사용자가 매우 긴 비밀번호를 필요로 하는 경우에는 비밀번호 유효기간도 2주 정도로 짧아야 합니다.즉, 해커가 각 트라이얼 패스워드의 테스트에 관련된 작업 팩터를 물리치고 일치하는 해시가 생성되는지 여부를 확인하는 데 자원을 투입하는 동안 패스워드가 유효하게 유지될 가능성은 크게 낮아집니다.

물론 패스워드 테이블이 침해되지 않을 경우 사용자의 계정을 잠그기 전에 해커가 사용자의 55바이트 비밀번호를 추측하는 시도를 최대 10번만 허용해야 합니다.

55바이트보다 긴 패스워드를 프리해시하는 경우는 제한을 넘지 않고 출력이 가장 크기 때문에 SHA-384를 사용해야 합니다.

언급URL : https://stackoverflow.com/questions/16594613/how-to-hash-long-passwords-72-characters-with-blowfish

반응형