2

メッセージ認証にHMACを使用するWebサービスを作成しています。ダイジェスト用の「データ」の準備で問題が発生し、PythonとNodeJSで同じ「データ」に対して異なるダイジェストを取得しています。

この問題はエンコーディングが原因であると確信していますが、これに最善の方法でアプローチする方法がわかりません。

Pythonコード:

import hmac
from hashlib import sha1

f = open('../test.txt')
raw = f.read()

raw = raw.strip()

hm = hmac.new('12345', raw, sha1)
res = hm.hexdigest()
print res

>> 5bff447a0fb82f3e7572d9fde362494f1ee2c25b

NodeJS(コーヒー)コード:

fs = require 'fs'
http = require 'http'
{argv} = require 'optimist'
crypto = require 'crypto'

# Load the file
file = fs.readFileSync argv.file, 'utf-8'
file = file.trim()

# Create the signature
hash = crypto.createHmac('sha1', '12345').update(file).digest('hex')
console.log(hash)

>> a698f82ea8ff3c4e9ffe0670be2707c104d933aa

編集:また、rawの長さはファイルより2文字長いですが、これらの2文字がどこから来ているのかわかりません。

4

2 に答える 2

4

これは、ファイルシステムから読み取るデータのエンコーディングの問題であり、使用するアルゴリズムには何もありません。

Python と JavaScript の両方で文字列データを扱うときは、データが格納されているエンコードに非常に注意する必要があります。 「生データ」で。データを読み取って署名するときは、エンコーディングを気にする必要はなく、言語でできるだけ「生」のままデータを使用するようにしてください。

注意すべき点:

  • ファイルシステムは「生の」バイトを保存し、ファイルの内容とエンコーディングについては何も知りません。さらに、一部のファイル (たとえば、jpeg など) では、「エンコード」の概念は役に立ちません。
  • 同じことが暗号アルゴリズムにも当てはまります。彼らは生のバイトを扱い、その「文字表現」については何も知りません。そのため、デジタル署名はあらゆる種類のバイナリ ドキュメントなどでうまく機能します。
  • trim()javascript またはstrip()python では文字列を操作し、それらの動作は基になるエンコーディングによって異なる場合があります (u's '.encode('utf-16').strip().decode('utf-16')たとえば、python で試してください)。可能であれば、トリミングの使用を避けて、作業方法とデータを混在させないようにします。
  • Python 2.x (そしておそらく Javascript も) には、文字列と生データの間の暗黙的な変換に関する一連の規則があります。

このコードでは、Python でバイナリ データを操作しますが、読み取るファイルのエンコーディングを定義するときに、JavaScript で文字列に変換します。どうやら、crypt モジュールには utf-8 から生の文字列への一種の暗黙的な変換があるようですが、それが何をするのかはわかりません。

hereで説明されているように、node.js で生の文字列を処理する最も適切な方法は、バッファーを使用することです。ファイルシステムからバッファを読み取ることはできますが、残念ながら、nodejs 暗号ライブラリはまだそれらをサポートしていません。ここで説明されているように:

Crypto モジュールは、統合された Stream API の概念が登場する前、およびバイナリ データを処理するための Buffer オブジェクトが登場する前に、Node に追加されました。

そのため、ストリーミング クラスには、他の Node クラスに見られる典型的なメソッドはありません。多くのメソッドは、デフォルトで、バッファではなくバイナリ エンコードされた文字列を受け入れて返します。

つまり、例を機能させるために、現在のアプローチは、呼び出しの 2 番目の引数として「binary」を渡してデータを読み取ることです。

file = fs.readFileSync argv.file, "binary"

また、先ほど言ったように、ファイルから読み取ったばかりのデータを削除することは避けたいと思います。

于 2012-10-23T19:02:58.667 に答える
1

試してみるいくつかのアイデア:

  • rawと同じ長さのチェックfile
  • fバイナリとして開く
  • import codecscodecs.openエンコーディングで使用する
  • striptrimPythonの文字列の最初と最後からすべての空白を削除します-最後からのみ削除すると思います。rstrip()したがって、同じ動作を得るために、明示的な文字セットを使用したい場合があります
于 2012-10-23T18:26:18.450 に答える