secrets — 보안 비밀 관리를 위한 보안 난수 생성
secrets — 보안 비밀 관리를 위한 보안 난수 생성
versionadded: 3.6.
secrets 모듈은 비밀번호, 계정 인증, 보안 토큰 및 관련 비밀과 같은 데이터를 관리하기에 적합한 암호학적으로 강력한 난수를 생성하는 데 사용됩니다.
본문
특히 secrets는 모델링과 시뮬레이션을 위해 설계된 random 모듈의 기본 의사 난수 생성기보다 우선적으로 사용해야 합니다. random 모듈은 보안이나 암호화를 위한 것이 아닙니다.
See also
PEP 506
난수
secrets 모듈은 운영 체제가 제공하는 가장 안전한 난수 소스에 대한 접근을 제공합니다.
- secrets.SystemRandom — 운영 체제가 제공하는 최고 품질의 소스를 사용하여 난수를 생성하는 클래스입니다. 자세한 내용은
random.SystemRandom을 참고하세요. - secrets.choice(seq) — 빈 시퀀스가 아닌 시퀀스에서 무작위로 선택된 요소를 반환합니다.
- secrets.randbelow(exclusive_upper_bound) —
[0, exclusive_upper_bound)범위의 임의의int를 반환합니다. - secrets.randbits(k) —
k개의 임의 비트를 가진 음이 아닌int를 반환합니다.
토큰 생성
secrets 모듈은 비밀번호 재설정, 추측하기 어려운 URL 등과 같은 응용 프로그램에 적합한 보안 토큰을 생성하는 함수를 제공합니다.
- secrets.token_bytes(nbytes=None) —
nbytes바이트 수를 포함하는 임의의 바이트 문자열을 반환합니다.nbytes가 지정되지 않거나None이면DEFAULT_ENTROPY가 대신 사용됩니다.
>>> token_bytes(16) b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b' - secrets.token_hex(nbytes=None) — 16진수로 된 임의의 텍스트 문자열을 반환합니다. 문자열에는
nbytes개의 임의 바이트가 있으며, 각 바이트는 두 개의 16진수 자리로 변환됩니다.nbytes가 지정되지 않거나None이면DEFAULT_ENTROPY가 대신 사용됩니다.
>>> token_hex(16) 'f9bf78b9a18ce6d46a0cd2b0b86df9da' - secrets.token_urlsafe(nbytes=None) —
nbytes개의 임의 바이트를 포함하는 임의의 URL 안전 텍스트 문자열을 반환합니다. 텍스트는 Base64로 인코딩되므로 평균적으로 각 바이트는 약 1.3개의 문자를 만듭니다.nbytes가 지정되지 않거나None이면DEFAULT_ENTROPY가 대신 사용됩니다.
>>> token_urlsafe(16) 'Drmhze6EPcv0fN_81Bj-nA'
토큰은 몇 바이트를 사용해야 하나요?
무차별 대입(brute-force) 공격으로부터 안전하려면 토큰에 충분한 무작위성이 필요합니다. 불행히도 충분하다고 여겨지는 것은 컴퓨터가 더 강력해지고 더 짧은 시간에 더 많은 추측을 할 수 있게 됨에 따라 필연적으로 증가합니다. 2015년 기준으로, secrets 모듈에 대해 예상되는 일반적인 사용 사례에는 32바이트(256비트)의 무작위성이 충분하다고 여겨집니다.
자신의 토큰 길이를 관리하려는 사람은 다양한 token_* 함수에 int 인자를 주어 토큰에 사용할 무작위성을 명시적으로 지정할 수 있습니다. 그 인자는 사용할 무작위성의 바이트 수로 취급됩니다.
그렇지 않으면 인자가 제공되지 않거나 인자가 None이면 token_* 함수는 DEFAULT_ENTROPY를 대신 사용합니다.
- secrets.DEFAULT_ENTROPY —
token_*함수가 사용하는 기본 무작위성 바이트 수입니다. 정확한 값은 유지보수 릴리스 중에도 언제든지 변경될 수 있습니다.
기타 함수
- secrets.compare_digest(a, b) —
a와b가 같으면True, 그렇지 않으면False를 반환합니다. 타이밍 공격(timing attack) 위험을 줄이기 위해 "일정 시간 비교(constant-time compare)"를 사용합니다. 자세한 내용은hmac.compare_digest()를 참고하세요.
레시피와 모범 사례
이 섹션은 기본 수준의 보안을 관리하기 위해 secrets를 사용하는 레시피와 모범 사례를 보여줍니다.
8자 영숫자 비밀번호 생성:
import string
import secrets
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(8))
Note
응용 프로그램은 비밀번호를 평문이든 암호화든 복구 가능한 형식으로 저장해서는 안 됩니다. 이들은 암호학적으로 강력한 일방향(비가역) 해시 함수를 사용하여 솔팅(salting)하고 해싱해야 합니다.
적어도 하나의 소문자, 적어도 하나의 대문자, 적어도 세 개의 숫자를 가진 10자 영숫자 비밀번호 생성:
import string
import secrets
alphabet = string.ascii_letters + string.digits
while True:
password = ''.join(secrets.choice(alphabet) for i in range(10))
if (any(c.islower() for c in password)
and any(c.isupper() for c in password)
and sum(c.isdigit() for c in password) >= 3):
break
XKCD 스타일 암호 문구(passphrase) 생성:
import secrets
# On standard Linux systems, use a convenient dictionary file.
# Other platforms may need to provide their own word-list.
with open('/usr/share/dict/words') as f:
words = [word.strip() for word in f]
password = ' '.join(secrets.choice(words) for i in range(4))
비밀번호 복구 응용 프로그램에 적합한 보안 토큰을 포함하는 추측하기 어려운 임시 URL 생성:
import secrets
url = 'https://example.com/reset=' + secrets.token_urlsafe()