示例说明
random 模块的伪随机可被预测,安全令牌必须用 secrets——它调用操作系统的密码学随机源。三类令牌各有形态:API key 用受控字母表拼出可人读的带前缀键;token_urlsafe 输出 URL 免转义的紧凑串;验证码用 randbelow 限定位数。比较环节的恒时比较防时序侧信道,普通等号比较会在首个不匹配字符处提前返回。
技术要点
- secrets 基于操作系统密码学随机源
- compare_digest 恒时比较防时序攻击
- 令牌附带作用域提示便于审计
代码解读
api_key 用 choice 按字母表取四十个字符并加业务前缀;otp_code 以 randbelow 生成定长数字码;constant_time_match 先比长度再用 compare_digest 比较字节。scoped_token 把令牌与作用域绑定返回结构化结果,作用域泄漏时影响面可控。
使用建议
令牌只显示一次,存储侧只存哈希。前缀便于泄漏扫描工具识别。验证码的有效期与尝试次数限制要在服务端配套。
代码示例
import hmac
import secrets
ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
def api_key(prefix: str = 'sk') -> str:
body = ''.join(secrets.choice(ALPHABET) for _ in range(40))
return f'{prefix}_{body}'
def url_token(nbytes: int = 32) -> str:
return secrets.token_urlsafe(nbytes)
def otp_code(digits: int = 6) -> str:
# 朴素做法 random.randint 可预测,必须用 secrets
floor = 10 ** (digits - 1)
return str(floor + secrets.randbelow(9 * floor))
def constant_time_match(candidate: str, expected: str) -> bool:
if len(candidate) != len(expected):
return False
return hmac.compare_digest(
candidate.encode(), expected.encode()
)
def scoped_token(scope: str, nbytes: int = 16) -> dict:
return {
'token': url_token(nbytes),
'scope': scope,
'hint': f'scope={scope}',
}
key = api_key()
code = otp_code()
print('key length:', len(key), 'otp:', code)
print('compare ok:', constant_time_match(code, code))
print('compare tampered:', constant_time_match(code, '123456'))