web-dev-qa-db-ja.com

一般的に信頼できると考えられているSHA-256 JavaScript実装はありますか?

私はフォーラムのログインを書いていますが、サーバーに送信する前にjavascriptでクライアント側のパスワードをハッシュする必要があります。実際にどのSHA-256実装を信頼できるかを判断するのに苦労しています。私は誰もが使用する何らかの種類の信頼できるスクリプトがあることを期待していましたが、すべて独自の実装を持つさまざまなプロジェクトの負荷を見つけています。

自分でレビューする資格がない限り、他の人の暗号を使用することは常に信仰の飛躍であり、「信頼できる」という普遍的な定義はないことを理解していますが、これは何らかの種類があるはずの一般的で重要なもののようです何を使用するかについてのコンセンサス。私は単純ですか?

コメントにたくさん出てくるので編集します。はい、サーバー側でより厳しいハッシュを再度行います。クライアント側のハッシュは、データベースに保存する最終結果ではありません。クライアント側のハッシュは、人間のクライアントが要求するためです。彼らは特定の理由を挙げていない。おそらく彼らは単にやり過ぎが好きだ。

69
jono

Stanford JS Crypto Library には、SHA-256の実装が含まれています。 JSの暗号化は他の実装プラットフォームほど十分に吟味されたものではありませんが、このプラットフォームは Dan Boneh によって少なくとも部分的に開発され、ある程度は後援されています-暗号化で確立され信頼された名前。これは、プロジェクトが実際に何をしているのかを知っている誰かがプロジェクトを監督していることを意味します。プロジェクトは NSF でもサポートされています。

しかし、指摘する価値はあります...
...クライアント側でパスワードをハッシュしてから送信する場合、ハッシュはパスワードであり、元のパスワード無関係になります。攻撃者はユーザーを偽装するためにハッシュを傍受するだけでよく、そのハッシュがサーバーに変更されずに保存されている場合、、サーバーはtrueプレーンテキストのパスワード(ハッシュ)

したがって、セキュリティはworseになりました。以前に信頼されていたスキームに 独自の改善を追加 を決定したためです。

88
tylerl

オン https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest 内部jsモジュールを使用するこのスニペットを見つけました:

async function sha256(message) {
    // encode as UTF-8
    const msgBuffer = new TextEncoder('utf-8').encode(message);                    

    // hash the message
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

    // convert ArrayBuffer to Array
    const hashArray = Array.from(new Uint8Array(hashBuffer));

    // convert bytes to hex string                  
    const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
    return hashHex;
}

crypto.subtlehttpsまたはlocalhostでのみ利用可能です。たとえば、python3 -m http.serverを使用したローカル開発の場合、/etc/hostsにこの行を追加する必要があります:0.0.0.0 localhost

再起動-localhost:8000を使用してcrypto.subtleを開くことができます。

22

Forge のSHA-256実装は高速で信頼性があります。

いくつかのSHA-256 JavaScript実装でテストを実行するには、 http://brillout.github.io/test-javascript-hash-implementations/ に移動します。

私のマシンでの結果は、forgeが最速の実装であり、受け入れられた回答で言及されているスタンフォードJavascript Crypto Library(sjcl)よりもかなり高速であることを示唆しています。

Forgeは256 KBの大きさですが、SHA-256関連のコードを抽出するとサイズが4.5 KBに減少します。 https://github.com/brillout/forge-sha256 を参照してください

14
brillout

いいえ、ブラウザのJavaScriptを使用してパスワードセキュリティを改善する方法はありません。 この記事 を読むことを強くお勧めします。あなたの場合、最大の問題は鶏卵の問題です。

Javascript暗号化の配信における「鶏卵の問題」とは何ですか?

パスワードを配信するためにネットワークを信頼しない場合、またはさらに悪いことに、ユーザーの秘密を保持しないためにサーバーを信頼しない場合、セキュリティコードを配信するためにそれらを信頼することはできません。暗号を導入する前にパスワードを盗聴したり日記を読んでいた同じ攻撃者は、単に暗号コードを乗っ取っただけです。

[...]

TLS/SSLを使用してJavascript暗号コードを配信できないのはなぜですか?

あなたはできる。思ったより難しいですが、SSLを使用してJavascript暗号化をブラウザに安全に送信します。問題は、SSLを使用して安全なチャネルを確立すると、Javascript暗号化が不要になることです。 「本物の」暗号があります。

これはこれにつながります:

Javascriptで暗号コードを実行する際の問題は、事実上、暗号が依存するすべての機能が、ホスティングページの作成に使用されるコンテンツの一部によってサイレントにオーバーライドされる可能性があることです。暗号セキュリティは、プロセスの早い段階で(偽の乱数を生成するか、アルゴリズムで使用される定数とパラメーターを改ざんすることにより)、または後で(鍵素材を攻撃者に戻す)、または---最も可能性の高いシナリオでは---暗号を完全にバイパスします。

Javascriptコードが実行環境を検証するための信頼できる方法はありません。 Javascript暗号コードは、「私は実際に乱数ジェネレーターを扱っているのか、それとも攻撃者によって提供されたものの一部を扱っているのか?」と尋ねることはできません。 そして、「私、著者、承認する方法を除いて、誰もこの暗号シークレットで何もすることを許可されていません」と断言することはできません。これら暗号を使用する他の環境でしばしば提供される2つのプロパティであり、Javascriptでは不可能です。

基本的に問題はこれです:

  • クライアントはサーバーを信頼していないため、追加のセキュリティコードを追加する必要があります。
  • そのセキュリティコードは、サーバー(サーバーが信頼していないサーバー)によって配信されます。

または、代わりに、

  • クライアントはSSLを信頼していないため、追加のセキュリティコードを使用することを望んでいます。
  • そのセキュリティコードはSSL経由で配信されます。

注:また、SHA-256は非常に簡単であるため、これには適していません 無塩の非反復パスワードを強引に強制する 。とにかくこれを行う場合は、 bcryptscrypt 、または PBKDF2 の実装を探してください。

10
Brendan Long

この実装は非常に使いやすいことがわかりました。また、寛大なBSDスタイルのライセンスがあります:

jsSHA: https://github.com/Caligatio/jsSHA

SHA-256ハッシュの16進文字列表現を取得する簡単な方法が必要でした。わずか3行で完了しました。

var sha256 = new jsSHA('SHA-256', 'TEXT');
sha256.update(some_string_variable_to_hash);
var hash = sha256.getHash("HEX");
8
cobbzilla

興味がある人のために、これはsjclを使用してSHA-256ハッシュを作成するためのコードです。

import sjcl from 'sjcl'

const myString = 'Hello'
const myBitArray = sjcl.hash.sha256.hash(myString)
const myHash = sjcl.codec.hex.fromBits(myBitArray)
6
Danny Sullivan

タイラーが言及したスタンフォード図書館に加えて。 jsrsasign が非常に便利であることがわかりました(Githubリポジトリはこちら: https://github.com/kjur/jsrsasign )。私はそれがどれほど正確に信頼できるかわかりませんが、SHA256、Base64、RSA、x509などのAPIを使用しました。実際、Stanfordライブラリも含まれています。

あなたがやりたいことがSHA256だけなら、 jsrsasign はやり過ぎかもしれません。しかし、関連する分野で他のニーズがある場合、それはぴったりだと思います。

0
Faraway