私は間違いを犯し、Django プロジェクトSECRET_KEY
をパブリック リポジトリにコミットしました。
docs によると、この鍵は秘密にしておくべきでした。
Django プロジェクトはライブであり、アクティブなユーザーによってしばらくの間実行されています。を変更するとどのような影響がありSECRET_KEY
ますか? 既存のユーザー、Cookie、セッションなどは影響を受けますか? 明らかに、新しいSECRET_KEY
ものは公共の場所に保存されなくなります。
私は間違いを犯し、Django プロジェクトSECRET_KEY
をパブリック リポジトリにコミットしました。
docs によると、この鍵は秘密にしておくべきでした。
Django プロジェクトはライブであり、アクティブなユーザーによってしばらくの間実行されています。を変更するとどのような影響がありSECRET_KEY
ますか? 既存のユーザー、Cookie、セッションなどは影響を受けますか? 明らかに、新しいSECRET_KEY
ものは公共の場所に保存されなくなります。
編集:この回答は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 に取り組んでいます。ソースをざっと見てみると、ほとんど同じ答えが得られます。後で精密検査をするかもしれません。
この質問があったため、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
$
このページhttps://docs.djangoproject.com/en/dev/topics/signing/によると、SECRET_KEYは主に一時的なものに使用されます-たとえば、改ざんを検出できるように、ネットワーク経由で送信されるデータに署名します。壊れる可能性のあるものは次のとおりです。
私よりも最近の、または顕著な Django の経験を持っている人は別の方法でチャイムを鳴らすかもしれませんが、署名 API を使用して明示的に何かを行っていない限り、これはユーザーに軽度の不便をもたらすだけであると思います。
SECRET_KEY 文字列は、主に Cookie データの暗号化および/またはハッシュに使用されます。デフォルトのセッション Cookie には独自の欠点があるため、多くのフレームワーク (Django を含む) がこれに到達します。
非表示フィールドを持つ記事を編集するためのフォームが django にあると想像してください。この隠しフィールドには、編集中の記事の ID が保存されます。また、他の記事 ID が送信されないようにしたい場合は、ハッシュ ID を含む隠しフィールドを追加します。したがって、誰かが ID を変更した場合、ハッシュが同じではないため、それがわかります。
もちろん、これは些細な例ですが、これが SECRET_KEY の使用方法です。
Django は、たとえば {% csrf_token %} などのために内部的に使用しています。質問に基づいて、それを使用していないことに基づいて変更しても、実際にはアプリケーションに影響を与えるべきではありません。
唯一のことは、セッションの値が削除される可能性があることです。たとえば、django は別のキーでセッションをデコードできないため、ユーザーは再度 admin にログインする必要があります。
私はこれと同じ間違いをしました。デフォルトのパスワードは 50 文字だったので、powershell を使用して 50 文字のランダムな文字列を生成し、古い SECRET_KEY をそれに置き換えました。ログインしていて、SECRET_KEY を置き換えた後、以前のセッションが無効になりました。
Powershell の場合 ( source ):
# 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 の場合 ( source ):
# 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 の長いキーで試してみました。どちらも機能しました。ソース コードを理解していれば、signer 関数によって返されるオブジェクトは 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 ビット) でカバーされます。