私たちのウェブアプリでは、使い捨てトークンをうまく利用しています。たとえば、誰かが3つの「アカウント」のいずれかを作成したり、パスワードをリセットしたり、ランダムな使い捨てトークンを必要とするその他の数のことをしたりした場合、次のようになります。
これはすべて正常に動作します。ただし、プロファイリングを通じて、API呼び出しの一部はトークンの確認と作成の両方を行う必要があるため、数秒かかることがわかりました。一部のAPI呼び出しは、Scryptを3回以上使用します。
ひどくはありませんが、可能であればAPI呼び出しを高速化したいと考えています。
私はいくつかのランダムなトークンを事前に生成するという考えを浮かび上がらせましたが、先に進んでこれを始める前に、セカンドオピニオンをお願いします。
これについては、2つの方法があると思います。まず、単純に(トークン、ハッシュ、ソルト)トリプルを作成し、メモリに格納します。これの欠点は、暗号化されていないトークンがそこにあるだけであり、攻撃者がそれらを取得して使用できることです。ただし、そのためには特定のAWSインスタンスへのアクセスが必要であり、1回限りのトークンはその状況での懸念が最も少ないでしょう。
2つ目は、ある種のボールトを使用することです。そのため、タプルはまだメモリ内にありますが、暗号化されています。これは安全に聞こえますが、ボールトのパスワードをどこかに置く必要があるため、攻撃者がAWSインスタンスにアクセスできる場合は、ボールトへのアクセスが可能です。
考え?私はこの考えに少し警戒していますが、いくつかのAPI呼び出しを3秒から1秒未満に減らしたいと思っています。
概要:あなたのような本当にランダムなデータに対してscryptを使用する必要はありません。 SHA256のような安全なハッシュを使用するだけで大丈夫です。
説明:SHA256のようなハッシュは、私たちの知る限りでは不可逆的です。ハッシュから元のテキストに移動する唯一の方法は、事前計算と総当たりの組み合わせを使用することです。人々は弱い予測可能なパスワードを選択するため、事前計算はパスワードの保存に非常に成功していることがわかります。これが、パスワードハッシュの科学全体を作成する必要がある理由です。
ただし、256ビットのエントロピーがあります。 Rainbow table (この惑星に格納するスペースがない)または総当たり(太陽は途中で爆発する)を生成することは不可能です。大きな入力スペース。
ですから、ランダムデータに高速のSHA256を使用して、それが解読不可能であることを確認してください。
トークンを事前に生成すると、攻撃者がトークンにアクセスすることを心配していると言います。これは技術的にはより大きなウィンドウを提供しますが、攻撃者がとにかく生成されている安全なトークンを監視することははるかに困難です。
私たちがパスワードをハッシュ化する理由は、今後数年間の違反がパスワードを明らかにしないためです。この場合、過去の違反からわずか1分が問題です。 1分前に誰かがあなたに違反した場合、彼らもおそらくあなたが知っている違反をすることができます。
私の提案はこれです:
ニールの答え も正しいです(何らかの理由でSha256の動作が遅い場合は、上記を使用できます)。
ランダムトークンでscryptを実行するのではなく、このような状況では、hmacを生成します。 redditのオープンソースの電子メール購読解除トークンコード の例を次に示します。
def generate_notification_email_unsubscribe_token(user_id36, user_email=None,
user_password_hash=None):
"""Generate a token used for one-click unsubscribe links for notification
emails.
user_id36: A base36-encoded user id.
user_email: The user's email. Looked up if not provided.
user_password_hash: The hash of the user's password. Looked up if not
provided.
"""
import hashlib
import hmac
if (not user_email) or (not user_password_hash):
user = Account._byID36(user_id36, data=True)
if not user_email:
user_email = user.email
if not user_password_hash:
user_password_hash = user.password
return hmac.new(
g.secrets['email_notifications'],
user_id36 + user_email + user_password_hash,
それが1回だけ使用されることを確認する必要がある場合は、現在行っているように、その値をデータベースに追加で挿入し、一度使用したら削除できます。