【问题标题】:What is the reason for _secret_backdoor_key variable in Python HMAC library source code?Python HMAC库源代码中_secret_backdoor_key变量的原因是什么?
【发布时间】:2016-07-12 09:07:13
【问题描述】:

今天在浏览 Python HMAC 模块源代码时,发现其中包含全局变量_secret_backdoor_key。然后检查该变量以中断对象初始化。

代码如下所示

# A unique object passed by HMAC.copy() to the HMAC constructor, in order
# that the latter return very quickly.  HMAC("") in contrast is quite
# expensive.
_secret_backdoor_key = []

class HMAC:
    """RFC 2104 HMAC class.  Also complies with RFC 4231.

    This supports the API for Cryptographic Hash Functions (PEP 247).
    """
    blocksize = 64  # 512-bit HMAC; can be changed in subclasses.

    def __init__(self, key, msg = None, digestmod = None):
        """Create a new HMAC object.

        key:       key for the keyed hash object.
        msg:       Initial input for the hash, if provided.
        digestmod: A module supporting PEP 247.  *OR*
                   A hashlib constructor returning a new hash object.
                   Defaults to hashlib.md5.
        """

        if key is _secret_backdoor_key: # cheap
            return

完整的code is here

有谁知道这个变量的原因是什么?评论说 HMAC 比空白字符串(“”)返回得更快。但是为什么用户想要将空密钥传递给 HMAC 函数呢?变量命名只是 HMAC 开发者的玩笑还是真的是某种后门?

【问题讨论】:

    标签: python hash python-internals


    【解决方案1】:

    要创建 HMAC 实例的副本,您需要先创建一个 empty 实例。

    _secret_backdoor_key 对象用作提前退出__init__ 的哨兵,而不是运行__init__ 功能的其余部分。 copy 方法然后直接设置实例属性:

    def copy(self):
        """Return a separate copy of this hashing object.
    
        An update to this copy won't affect the original object.
        """
        other = self.__class__(_secret_backdoor_key)
        other.digest_cons = self.digest_cons
        other.digest_size = self.digest_size
        other.inner = self.inner.copy()
        other.outer = self.outer.copy()
        return other
    

    您可以使用self.__class__('')(一个空字符串)获得相同的效果,但随后HMAC.__init__ 做了很多不必要的工作,因为创建的实例上的属性将被替换无论如何 .请注意,使用HMAC('') 是一种创建实例的有效方式,在这种情况下,您不希望实例没有任何状态。通过传入哨兵,HMAC.copy() 可以避免所有额外的工作。

    您可以使用不同的“标志”值,例如False,但由于您自己的代码中存在错误,因此传递它太容易了。相反,您希望收到有关此类错误的通知。通过使用“秘密”内部哨兵对象,您可以避免此类意外情况。

    使用[] 作为标记唯一对象是一种非常古老的做法。这些天你会改用object()。这个想法是,哨兵是一个独特的、单一的对象,您可以使用is 对其进行身份测试。您无法在其他地方重新创建该对象,is 测试仅在您传入对完全相同的单个对象的引用时才有效。

    【讨论】:

    • 感谢您的回答,这很有趣,但是为什么要使用一些哨兵值而不是空字符串呢?为什么空字符串或布尔值 False 会更慢?
    • @PawelMiech:传入一个空字符串是一个有效的用例,您希望正确创建实例。 False 可以,但你必须记录下来。这仅供内部使用,并且哨兵值是内部和秘密的。你不会不小心传入那个对象。
    • 好的,这就解释了。但是可能仍然可以将 [] 作为事故或错误传递,不是吗?当知道从 copy() 调用 init 时,添加显式关键字参数会停止 init 不是更好吗?例如 init:"early_exit" 的额外参数,默认为 False,如果从副本调用,则为 True。
    • @PawelMiech:不,如果你传入[],那将是一个不同的列表is 会测试身份。请注意,代码测试的是key is _secret_backdoor_key,而不是key == _secret_backdoor_key
    猜你喜欢
    • 1970-01-01
    • 2012-11-10
    • 2022-11-18
    • 1970-01-01
    • 2021-01-15
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多