You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

防御计时侧信道攻击的Python库与技术及登录API优化问询

防御计时侧信道攻击的Python库与技术

首先得明确,你的现有代码里有两个潜在的计时风险点:一是数据库查询部分,当用户名不存在时one()会抛出异常,这会导致耗时明显不同;二是如果verify_password不是恒定时间的实现,密码错误的位置不同也会带来耗时差异。下面是针对Python生态的具体防御方案:

1. 优先使用恒定时间的比较函数

Python标准库的hmac模块提供了hmac.compare_digest(a, b),这是专门为防御计时攻击设计的——它会逐字节比较两个字符串/字节串,不管匹配失败发生在哪个位置,耗时都是一致的,不会因为提前发现不匹配就提前终止比较。

如果你的verify_password是自行实现的,一定要用这个函数替代普通的==比较。示例:

import hmac
import hashlib

def verify_password(password, stored_hash, salt):
    # 计算输入密码的加盐哈希(示例用PBKDF2)
    input_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
    # 用恒定时间比较哈希值
    return hmac.compare_digest(input_hash, stored_hash)

2. 使用成熟的密码哈希库

不要自己实现密码哈希逻辑,直接用经过安全审计的库,它们的验证方法本身就是恒定时间的:

  • passlib:Python生态中非常流行的密码处理库,支持bcrypt、Argon2等多种安全哈希算法,其验证函数默认是恒定时间实现。示例:
    from passlib.context import CryptContext
    
    # 初始化密码上下文,选择bcrypt算法
    pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
    
    def verify_user(session, username, password):
        # 用first()替代one(),避免用户名不存在时抛出异常导致耗时差异
        user = session.query(Users).filter(Users.username == username).first()
        # 不管用户是否存在,都用一个dummy哈希执行验证,保证路径一致
        stored_hash = user.password_hash if user else pwd_context.hash("dummy-password-123")
        # passlib的verify方法是恒定时间的
        return pwd_context.verify(password, stored_hash)
    
  • bcrypt:专门针对密码哈希的轻量库,其bcrypt.checkpw方法也是恒定时间实现,能有效防御计时攻击。

3. 消除数据库查询的计时差异

你的现有代码中session.query(...).one()会在用户名不存在时抛出NoResultFound异常,这会导致查询阶段的耗时明显不同。解决方法:

  • 用first()替代one(),避免异常抛出;
  • 不管用户是否存在,都执行完全相同的后续逻辑(比如上面例子中,即使用户不存在也会执行一次哈希验证);
  • 可以先用count()查询用户是否存在,再获取哈希,确保查询逻辑的耗时尽量一致(虽然count()本身可能有微小差异,但比异常要好很多)。

额外注意事项

  • 绝对不要在代码中加入基于用户存在与否的分支逻辑(比如“如果用户不存在直接返回False”),必须让所有路径的执行步骤尽量一致;
  • 不要依赖随机延迟来掩盖问题——恒定时间的逻辑才是根本解决方案,随机延迟只是治标不治本的权宜之计。

内容的提问来源于stack exchange,提问作者Chen Levy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:05:55