crypt () 함수는 암호화 또는 암호 검증에 PHP를 사용할 때, 특히 비밀번호 _hash () 및 password_verify ()가 초기에 사용할 수 없기 전에 고전적인 선택입니다. 그러나 Crypt ()를 사용할 때 많은 개발자가 혼란스러운 문제를 겪게됩니다. 동일한 코드가 다른 운영 체제 나 환경에서 실행되지만 결과는 일관성이 없어 보안 위험으로 이어질 수도 있습니다. 이 기사는이 현상의 이유와 이러한 "구덩이"를 피하는 방법을 심도있게 탐구 할 것입니다.
PHP의 crypt () 함수는 일방형으로 문자열을 암호화하는 데 사용됩니다. 핵심 논리는 제공된 "소금 값"( 소금 )을 기반으로 사용할 암호화 알고리즘을 선택하는 것입니다. 이 소금 값은 알고리즘을 제어 할뿐만 아니라 암호화 과정에도 참여합니다. 예를 들어:
echo crypt('password', '$1$mysalt$'); // 사용 MD5 암호화
다른 접두사는 다른 암호화 알고리즘을 나타냅니다.
$ 1 $는 MD5 기반 암호화를 사용하는 것을 의미합니다
$ 2A $ , $ 2Y $ , $ 2B $는 Blowfish (bcrypt)를 사용하는 것을 의미합니다.
$ 5 $는 SHA-256을 사용하는 것을 의미합니다
$ 6 $는 SHA-512를 사용하는 것을 의미합니다
Crypt () 는 PHP의 표준 기능이지만, 구현은 기본 시스템의 C 라이브러리 (LIBC)에 의존합니다. 즉, PHP는 시스템 수준 crypt () 함수 만 캡슐화합니다. 이로 인해 다른 운영 체제 간의 crypt () 의 동작에는 큰 차이가있을 수 있으며, 이는 다음과 같이 표시됩니다.
모든 시스템이 동일한 암호화 알고리즘을 지원하는 것은 아닙니다. 예를 들어:
일부 이전 버전의 MACOS 시스템은 기존 DES 암호화 만 지원합니다.
Linux (특히 GNU LIBC를 사용하는 시스템)는 일반적으로 MD5, SHA-256, SHA-512, Blowfish 등을 지원합니다.
알파인 리눅스는 무슬림 LIBC, 특히 bcrypt로 인한 일부 알고리즘을 불완전하게 지원합니다.
즉, $ 2y $ 접두사 암호화를 사용하여 Ubuntu에서 잘 실행되는 스크립트는 Alpine 컨테이너에서 *0 또는 *1 (실패를 나타냄)을 직접 반환하거나 해시 문자열을 잘못된 형식으로 반환 할 수 있습니다.
일부 시스템에서는 동일한 알고리즘이 지원 되더라도 반환 된 암호화 결과는 약간 다른 형식을 가질 수 있습니다. 예를 들어:
$hash1 = crypt('password', '$2y$10$1234567890123456789012'); // 존재하다 Linux 우수한
$hash2 = crypt('password', '$2y$10$1234567890123456789012'); // 존재하다 macOS 우수한
위의 두 줄의 코드에서 $ HASH1 및 $ HASH2는 다를 수 있으며 시스템의 다른 버전의 성능조차 다를 수 있습니다. 이는 크로스 플랫폼 배포의 잠재적 위험입니다.
적절한 소금 값이 제공되지 않으면 Crypt () 의 동작은 시스템에 의해 결정됩니다.
전통적인 des 사용
기본적으로 해시 알고리즘을 사용하십시오
직접 돌아 오지 못했습니다
이는 코드에 알고리즘과 소금 값이 명시 적으로 지정되지 않으면 프로그램의 동작은 전적으로 시스템 구현에 의존하며 극도로 신뢰할 수 없음을 의미합니다.
개발자는 한때 Laravel Framework에서 Crypt ()를 사용하여 사용자 암호를 수동으로 암호화하여 데이터베이스에 저장했습니다. 코드는 일반적으로 로컬 우분투 개발 환경에서 실행됩니다. 그러나 알파인 기반 Docker 컨테이너에 배포 된 후에는 사용자 로그인이 항상 실패합니다. 그 이유는 Alpine의 Crypt ()가 사용하는 $ 2y $ bcrypt 알고리즘을 지원하지 않기 때문에 생성 된 해시가 불법이기 때문입니다.
이러한 호환성 및 이식성 문제를 피하려면 다음과 같이 권장됩니다.
이러한 기능은 PHP 5.5 이후에 도입되었으며 시스템의 crypt () 동작에 의존하지 않고 기본 구현에 더 잘 캡슐화됩니다. 샘플 코드 :
$hash = password_hash('mypassword', PASSWORD_BCRYPT);
if (password_verify('mypassword', $hash)) {
echo '올바른 비밀번호';
}
이 방법은 최적의 알고리즘의 자동 선택을 지원할뿐만 아니라 현재 가장 권장되는 관행 인 암호화 매개 변수 (예 : 비용) 업그레이드를 처리합니다.
예를 들어 대상 환경이 알고리즘을 지원하는지 확인하십시오.
$salt = '$2y$10$' . substr(str_replace('+', '.', base64_encode(random_bytes(16))), 0, 22);
$hash = crypt('mypassword', $salt);
배포하기 전에 대상 서버에서 생성 및 검증 프로세스를 테스트하여 환경 적 차이를 피하십시오.
다른 환경에서 정책 조정을 용이하게하는 암호화 정책을 제어하기 위해 구성 파일 또는 환경 변수를 사용하는 것을 고려하십시오.
Crypt () 는 PHP에서 오랫동안 주변에 있었지만 플랫폼 의존성은 특히 현대 응용 프로그램의 크로스 플랫폼 배포가 표준 일 때 덜 신뢰할 수있는 옵션이됩니다. crypt () 와 직면 한 "피트"는 실제로 시스템 간 호환성의 징후입니다. 가장 좋은 솔루션은 Password_hash () 와 같은보다 현대적이고 안정적인 API를 사용하는 것입니다.
여전히 이전 시스템을 유지하거나 특별한 요구가있는 Crypt ()를 사용하는 경우 모든 세부 사항을 테스트하고 확인하여 모든 운영 환경이 암호화 알고리즘을 지속적으로 지원할 수 있도록하십시오. 그렇지 않으면 보안 또는 기능의 "큰 구덩이"를 밟을 수 있습니다.
추가 디버깅을 보려면 액세스 할 수 있습니다.
https://m66.net/crypt-debug-tool (도구 페이지가 배포되었다고 가정)
시스템 간의 다른 암호화 동작이 프로젝트에서 "시한 폭탄"이되지 않도록하십시오.