1

Python 用の次のバージョンのコードがあります。

import hashlib
msg = 'abc'
print msg
sha256_hash = hashlib.sha256()
sha256_hash.update(msg)
hash_digest = sha256_hash.digest()
print hash_digest

対応する Node js バージョン:

var crypto= require('crypto');
var msg = 'abc';
var shasum = crypto.createHash('sha256').update(msg);
var hashDigest = shasum.digest();
console.log(hashDigest);

ただし、バイナリ出力はどちらもわずかにずれています。

  • ノード : �x����AA@�]�"#�a��z���a��
  • Python:�x���AA@�]�"#�a��z���a��

2 つのライブラリ間でも 16 進表現は正しいです。ここで何か間違ったことをしていますか?

4

3 に答える 3

4

私には合っています。

Python 2.7.3:

Python 2.7.3 (デフォルト、2012 年 4 月 10 日 23:24:47) [MSC v.1500 64 ビット (AMD64)] (win32)
詳細については、「ヘルプ」、「著作権」、「クレジット」、または「ライセンス」と入力してください。
>>> ハッシュライブラリをインポート
>>> メッセージ = 'abc'
>>> sha256_hash = hashlib.sha256()
>>> sha256_hash.update(メッセージ)
>>> hash_digest = sha256_hash.hexdigest()
>>> hash_digest を出力
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
>>>

ノード v0.10.30:

> crypto.createHash('sha256').update('abc').digest('hex')
「ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad」

両方の 16 進文字列が一致します。

于 2014-11-18T06:18:35.817 に答える
3

TL;DR

ノードコードは、ハッシュの結果を utf8 として解析しようとして失敗しています。


違いは、言語がバイナリ データと文字列型をどのように扱うかです。最終的なバイナリ出力を考慮すると、両方の例で同じ値が出力されます。それでは、2 つの例の出力を 16 進数で示してみましょう。

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

Python の場合:

'\xbax\x16\xbf\x8f\x01\xcf\xeaAA@\xde]\xae"#\xb0\x03a\xa3\x96\x17z\x9c\xb4\x10\xffa\xf2\x00\x15\xad'

ノード内:

<SlowBuffer ba 78 16 bf 8f 01 cf ea 41 41 40 de 5d ae 22 23 b0 03 61 a3 96 17 7a 9c b4 10 ff 61 f2 00 15 ad>

この場合、注目すべき重要なことは、Python の結果が文字列として返されることです。Python では、文字列は文字 (0 ~ 255) 値の単なる配列です。ただし、Node の値は Buffer として格納され、実際には値の配列 (0 ~ 255) も表します。それがここで異なる鍵です。Node の文字列はシングルバイト文字の配列ではなく、UTF-16 コード単位の配列であるため、Node は文字列を返しません。Python は、 で指定された別の文字列クラスを使用して Unicode をサポートしますu''

次に、出力を印刷する例を比較して、読みやすくするために短縮します

print '\xbax\x16\xbf\x8f\x01\xcf\xeaAA'

console.log('' + 
    new Buffer([0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41]))

Python コードでは、このバイト配列を端末に書き込みます。ただし、2 つ目は非常に異なることを言い、このバイト配列を文字列に変換してから、その文字列を端末に書き込みます。ただし、バッファはバイナリ データであり、UTF-8 でエンコードされたデータではないため、データを文字列にデコードできず、結果が文字化けします。バイナリ値を端末で実際にデコードされた値として直接比較したい場合は、両方の言語で同等の指示を与える必要があります。

print '\xbax\x16\xbf\x8f\x01\xcf\xeaAA'

process.stdout.write(
    new Buffer([0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41]))

process.stdout.writeこの場合、文字列ではなくバイナリ値を端末に書き込む方法です。

ただし、ハッシュは既にバイナリ値の文字列表現であり、不適切にデコードされた Unicode 文字よりも読みやすいため、ハッシュを 16 進数として比較する必要があります。

于 2014-11-18T08:34:53.323 に答える