ZetCode

Python os.urandom 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨了 Python 的 os.urandom 函数,该函数生成加密安全的随机字节。我们将涵盖它的用途、安全属性以及在 Python 程序中的实际应用。

基本定义

os.urandom 函数从特定于操作系统的随机源返回随机字节。这些字节适合用于加密。

关键参数:size(要生成的随机字节数)。返回请求长度的字节对象。在类 Unix 系统上,使用 /dev/urandom。

生成随机字节

os.urandom 最简单的用法是生成固定数量的随机字节。此示例展示了随机数据的基本生成和显示。

basic_generation.py
import os

# Generate 16 random bytes
random_bytes = os.urandom(16)

print(f"Random bytes: {random_bytes}")
print(f"Hex representation: {random_bytes.hex()}")
print(f"Length: {len(random_bytes)} bytes")

# Generate different amounts
for n in [1, 8, 32, 256]:
    print(f"{n} bytes: {os.urandom(n).hex()}")

此示例生成 16 个随机字节,并以不同的格式显示它们。它还展示了如何生成不同数量的随机数据。

输出是原始字节,可以将其转换为十六进制以进行显示,或进一步处理以用于特定应用。

创建随机字符串

os.urandom 可以通过编码字节来生成随机字符串。此示例创建指定长度的随机字母数字字符串。

random_strings.py
import os
import base64

def random_string(length):
    # Generate enough random bytes
    bytes_needed = (length * 3 + 3) // 4
    random_bytes = os.urandom(bytes_needed)
    
    # Encode to base64 and adjust length
    return base64.urlsafe_b64encode(random_bytes).decode()[:length]

# Generate various random strings
for length in [8, 16, 32, 64]:
    print(f"{length} chars: {random_string(length)}")

# Alternative using hex encoding
print("\nHex encoded strings:")
for _ in range(3):
    print(os.urandom(8).hex())

这展示了两种方法:用于紧凑字符串的 base64 编码和用于更简单表示的十六进制编码。base64 方法生成 URL 安全的字符串。

请注意,确切的字符集取决于使用的编码方法。

生成随机数

虽然 os.urandom 生成字节,但我们可以将这些字节转换为随机数。此示例演示了在各种范围内生成整数。

random_numbers.py
import os

def random_int(max_value):
    # Calculate bytes needed to cover the range
    byte_count = (max_value.bit_length() + 7) // 8
    while True:
        # Generate random bytes and convert to int
        random_bytes = os.urandom(byte_count)
        num = int.from_bytes(random_bytes, 'big')
        
        # Ensure the number is within range
        if num < max_value:
            return num

# Generate random numbers in different ranges
for max_val in [10, 100, 1000, 10000]:
    print(f"Random 0-{max_val-1}: {random_int(max_val)}")

# Generate a random float between 0 and 1
random_bytes = os.urandom(8)
random_float = int.from_bytes(random_bytes, 'big') / (1 << 64)
print(f"\nRandom float: {random_float}")

此代码展示了如何在范围内生成均匀分布的整数。浮点示例演示了将字节转换为浮点数。

对于加密应用,此方法优于 random 模块。

创建安全令牌

os.urandom 非常适合生成安全令牌,例如 CSRF 令牌或密码重置令牌。此示例展示了令牌生成。

secure_tokens.py
import os
import secrets
import hashlib

def generate_token(length=32):
    """Generate a URL-safe secure token"""
    return secrets.token_urlsafe(length)

def generate_hashed_token(salt=None, length=32):
    """Generate a hashed token with optional salt"""
    if salt is None:
        salt = os.urandom(16)
    token = os.urandom(length)
    hashed = hashlib.sha256(salt + token).hexdigest()
    return f"{salt.hex()}:{hashed}"

# Generate various tokens
print("Simple tokens:")
for _ in range(3):
    print(os.urandom(16).hex())

print("\nURL-safe tokens:")
for _ in range(3):
    print(generate_token())

print("\nHashed tokens:")
for _ in range(3):
    print(generate_hashed_token())

这演示了三种方法:原始十六进制令牌、使用 secrets(在内部使用 os.urandom)的 URL 安全令牌,以及使用 salt 的哈希令牌。

对于 Web 应用程序,secrets 模块通常是最佳选择。

加密密钥生成

os.urandom 适用于生成加密密钥。此示例展示了对称和非对称密钥生成。

key_generation.py
import os
from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

# Generate AES key
aes_key = os.urandom(32)  # 256-bit key
print(f"AES-256 key: {aes_key.hex()}")

# Generate HMAC key
hmac_key = os.urandom(64)  # 512-bit key
print(f"HMAC-SHA512 key: {hmac_key.hex()}")

# Generate RSA key using os.urandom as entropy source
def generate_rsa_key():
    def urandom_entropy(num_bytes):
        return os.urandom(num_bytes)
    
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=None,
        entropy=urandom_entropy
    )
    
    pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption()
    )
    return pem

rsa_key = generate_rsa_key()
print("\nRSA private key:")
print(rsa_key.decode())

这展示了如何为对称加密 (AES)、消息身份验证 (HMAC) 和非对称加密 (RSA) 生成密钥。

对于生产用途,请考虑更高级别的库,如 cryptography。

密码哈希

os.urandom 对于通过提供加密 salt 来安全地哈希密码至关重要。此示例演示了正确的密码存储。

password_hashing.py
import os
import hashlib
import bcrypt
import argon2

def simple_hash(password):
    """Basic salted hash using SHA-256"""
    salt = os.urandom(32)
    hash_obj = hashlib.sha256(salt + password.encode())
    return f"{salt.hex()}:{hash_obj.hexdigest()}"

def bcrypt_hash(password):
    """Bcrypt password hashing"""
    salt = bcrypt.gensalt()
    return bcrypt.hashpw(password.encode(), salt)

def argon2_hash(password):
    """Argon2 password hashing"""
    salt = os.urandom(16)
    hasher = argon2.PasswordHasher(
        time_cost=3, memory_cost=65536, parallelism=4, hash_len=32, salt_len=16
    )
    return hasher.hash(password, salt=salt)

# Example usage
password = "secure_password123"

print("Simple hash:")
print(simple_hash(password))

print("\nBcrypt hash:")
print(bcrypt_hash(password).decode())

print("\nArgon2 hash:")
print(argon2_hash(password))

这展示了三种具有越来越高安全性的密码哈希方法。所有这些方法都直接或间接地使用 os.urandom 来生成 salt。

对于新的应用程序,建议使用 Argon2 或 bcrypt 而不是简单的哈希。

安全注意事项

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程