【问题标题】:Generate Jupyter Notebook password without Python在没有 Python 的情况下生成 Jupyter Notebook 密码
【发布时间】:2021-09-28 15:11:45
【问题描述】:

https://jupyter-docker-stacks.readthedocs.io/en/latest/using/common.html#docker-options 之后,您可以定义自己的密码,用于在使用 docker 映像时启动 Jupyter Notebook。

docker run -d -p 8888:8888 jupyter/base-notebook start-notebook.sh --NotebookApp.password='sha1:74ba40f8a388:c913541b7ee99d15d5ed31d4226bf7838f83a50e'

我只能发现使用IPython.lib.passwd()可以生成使用的salted sha1密码。但是,如何在不使用 Python 的情况下生成它?我没有 IPython,或者只是不知道如何使用它。我在 CentOS Stream 上。

【问题讨论】:

    标签: bash jupyter-notebook jupyter sha1 salt


    【解决方案1】:

    您可以使用以下小 shell 脚本来近似原始密码生成算法:

    #!/bin/bash
    
    passphrase="hello, world"
    
    # generate salt
    salt=$(openssl rand -hex 6)
    
    # generate hash
    algorithm=sha1
    echo -n "$(echo ${passphrase} | iconv -t utf-8)${salt}" | openssl dgst -${algorithm} | awk -v alg="${algorithm}" -v salt="${salt}" '{print alg ":" salt ":" $NF}'
    

    为什么会这样(有点)?

    您提到原始密码生成算法是基于IPython.lib.passwd,实际上是在IPython.lib.security 中实现的。相关代码部分是:

    salt_len = 12
    
    h = hashlib.new(algorithm)
    salt = ('%0' + str(salt_len) + 'x') % random.getrandbits(4 * salt_len)
    h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii'))
    
    return ':'.join((algorithm, salt, h.hexdigest()))
    

    为了理解这段代码的作用,首先再次查看生成的输出是很有用的。根据您的问题,我们有一个生成密码的示例:

    sha1:74ba40f8a388:c913541b7ee99d15d5ed31d4226bf7838f83a50e

    冒号将该字符串分为三部分:

    <hashing-algorithm> : <salt> : <hashed salted passphrase>
    

    考虑到这一点,让我们来看看IPython 代码。在顶部,我们定义了用于盐的字符数。让我们仔细检查一下 - 是的,确实,在您的示例中,盐由 12 个字符组成:74ba40f8a388

    接下来,创建散列算法的新实例h。从您的示例中我们知道,algorithm 参数的值为"sha1"

    之后,随机生成一个盐。现在这条线很有趣。如果你没有 Python 背景,百分号 (%) 可能会让你想起整数 modulo operator。但实际上并非如此,因为百分号左边的参数是string类型。所以,更确切地说,这是 (now kind of obsolete) 用于格式化字符串的 Python 语法,与 C 中的 printf 非常相似,除了你不限于 Python 中的 打印,你可以在任何有字符串的地方使用此格式化操作。

    鉴于我们知道salt_len12,这条线基本上简化为:

    salt = '%012x' % random.getrandbits(48)
    

    这意味着盐应该是一个48位的位串,格式为12位十六进制字符串。

    为什么是 48 位?好吧,你需要两个十六进制字符来编码一个字节(0x000xff),所以如果我们的目标是 12 个字符,我们需要 6 个字节 = 48 位。

    return 之前的最后一行将sha1 算法应用于 utf-8 编码密码和 ascii 编码 salt 的串联。

    最后,算法、加盐和散列加盐密码作为连接字符串返回,以冒号 (:) 作为分隔符。

    现在,如果您检查我在上面发布的 shell 脚本,您会发现其中的步骤或多或少是相同的。但是有一个显着的区别,这就是为什么我最初写它只是实际算法的近似值。

    不同之处在于盐的生成方式。虽然结果在这两种情况下都是 12 位十六进制字符串,但 IPython 代码使用 Mersenne-Twister 的实现,而我的脚本基于 MD5 散列。这将导致不同的加密属性。

    但您可以自行决定是否可以接受。不幸的是,我无法从命令行获取 Mersenne Twister 的实现。但是,如果您知道生成 salt 的好方法,请随时更新脚本。它的其余部分不应该受到影响。


    或者,如果您更喜欢没有openssl 的解决方案,您也可以使用这个版本:

    #!/bin/bash
    
    passphrase="hello, world"
    
    # generate salt
    salt=$(tr -dc a-f0-9 < /dev/urandom | head -c 12)
    
    # generate hash
    algorithm=sha1
    echo -n "$(echo ${passphrase} | iconv -t utf-8)${salt}" | sha1sum | awk -v alg="${algorithm}" -v salt="${salt}" '{print alg ":" salt ":" $1}'
    

    但不幸的是,我无法说明通过这种方式通过/dev/urandom 生成的盐的特性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      • 2019-04-03
      • 2019-10-24
      • 1970-01-01
      相关资源
      最近更新 更多