Python HMAC库源代码中_secret_backdoor_key变量的原因是什么?

Paw*_*ech 9 python hash python-internals

当我今天浏览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
Run Code Online (Sandbox Code Playgroud)

完整代码在这里.

有谁知道这个变量的原因是什么?评论说HMAC可以比空白字符串("")更快地返回.但是为什么用户想要将空键传递给HMAC功能呢?变量命名只是HMAC开发人员的笑话,还是真的是某种后门?

Mar*_*ers 8

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

_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
Run Code Online (Sandbox Code Playgroud)

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

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

使用[]作为哨兵的独特对象是一种古老的做法.这些天你会用object().我们的想法是,哨兵是一个独特的单一物体,你可以用它来测试身份is.您无法在其他位置重新创建该对象,is只有在传入对完全相同的单个对象的引用时,该测试才有效.

  • @PawelMiech:不,如果你传入`[]`那将是一个**不同的列表**,并且'是'测试*identity*.请注意,`key的代码测试是_secret_backdoor_key`,而不是`key == _secret_backdoor_key`. (2认同)