「Remember Me」機能を実装する必要があるモバイルアプリケーションを開発しています。ログインが必要なアプリケーション内の特定のページがあります。私がする必要があるのは、「Remember Me」チェックボックスが選択されている場合、ユーザーがログアウトして再度ログインページに到達したときに後で入力できるように、ユーザー名とパスワードを保存する必要があることです。
以前の実装では、ログインフォームからデータをキャプチャしてローカルストレージに保存しました。しかし、どうすればそれを保護できるかを知る必要があります。
私は this answer で与えられたアドバイスに従って、サンプル実装を実装しました。 [〜#〜] sjcl [〜#〜] を使用して、データを(JavaScriptで)暗号化および復号化しています。
function encryptLoginData(data) {
//Generate PBKDF2
var result = sjcl.misc.cachedPbkdf2(data.password, {count: 1000});
var key = sjcl.codec.hex.fromBits(result.key);
var salt = sjcl.codec.hex.fromBits(result.salt);
//Encrypt data using the key and the salt generated from password
var finalData = sjcl.json.encrypt(key, JSON.stringify(data), {salt: salt});
var encryptedData = JSON.stringify([key, finalData]);
return encryptedData;
}
後で、私が使用しているデータを入力するために:
function decryptLoginData(data) {
//Decryption of login data
var fetchedData = JSON.parse(data);
var decryptedData = JSON.parse(sjcl.json.decrypt(fetchedData[0], fetchedData[1]));
return decryptedData;
}
気づいたら、後で解読できるように、キーと暗号化されたデータを一緒に保存する必要があります。ただし、JavaScriptとキーにアクセスできるユーザーは、単一のsjcl.json.decrypt
を使用してデータを簡単に復号化できます。私が思うに、私はデータをさらに不明瞭にしているだけで、実際には保護していませんか?何か不足していますか?これを行うより安全な方法はありますか?
PS:私は暗号化の初心者です。
暗号化を初めて使用する場合は、暗号化を使用しないでください。ここでは個人的なものはありません。 セキュリティをテストできないためです。一部のシステム/プロトコル/アルゴリズムが安全かどうかは、簡単には(またはまったく)わかりません。そのようなテストは単に存在しません。これは、テストが可能な機能とは非常に異なります。サーバーが起動して要求に応答するかどうかを確認するのは簡単ですが、これがすべて発生しているかどうかを確認することはできませんsecurely。その理論的な理由には、 停止問題 のような根本的な根があります。
暗号を正しく使用する唯一の既知の方法は、暗号の研究に一生を捧げた人々の手にそれを任せることです。 それらの人があなたのシステムへの攻撃をまとめて思いつくことができない場合、何年もの無音の苦労と瞑想にもかかわらず、あなたのシステムはおそらくです安全、または少なくとも競合他社よりも安全であり、多くの場合十分です。
「remember me」機能は、ユーザー側の状態を維持することです。そのため、ユーザーがサーバーに戻ったときに、サーバーは自動的に認識します彼、そして厄介なパスワードの入力を求めません。どのように表現しても、これはユーザーデバイス(携帯電話、私が理解しているように)には、特別なユーザー操作なしでサーバーに "ログオン"するために必要なものがすべて含まれていることを意味します。特に、携帯電話が盗まれた場合、泥棒は同じデータを入手してサーバーにログオンできます。これは避けられないことであり、それが(繰り返しになりますが)基本的なことです。ユーザーがパスワードを入力する必要がない場合、人間のユーザーについては何も特定されず、物理的な存在は必要ありません。それが多かれ少なかれ、「覚えておく」機能のポイントです。
暗号化の量はどこでも変更されません。アプリがユーザーの介入なしにサーバーにログオンできる場合、それは可能です。
したがって、「記憶」機能は回避できないリスクであり、ユーザーエクスペリエンスの向上とバランスを取る必要があります(ユーザーは基本的に、パスワードを入力するよりもパスワードを入力しないことを好みます)。トレードオフをもう少し有利にするいくつかの方法があります。
アプリが保存するものは何でも、パスワードに依存しないようにします。ユーザーパスワードまたはユーザーパスワードから計算されたハッシュを保存しないでください。ユーザーパスワードは機密データであり、その範囲はアプリを超えています。ユーザーパスワードは、脳へのハイウェイです。代わりに、サーバー側でランダムに生成された「セッションキー」を保存します。 (少なくとも)16バイト長にして、サーバーで cryptographically secure PRNG を使用して生成します(例:/dev/urandom
またはその周りのラッパー)。
ランダムセッションキーを使用している場合は、いつでもサーバーでキーを取り消すことができます。これは、ユーザーのパスワードと比較すると良いことです。ユーザーに潜在的な攻撃者は言うまでもなく、パスワードを「忘れさせる」ことができないためです。
時間制限を設けてください。たとえば、「記憶」機能を1週間有効にします。これにより、ユーザーは定期的にパスワードを再入力する必要がありますが、スケジュールを選択できます。さらに、トレードオフ。時間制限付きのセッションキーを使用すると、厳密に制限された時間枠内で攻撃者によるダメージを抑えることができます。
だから今あなたの問題は「単純に」問題です:
HTTP/Webコンテキストでは、このすべてはすでに存在し、呼び出されます HTTP cookies 。 "Secure" and "HttpOnly" フラグを設定し、SSL(HTTPS)を使用していることを確認してください(SSLを使用していない場合は、すでに大きな問題がたくさんあるため、最初にそれを行います)。 安全に実装するのが最も簡単なシステムは、すでに誰かが安全に実装しているシステムです。そのまま使用してください。
ここで、アプリが非協力的なサーバーにログオンしようとしていて、「remember me」機能をまったく認識しておらず、セッションキーをCookieとして送信しない場合は、問題。その腐敗した状況では、クライアント側にユーザー資格情報を保存する必要があり、それは良くありません。 パスワードマネージャーソフトウェア はそのような問題に対処しようとしますが、トレードオフは前述のように良くありません。ユーザーは一般的にそれを好まないでしょう。ユーザー「マスターパスワード」を使用したローカル暗号化が行われますが、これは難しい問題です。さらに、Javascriptはまったく適切ではありません(特にパフォーマンスが低く、遅いハッシュと矛盾するため) 。
あなたがそこに行かないならそれは非常に好ましいです。
あなたが言うように、あなたは絶対的に正しいです:
javaScriptとキーにアクセスできる人なら誰でも、単一のsjcl.json.decryptを使用してデータを簡単に復号化できます。
しかしながら、
何か不足していますか?
はい:
原則として、JavaScriptのセキュリティ(暗号化)にはあまり価値がありません。なぜ、それが純粋にセキュリティプリンシパルにあるのか 自分が制御できないローカルマシン/デバイスを信頼すべきではありません。
PBKDF2は復号化を許可しません。ハッシュ関数です。
ローカルストレージは新しく、この新しいテクノロジーがハッキングされる可能性があります
これを行うより安全な方法はありますか?
はい、次のベストプラクティスに従ってください。
複雑さがセキュリティの弱点を引き起こすため、JavaScript認証を簡素化します。修正しようとしている問題はすでに解決されています。ユーザーが安全にログオンすると、サーバーに永続的なSecure
、HTTP only
cookieを保存させます。
現在パスワードを検証しているサーバー側コードの場合、呼び出しを続行する前にCookieを検証するようにします。
(サーバー側の)記憶機能を取り消し/期限切れにする機能をサポートします。これは、一意のGUID Cookieごと、またはGUIDの有効期限を含む、サーバーでハッシュ/署名されたJSON文字列を使用して行うことができます。
LocalStorageに異なるSSOキーを保存し、各呼び出しのキーのペアを検証することで、攻撃者がキーを抽出するのをより困難にすることができます。 (Localstorage + Secure/Persistent/HTTP cookie)
携帯電話に認証情報を保存する安全な方法はありません。一般的に使用されるアプローチは、ユーザーにアプリのパスワードを設定することを要求することです。このパスワードは、記憶する必要のある情報を暗号化するために使用されます。このパスワードは電話に保存されません(アプリを使用するときのメモリ内を除く)。
覚えておく必要のあるパスワードを1つだけ使用している場合、残念ながらこのデータを保存する安全な方法はありません。他の唯一のオプションは、難読化を使用することです。これは、あいまいさによるセキュリティです。