Python中生成API KEY和SECRET的最简单、最安全的方法是什么?

60

我需要生成一个 API 密钥和密钥,它们将被存储在 Redis 服务器中。生成密钥和密钥的最佳方法是什么?

我正在开发一个基于 Django-tastypie 框架的应用程序。


2
django.utils.crypto中有get_random_string函数,参见https://dev59.com/W18e5IYBdhLWcg3wPIeA - Kos
5个回答

96
如果您使用的是Python 3.6或更高版本,则最好使用 secrets 模块:

secrets 模块用于生成适用于管理诸如密码、帐户身份验证、安全令牌和相关机密数据等数据的加密强度随机数。

特别地,应优先使用 secrets 而不是 random 模块中的默认伪随机数生成器。后者旨在用于建模和仿真,而非安全或加密。

例如,要生成一个16字节的令牌:

>>> import secrets
>>> secrets.token_urlsafe(16)
'zs9XYCbTPKvux46UJckflw'
>>> secrets.token_hex(16)
'6bef18936ac12a9096e9fe7a8fe1f777'

10
谢谢!这是一个可以直接从终端调用的版本: python -c 'import secrets; print(secrets.token_urlsafe(16))' - Paweł Mucha
对于在Windows上通过cmd运行Pawel的代码的用户,如果出现错误SyntaxError: EOL while scanning string literal,请将单引号替换为双引号。 - user5305519
token_urlsafetoken_hex之间的区别有什么建议?每个用例推荐使用哪一个? - lowercase00
最好只在数据库中保存生成的令牌的哈希值。如果不太偏离主题,您能否推荐一些计算哈希值的方法? - chrisinmtown
它说,“设计用于建模和仿真,而非安全或密码学”。在生产中使用是否安全? - Rahul Dey
1
@RahulDey,它说应该优先使用随机模块中的默认伪随机数生成器,该生成器是为...设计的,因此这些信息不是关于“secrets”,而是关于“random”。 - bkis

74

适用于Python3.6+

import secrets

generated_key = secrets.token_urlsafe(length)

对于旧版本的Python

要想非常安全地生成随机数,您应该使用urandom:

from binascii import hexlify

key = hexlify(os.urandom(length))

如果需要字节,请使用key.encode(),如果需要字符串,请调用key.decode()

对于生成一般非安全随机字符串,使用Python方法生成您所需长度的密钥即可:

import random
import string

def generate_key(length):
    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))

然后你可以使用你想要的长度来调用它key = generate_key(40)
你可以指定你想要使用的字母表,例如仅使用string.ascii_lowercase生成只包含小写字母的密钥等。

tastypie还有一个API身份验证模型,值得一看https://django-tastypie.readthedocs.org/en/latest/authentication.html#apikeyauthentication


不确定为什么这个被踩了,os.urandom() 既简单又安全。 - Seán Hayes
1
如果您使用的是Python 3.6+,请向下滚动。Moby Duck提出了一个更简单的解决方案。 - Paweł Mucha

4
您可以使用以下模块生成随机字符串。
 1 - os.urandom(64).encode('hex') #from os module
 2 - uuid.uuid4()                 # from uuid module
 3 - get_random_string(length=32) #from django.utils.crypto
 4 - secrets.token_hex(64)         #from secrets >= python 3.6 

2

由于我无法评论T. Opletals的答案,因此我会添加答案。

您不应使用random.choice,因为随机数不具有加密安全性。更好的选择是使用random.SystemRandom(),它使用系统的随机源,在Linux上这将是urandom。

def generate_key(length):
    char_set = string.ascii_letters + string.punctuation                    
    urand = random.SystemRandom()                                           
    return ''.join([urand.choice(char_set) for _ in range(length)])

1

如果您想要一个易于使用但高度可定制的密钥生成器,请使用key-generator pypi包。

这里是GitHub存储库,您可以在其中找到完整的文档。

以下是一个示例:

from key_generator.key_generator import generate

custom_key = generate(2, ['-', ':'], 3, 10, type_of_value = 'char', capital = 'mix', seed = 17).get_key()
print(custom_key)  # ZLFdHXIUe-ekwJCu

希望这可以帮到你 :)
声明:这个使用了我开发的 key-generator 库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接