"crypt" --- 유닉스 비밀번호 확인 함수
*************************************

**소스 코드:** Lib/crypt.py

버전 3.11부터 폐지: The "crypt" module is deprecated (see **PEP 594**
for details and alternatives). The "hashlib" module is a potential
replacement for certain use cases.

======================================================================

이 모듈은 수정된 DES 알고리즘을 기반으로 하는 단방향 해시 함수인
*crypt(3)* 루틴에 대한 인터페이스를 구현합니다; 자세한 내용은 유닉스
매뉴얼 페이지를 참조하십시오. 가능한 용도는 실제 암호를 저장하지 않고
암호를 확인하기 위해 해시 된 암호를 저장하거나 사전으로 유닉스 암호를
해독하려고 시도하는 것을 포함합니다.

이 모듈의 동작은 실행 중인 시스템의 *crypt(3)* 루틴의 실제 구현에 따라
달라집니다. 따라서, 현재 구현에서 사용할 수 있는 모든 확장을 이 모듈에
서도 사용할 수 있습니다.

가용성: 유닉스. VxWorks에서는 사용할 수 없습니다.


해싱 방법
=========

버전 3.3에 추가.

"crypt" 모듈은 해싱 방법 목록을 정의합니다 (모든 플랫폼에서 모든 방법
을 사용할 수 있는 것은 아닙니다):

crypt.METHOD_SHA512

   SHA-512 해시 함수를 기반으로 16문자의 솔트(salt)와 86문자의 해시를
   사용하는 모듈형 암호 형식(Modular Crypt Format) 방법. 이것은 가장
   강력한 방법입니다.

crypt.METHOD_SHA256

   SHA-256 해시 함수를 기반으로 16자의 솔트와 43자의 해시를 사용하는
   또 다른 모듈형 암호 형식 방법.

crypt.METHOD_BLOWFISH

   Blowfish 암호를 기반으로 22문자의 솔트와 31문자의 해시를 사용하는
   또 다른 모듈형 암호 형식 방법.

   버전 3.7에 추가.

crypt.METHOD_MD5

   MD5 해시 함수를 기반으로 8자의 솔트와 22자의 해시를 사용하는 또 다
   른 모듈형 암호 형식 방법.

crypt.METHOD_CRYPT

   2문자의 솔트와 13문자의 해시를 사용하는 전통적인 방법. 이것은 가장
   약한 방법입니다.


모듈 어트리뷰트
===============

버전 3.3에 추가.

crypt.methods

   사용 가능한 비밀번호 해싱 알고리즘 리스트, "crypt.METHOD_*" 객체들.
   이 리스트는 가장 강한 것부터 가장 약한 것 순으로 정렬됩니다.


모듈 함수
=========

"crypt" 모듈은 다음 함수를 정의합니다:

crypt.crypt(word, salt=None)

   *word* will usually be a user's password as typed at a prompt or
   in a graphical interface.  The optional *salt* is either a string
   as returned from "mksalt()", one of the "crypt.METHOD_*" values
   (though not all may be available on all platforms), or a full
   encrypted password including salt, as returned by this function.
   If *salt* is not provided, the strongest method available in
   "methods" will be used.

   비밀번호 확인은 일반적으로 *word*로 평문 비밀번호를 전달하는 것으로
   수행됩니다. 이전 "crypt()" 호출의 전체 결과와 이 호출의 결과가 같아
   야 합니다.

   *salt*(무작위의 2자나 16자 문자열, 방법을 가리키기 위해 앞에
   "$digit$"가 붙을 수 있음)는 암호화 알고리즘을 교란하는 데 사용됩니
   다. *salt*의 문자는 "$digit$"를 앞에 붙이는 모듈형 암호 형식을 제외
   하고는 "[./a-zA-Z0-9]" 집합에 있어야 합니다.

   해시 된 비밀번호를 문자열로 반환합니다. 이 문자열은 솔트와 같은 알
   파벳의 문자로 구성됩니다.

   몇 가지 *crypt(3)* 확장이 *salt*에 다른 크기의 다른 값을 허용하기
   때문에, 암호를 확인할 때 전체 암호화된 비밀번호를 솔트로 사용하는
   것이 좋습니다.

   버전 3.3에서 변경: *salt*에 대한 문자열 외에 "crypt.METHOD_*" 값을
   받아들입니다.

crypt.mksalt(method=None, *, rounds=None)

   Return a randomly generated salt of the specified method.  If no
   *method* is given, the strongest method available in "methods" is
   used.

   반환 값은 *salt* 인자로 "crypt()"에 전달하기에 적합한 문자열입니다.

   *rounds*는 "METHOD_SHA256", "METHOD_SHA512" 및 "METHOD_BLOWFISH"에
   대한 라운드 수를 지정합니다. "METHOD_SHA256" 과 "METHOD_SHA512"의
   경우 "1000"와 "999_999_999" 사이의 정수여야 하며, 기본값은 "5000"입
   니다. "METHOD_BLOWFISH"의 경우 "16"(2^4)과 "2_147_483_648"(2^31) 사
   이의 2의 거듭제곱이어야 하며, 기본값은 "4096"(2^12)입니다.

   버전 3.3에 추가.

   버전 3.7에서 변경: *rounds* 매개 변수가 추가되었습니다.


예제
====

일반적인 사용법을 보여주는 간단한 예제 (타이밍 공격에 대한 노출을 제한
하기 위해서는 상수 시간 비교 연산이 필요합니다.
"hmac.compare_digest()"가 이 목적에 적합합니다):

   import pwd
   import crypt
   import getpass
   from hmac import compare_digest as compare_hash

   def login():
       username = input('Python login: ')
       cryptedpasswd = pwd.getpwnam(username)[1]
       if cryptedpasswd:
           if cryptedpasswd == 'x' or cryptedpasswd == '*':
               raise ValueError('no support for shadow passwords')
           cleartext = getpass.getpass()
           return compare_hash(crypt.crypt(cleartext, cryptedpasswd), cryptedpasswd)
       else:
           return True

가장 강력한 방법을 사용하여 비밀번호의 해시를 생성하고, 원본과 비교하
여 확인하려면 이렇게 합니다:

   import crypt
   from hmac import compare_digest as compare_hash

   hashed = crypt.crypt(plaintext)
   if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
       raise ValueError("hashed version doesn't validate against original")
