node.jsで文字列のsha1ハッシュを取得するにはどうすればよいですか?


108

node.jsで記述されたWebSocketサーバーを作成しようとしています

サーバーを機能させるには、文字列のSHA1ハッシュを取得する必要があります。

私がしなければならないことは、ドキュメントのセクション5.2.2の35ページで説明されています

注:例として、"Sec-WebSocket-Key" クライアントのハンドシェイクのヘッダーの値がの"dGhlIHNhbXBsZSBub25jZQ=="場合、サーバーは"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"文字列を追加して文字列を形成します"dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"。サーバーはこの文字列のSHA-1ハッシュを取得し、値0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xeaを提供します。次に、この値はbase64でエンコードさ"s3pPLMBiTxaQ9kYGzzhZRbK+xOo="れて、"Sec-WebSocket-Accept"ヘッダーで返される値になります。


9
独自にロールするのではなく、優れたsocket.ioライブラリを使用することを強くお勧めします。これは広範囲にわたってテストされ、パッチが適用されただけでなく、さまざまな方法でほとんどのブラウザー(WebSocket APIなしのブラウザー)をサポートします。
Alex Turpin

1
将来の訪問者のための良いリファレンス:stackoverflow.com/questions/9407892/...
Damodaran

回答:



32

必須:SHA1が壊れています。45,000米ドルでSHA1の衝突を計算できます。あなたは使うべきですsha256

var getSHA256ofJSON = function(input){
    return crypto.createHash('sha256').update(JSON.stringify(input)).digest('hex')
}

質問に答えてSHA1ハッシュを作成するには:

const INSECURE_ALGORITHM = 'sha1'
var getInsecureSHA1ofJSON = function(input){
    return crypto.createHash(INSECURE_ALGORITHM).update(JSON.stringify(input)).digest('hex')
}

次に:

getSHA256ofJSON('whatever')

または

getSHA256ofJSON(['whatever'])

または

getSHA256ofJSON({'this':'too'})

公式ノードのドキュメント crypto.createHash()


7
良いアイデア。ただし、デフォルトでObject.toString()返さ[object Object]れるため、すべてのオブジェクト(配列とnullを除く)は同じsha1sum値を持つことに注意してください。だから、sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1})など
maerics

sha1(JSON.stringify( "some string"))=> sha1( "\" some string \ "")これは絶対に予期されておらず、クロスプラットフォームではありません。時々、より良いものは善の敵です。
Pierre

3
指定された文字列のsha1は、どのプラットフォームでも同じであると想定されています。JSON.stringifyを使用した実装は元の文字列を変更し、sha1sum( "abcd")はf805c8fb0d5c466362ce9f0dc798bd5b3b32d512を提供します。誰もが81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre

2
@Pierreそれは素晴らしい点です。sha1sumあなたが言ったことを考えると、関数の名前付けは不正確だと思います-これは明らかに通常のsha1がすることよりも多くのことをします。答えで関数の名前を変更しました。
mikemaccana 2016年



7

問題を回避するためのヒント(不正なハッシュ):

NodeJSが文字列のUTF-8表現をハッシュしていることを経験しました。他の言語(Python、PHP、PERLなど)は、バイト文字列をハッシュしています。

バイナリ引数を追加して、バイト文字列を使用できます。

const crypto = require("crypto");

function sha1(data) {
    return crypto.createHash("sha1").update(data, "binary").digest("hex");
}

sha1("Your text ;)");

「\ xac」、「\ xd1」、「\ xb9」、「\ xe2」、「\ xbb」、「\ x93」などで試すことができます...

その他の言語(Python、PHPなど):

sha1("\xac") //39527c59247a39d18ad48b9947ea738396a3bc47

Nodejs:

sha1 = crypto.createHash("sha1").update("\xac", "binary").digest("hex") //39527c59247a39d18ad48b9947ea738396a3bc47
//without:
sha1 = crypto.createHash("sha1").update("\xac").digest("hex") //f50eb35d94f1d75480496e54f4b4a472a9148752


1
^^ @JossefHarushによる非常に重要な発言!特にハッシュする前にテキストをlatin1としてエンコードする必要がない場合(たとえば、PHPとの互換性のために)、テキストにlatin1の範囲外のUnicode記号が含まれている可能性がある場合(たとえば、絵文字!)、使用しないでくださいbinarybinaryまたはlatin1エンコーディングで使用すると、情報失われ、衝突の可能性が高くなります。例えばこれら2と上記のスニペットを試してみてください
CBR

すべてのハッシュはバイナリデータに対して行われます。あなたが経験している問題は、あなたが言及する他の言語がUTF-8を使用しておらず、その逆ではないということです。これは、Latin1以外の何かをハッシュしようとすると非常に明らかになります。特にPHPの場合、ハードコードされたテキストのテキストファイル自体など、エンコーディングはソースによって完全に決定されます。Perlは、UTF-8を使用するためにかなりの手間が必要になる場合があります。
Ryan Hanekamp

3

以下を使用できます。

  const sha1 = require('sha1');
  const crypt = sha1('Text');
  console.log(crypt);

インストール:

  sudo npm install -g sha1
  npm install sha1 --save

こんにちはuser944550さん、ようこそ。さらに情報を追加することを検討してください。
Tiago Martins Peres李大仁
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.