我犯了一个错误,并将Django项目SECRET_KEY
提交到公共存储库中。
根据文档https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY,此密钥应保持秘密
Django项目已经启动,并且已经有一些活跃用户运行了一段时间。如果更改,会产生什么影响SECRET_KEY
?现有的用户,Cookie,会话等是否会受到影响?显然,新产品SECRET_KEY
将不再存储在公共场所。
我犯了一个错误,并将Django项目SECRET_KEY
提交到公共存储库中。
根据文档https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY,此密钥应保持秘密
Django项目已经启动,并且已经有一些活跃用户运行了一段时间。如果更改,会产生什么影响SECRET_KEY
?现有的用户,Cookie,会话等是否会受到影响?显然,新产品SECRET_KEY
将不再存储在公共场所。
Answers:
编辑:此答案基于Django 1.5
SECRET_KEY
在很多地方都使用过该工具,我将首先指出它会受到什么影响,然后尝试遍历该列表并给出影响的精确解释。
SECRET_KEY
直接或间接使用的事物列表:
startproject
实际上,这里列出的许多项目都可以SECRET_KEY
通过django.utils.crypt.get_random_string()
它来为随机引擎提供种子。不会受到值更改的影响SECRET_KEY
。
价值变化直接影响的用户体验是:
django.contrib.comments
)将无法验证它是否在值更改之前被请求并在值更改之后被提交。我认为这是非常小的,但可能会使用户感到困惑。django.contrib.messages
)的消息将无法在与注释表单相同的时间条件下验证服务器端。更新:现在可以在Django 1.9.5上运行,快速查看源代码可以得到几乎相同的答案。以后可能要进行彻底检查。
SECRET_KEY
(用于salted_hmac
对会话数据进行哈希处理)。
<algorithm>$<iterations>$<salt>$<hash>
在AUTH_USER,所以随机盐一同存储在每种情况下的密码。
自从提出此问题以来,Django文档已更改为包含答案。
密钥用于:
- 如果您使用的会话后端不是
django.contrib.sessions.backends.cache
或使用默认会话,则所有会话get_session_auth_hash()
。- 如果使用
CookieStorage
或,则显示所有消息FallbackStorage
。- 所有
PasswordResetView
令牌。- 加密签名的任何用法,除非提供了不同的密钥。
如果您旋转密钥,以上所有内容将失效。秘密密钥不用于用户密码,密钥旋转不会影响它们。
我不清楚我该如何旋转密钥。我找到了关于Django如何为新项目生成密钥的讨论,以及讨论其他选项的Gist 。我最终决定只让Django创建一个新项目,将新密钥复制到我的旧项目中,然后擦除该新项目。
cd ~/junk # Go to some safe directory to create a new project.
django-admin startproject django_scratch
grep SECRET_KEY django_scratch/django_scratch/settings.py # copy to old project
rm -R django_scratch
看起来Django 在1.10版中添加了该get_random_secret_key()
功能。您可以使用它来生成新的密钥。
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
s!)5@5s79sp=92a+!f4v!1g0d0+64ln3d$xm1f_7=749ht&-zi
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
_)+%kymd=f^8o_fea1*yro7atz3w+5(t2/lm2cz70*e$2mn\g3
$
startproject
,您会发现它只是使用crypto
模块生成了一个随机字符串。
根据此页面https://docs.djangoproject.com/en/dev/topics/signing/,SECRET_KEY主要用于临时性内容-对通过网络发送的数据进行签名,以便例如检测篡改。看起来可能会中断的事情是:
可能有比我更早和/或重要的Django经验的人,但是我怀疑除非您明确地使用签名API进行操作,否则这只会给用户带来不便。
SECRET_KEY字符串主要用于加密和/或哈希Cookie数据。许多框架(包括Django)都可以使用此功能,因为默认会话cookie具有其自身的缺点。
想象一下,您在django中具有用于编辑带有隐藏字段的文章的表单。在此隐藏字段中存储了您正在编辑的文章的ID。而且,如果您想确保没有人可以向您发送任何其他文章ID,则将添加一个带有哈希ID的额外隐藏字段。因此,如果有人更改ID,您将知道它,因为哈希不会相同。
当然,这是一个简单的示例,但这就是SECRET_KEY的使用方式。
Django内部使用它,例如用于{%csrf_token%}和其他一些东西。如果您根据自己的问题并且未使用它来进行更改,那么它实际上不会对您的应用程序产生任何影响。
唯一的是,可能会删除会话值。因此,例如,用户将不得不再次登录admin,因为django将无法使用其他密钥来解码会话。
我犯了同样的错误。默认密码为50长,因此我使用powershell生成了50长的随机字符串,并用它替换了旧的SECRET_KEY。我已登录,并且在替换SECRET_KEY之后,我之前的会话已失效。
使用Powershell(来源):
# Load the .net System.Web namespace which has the GeneratePassword function
[Reflection.Assembly]::LoadWithPartialName("System.Web")
# GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
[System.Web.Security.Membership]::GeneratePassword(50,5)
使用Bash(来源):
# tr includes ABCabc123 and the characters from OWASP's "Password special characters list"
cat /dev/urandom | tr -dc 'A-Za-z0-9!"#$%&\''()*+,-./:;<=>?@[\]^_`{|}~' | head -c 100 ; echo
此时,我想为什么不尝试使用更大的密钥,所以我尝试了100和1000长的密钥。两者都起作用。如果我理解源代码,则签名者函数返回的对象是base64中的hmac哈希。RFC 2104要求HMAC密钥的长度。
使用比B字节长的密钥的应用程序将首先使用H对密钥进行哈希处理,然后将所得的L字节字符串用作HMAC的实际密钥。
HMAC的密钥可以是任何长度(长于B字节的密钥首先使用H进行哈希处理)。但是,强烈建议少于L个字节,因为这会降低功能的安全性。长度超过L个字节的键是可以接受的,但是额外的长度不会显着增加功能强度。(如果认为密钥的随机性较弱,则建议使用较长的密钥。)
要转换为普通话,密钥的大小必须与输出大小相同。密钥也需要以位为单位。base64中的每个数字代表6位。因此,如果您拥有50个字符的密码,那么您将拥有一个50 x 6 = 300位的秘密密钥。如果您使用的是SHA256,则需要一个256位的密钥(sha256根据定义使用256位)。因此,除非您打算使用大于SHA256的哈希算法,否则50长密码应该可以工作。
但是,由于密钥中的任何多余位都将被散列,因此其大小不会大大降低性能。但这将保证您有足够的位数用于较大的哈希函数。SHA-512将被100个长的SECRET_KEY(50 x 6 = 600位> 512位)覆盖。
data decode will break
,或者指出一些可能会破坏代码(在Django或示例项目中)?编辑:仍在使用django 1.4-是这种情况吗?