암호 암호화에 HASH_PBKDF2를 사용할 때 SALT는 보안을 보장하는 핵심 구성 요소입니다. 많은 개발자들이 Hash_PBKDF2 가 암호 기반 키 파생 기능이라는 것을 알고 있지만, 솔트를 올바르게 생성하고 사용하는 방법을 무시합니다. 이 기사는 SALT 의 역할, 일반적인 오해 및 PHP에서 안전한 소금을 생성하기위한 권장 관행을 심층적으로 설명합니다.
소금 의 역할은 무지개 테이블 공격의 위험과 동일한 암호가 동일한 해시를 생성하는 것과 동일한 암호를 방지하는 것입니다. 소금이 없으면 공격자는 일반 텍스트 비밀번호를 반전시키기 위해 비밀번호 해시 테이블 만 있으면됩니다. 소금 을 추가하면 각 암호화가 독특 해지고 두 사용자가 동일한 암호를 설정하더라도 해시 값은 완전히 다릅니다.
PHP의 HASH_PBKDF2 기능 프로토 타입은 다음과 같습니다.
<span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-title function_ invoke__">hash_pbkdf2</span></span><span> (
</span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$algo</span></span><span>,
</span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$password</span></span><span>,
</span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$salt</span></span><span>,
</span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$iterations</span></span><span>,
</span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$length</span></span><span> = </span><span><span class="hljs-number">0</span></span><span>,
</span><span><span class="hljs-keyword">bool</span></span><span> </span><span><span class="hljs-variable">$binary</span></span><span> = </span><span><span class="hljs-literal">false</span></span><span>
)
</span></span>
$ 소금 매개 변수는 해시의 고유성을 높이는 데 사용되므로 생성되는 방식이 중요합니다.
고정 문자열을 소금으로 사용하십시오.
<span><span><span class="hljs-variable">$salt</span></span><span> = </span><span><span class="hljs-string">'123456'</span></span><span>;
</span></span>
이것은 매우 위험한 행동입니다. 고정 소금은 모든 사용자의 해시 값이 반복 될 가능성이 있음을 의미합니다.
간단한 기능을 사용하여 생성 :
예를 들어, uniqid () 및 mt_rand () 와 같은 함수는 무작위가 충분하지 않거나 예측 될 수 있습니다.
<span><span><span class="hljs-variable">$salt</span></span><span> = </span><span><span class="hljs-title function_ invoke__">uniqid</span></span><span>();
</span></span>
독특 해 보이지만 엔트로피가 충분하지 않으며 보안 목적으로 권장되지 않습니다.
PHP 제공 암호화 보안 수준 기능을 사용하여 소금을 생성하는 것이 좋습니다.
<span><span><span class="hljs-variable">$salt</span></span><span> = </span><span><span class="hljs-title function_ invoke__">random_bytes</span></span><span>(</span><span><span class="hljs-number">16</span></span><span>); </span><span><span class="hljs-comment">// 16 바이트 = 128 조금</span></span><span>
</span></span>
문자열 (예 : 데이터베이스에 저장)으로 저장 해야하는 경우 bin2Hex () 또는 base64_encode ()를 사용하여 인코딩 할 수 있습니다.
<span><span><span class="hljs-variable">$salt</span></span><span> = </span><span><span class="hljs-title function_ invoke__">bin2hex</span></span><span>(</span><span><span class="hljs-title function_ invoke__">random_bytes</span></span><span>(</span><span><span class="hljs-number">16</span></span><span>)); </span><span><span class="hljs-comment">// 32 16 진 문자 문자열</span></span><span>
</span></span>
다음은 hash_pbkdf2를 사용하여 암호를 안전하게 암호화하는 방법에 대한 완전한 예입니다.
<span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">hashPassword</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$password</span></span></span><span>) {
</span><span><span class="hljs-variable">$salt</span></span><span> = </span><span><span class="hljs-title function_ invoke__">bin2hex</span></span><span>(</span><span><span class="hljs-title function_ invoke__">random_bytes</span></span><span>(</span><span><span class="hljs-number">16</span></span><span>)); </span><span><span class="hljs-comment">// 안전하게 생성하십시오 salt</span></span><span>
</span><span><span class="hljs-variable">$iterations</span></span><span> = </span><span><span class="hljs-number">100000</span></span><span>;
</span><span><span class="hljs-variable">$algo</span></span><span> = </span><span><span class="hljs-string">'sha256'</span></span><span>;
</span><span><span class="hljs-variable">$length</span></span><span> = </span><span><span class="hljs-number">64</span></span><span>;
</span><span><span class="hljs-variable">$hash</span></span><span> = </span><span><span class="hljs-title function_ invoke__">hash_pbkdf2</span></span><span>(</span><span><span class="hljs-variable">$algo</span></span><span>, </span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$salt</span></span><span>, </span><span><span class="hljs-variable">$iterations</span></span><span>, </span><span><span class="hljs-variable">$length</span></span><span>, </span><span><span class="hljs-literal">false</span></span><span>);
</span><span><span class="hljs-keyword">return</span></span><span> [
</span><span><span class="hljs-string">'salt'</span></span><span> => </span><span><span class="hljs-variable">$salt</span></span><span>,
</span><span><span class="hljs-string">'hash'</span></span><span> => </span><span><span class="hljs-variable">$hash</span></span><span>,
</span><span><span class="hljs-string">'algo'</span></span><span> => </span><span><span class="hljs-variable">$algo</span></span><span>,
</span><span><span class="hljs-string">'iterations'</span></span><span> => </span><span><span class="hljs-variable">$iterations</span></span><span>
];
}
</span><span><span class="hljs-comment">// 예제 사용</span></span><span>
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-title function_ invoke__">hashPassword</span></span><span>(</span><span><span class="hljs-string">'MySecretPassword'</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$result</span></span><span>);
</span></span>
비밀번호를 확인할 때는 데이터베이스에서 원래 소금 , 반복 및 알고를 읽은 다음 비교를 위해 같은 방식으로 해시를 재생해야합니다.
<span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">verifyPassword</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$password</span></span></span><span>, </span><span><span class="hljs-variable">$storedHash</span></span><span>, </span><span><span class="hljs-variable">$salt</span></span><span>, </span><span><span class="hljs-variable">$iterations</span></span><span>, </span><span><span class="hljs-variable">$algo</span></span><span> = </span><span><span class="hljs-string">'sha256'</span></span><span>, </span><span><span class="hljs-variable">$length</span></span><span> = </span><span><span class="hljs-number">64</span></span><span>) {
</span><span><span class="hljs-variable">$hash</span></span><span> = </span><span><span class="hljs-title function_ invoke__">hash_pbkdf2</span></span><span>(</span><span><span class="hljs-variable">$algo</span></span><span>, </span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$salt</span></span><span>, </span><span><span class="hljs-variable">$iterations</span></span><span>, </span><span><span class="hljs-variable">$length</span></span><span>, </span><span><span class="hljs-literal">false</span></span><span>);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-title function_ invoke__">hash_equals</span></span><span>(</span><span><span class="hljs-variable">$storedHash</span></span><span>, </span><span><span class="hljs-variable">$hash</span></span><span>);
}
</span></span>
Hash_equals는 타이밍 공격을 방지 할 수 있으며 해시를 비교할 때 안전한 선택입니다.
Hash_PBKDF2를 안전하게 사용하려면 열쇠는 강한 임의의 소금을 생성하고 충분한 수의 반복을 설정하는 것입니다. 정적 또는 낮은 엔트로피 염을 사용하지 마십시오. 그렇지 않으면 전체 암호화 프로세스의 보안을 파괴합니다. 비밀번호 보안 분야에는 소위 "make use"가 없으며 모든 세부 사항은 진지하게 받아 들일 가치가 있습니다. 이 기사가보다 안전한 PHP 응용 프로그램을 구축하기 위해 Hash_PBKDF2 에서 올바른 생성 소금을 이해하는 데 도움이되기를 바랍니다.