探究Python生成随机字符串

来源:互联网 发布:java中的多态是什么 编辑:程序博客网 时间:2024/05/16 12:13

目前看到的最简洁的方法

import osdef randomString(n):    return (''.join(map(lambda x:(hex(ord(x))[2:]), os.urandom(n))))[0:8]if __name__ == '__main__':    print randomString(16)

来看看 randomString 函数所做的事情

  1. 首先这个函数的一行代码里面,最核心的是 os.urandom(n) 函数,这就是标准库提供的产生随机字串的函数,它的原理我们留到最后再说,现在我们只要知道它会返回一个由参数 n 指定的字节长度的随机字节串(而非字符串,因为可能结果并不能被任何一种字符编码所解释,所以不能称其为字符串)
  2. map(function, iterable, ...) 函数,对可迭代数据结构 iterable 中的每一个元素应用 function 函数,并将结果作为新的 list 返回。在 randomString 函数中的用途是将 os.urandom(n) 所返回的随机字节串中的每个字节传入 lambda 表达式进行处理
  3. lambda x:(hex(ord(x))[2:]) 这个 lambda 表达式的作用是将 os.urandom(n) 返回结果中的每个字节转换为可见的由数字和字母组成的长度为 2 的字符
  4. ord(x) 在此处是计算一个字节 unicode 码值的十进制表示,比如字符 a,unicode code 是 0x0061,则 ord('a') 返回 97,因为十六进制的 61 等于十进制的 97。注:其实这个函数对传入参数是 unicode object 和 8-bit 字符 的操作分别是 unichr()chr() 函数的逆向过程
  5. hex(x) 把十进制的数转换为十六进制,因为此处我们不需要结果中的前导 0x,所以做切片操作 [2:0]
  6. ''.join(str_array)'' 为分隔符把参数重的字符连接成一个字符串

os.urandom(n)

作用

官方文档如是说

os.urandom(n)
​ Return a string of n random bytes suitable for cryptographic use.

​ This function returns random bytes from an OS-specific randomness source. The returned data should be unpredictable enough for cryptographic applications, though its exact quality depends on the OS implementation. On a UNIX-like system this will query /dev/urandom, and on Windows it will use CryptGenRandom(). If a randomness source is not found, NotImplementedError will be raised.

​ For an easy-to-use interface to the random number generator provided by your platform, please see random.SystemRandom.

​ New in version 2.4.

第一段的大意是这个函数将会返回一个适用于加密的 n 个字节长度的随机字符串

那么它内部是如何实现随机的呢?我们通过第二段内容可知,这个函数将会调用系统提供的随机源,依赖于程序运行时的当前系统,在 Windows 上会使用 CryptGenRandom(),而在类 UNIX 系统上将会使用 /dev/urandom

如果当前系统没有提供随机源,那么将会抛出一个 NotImplementedError

源码

这是个蛋疼心碎的过程,费尽九牛二虎之力,在 mac 上翻了半天 python 2.7 的 lib 目录,在 os.py 中没有找到 urandom 这个函数定义,打印 os.__all__ 发现包括 urandom 在内的许多模块并不是直接定义在 os.py 中的,而是扩展(__all__.__extend__)自其它模块

urandom 就是扩展自 posix 模块,看来这玩意是 POSIX 的标准接口,涨姿势了

然而问题又来了,没有找到 posix.py 文件!

只有以下这些名字与 posix 相关的文件

  • posixfile.py
  • posixfile.pyc
  • posixfile.pyo
  • posixpath.py
  • posixpath.pyc
  • posixpath.pyo

在这些文件里面根本没有 urandom 相关字眼(卧尼玛……..

目前在 python 命令行环境下通过内建 help() 函数查看 posix 模块的帮助文档,在文档中可以看到 urandom(),不过也没有具体的实现代码

urandom(...)    urandom(n) -> str    Return n random bytes suitable for cryptographic use.

好吧,我不纠结,这里挖个坑,等有空再研究下(一般这么说的时候都没有下文了呵呵呵呵呵呵

POSIX 中的 urandom 在类 UNIX 系统中的实现

维基百科如是说

In Unix-like operating systems, /dev/random is a special file that serves as a blocking pseudorandom number generator. It allows access to environmental noise collected from device drivers and other sources.[1] Not all operating systems implement the same semantics for /dev/random.

剩下的大篇幅介绍请各位直接去 wiki 上看,内容还是挺丰富的

我的理解如下

/dev/random/dev/urandom 都是 UNIX 提供的产生永不为空的随机字节流的伪设备,有许多程序和安全程序都依赖于它们

/dev/random

  • 优势:随机性足够高
  • 劣势:依赖于系统中断,如果系统中断数不足,则会锁死,尝试读取的进程将会进入等待

/dev/urandom

  • 优势:不依赖系统中断,速度快
  • 劣势:相对前者数据随机性不高,且依赖于系统噪声(当前打开的文件数,进程数等等)