0

デバイス識別子をハッシュする方法を探し回ったところ、次のコードに出くわしました。

私はそれが何をしているのか本当に理解していません。

  1. デバイス ID を urlEncode する必要があるのはなぜですか?
  2. バイトをハッシュする必要があるのはなぜですか? String でそれを行うことはできませんか?
  3. なぜ BigInteger に変換する必要があるのですか?
  4. ハッシュされた id を持つ文字列を取得するためにビットをシフトする必要があるのはなぜですか?

行ごとに何が起こっているのか説明できる人はいますか? これが、ブログやフォーラムでも流布されているこのスニペットを他の人が理解するのに役立つことを願っています。

String hashedId = "";

String deviceId = urlEncode(Secure.getString(context.getContentResolver(), Secure.ANDROID_ID));

try {
    MessageDigest digest = MessageDigest.getInstance("SHA-1");

    byte bytes[] = digest.digest(deviceId.getBytes());

    BigInteger b = new BigInteger(1, bytes);
    hashedId = String.format("%0" + (bytes.length << 1) + "x", b);

} catch (NoSuchAlgorithmException e) {
    //ignored
}

return hashedId;
4

4 に答える 4

3

デバイス ID を urlEncode する必要があるのはなぜですか?

バイトをハッシュする必要があるのはなぜですか? String でそれを行うことはできませんか?

SHA-1 を含むほとんどのハッシュ アルゴリズムは、バイナリ データを入力 (バイト) として処理します。文字列自体には、特定のバイナリ表現はありません。エンコーディングによって変わります。

彼らが提供するコード行は、少し壊れやすいデフォルトのエンコーディングを使用しています。私は次のようなものを見たいです

byte bytes[] = digest.digest(deviceId.getBytes(Charset.forName("UTF-8")));

なぜ BigInteger に変換する必要があるのですか?

これは、16 進表現への変換を支援するために便宜上使用されています。

ハッシュされた id を持つ文字列を取得するためにビットをシフトする必要があるのはなぜですか?

使用されているフォーマット文字列は です%0Nx。これにより、文字列はゼロで埋められNます。16 進数で 1 バイトを表すには 2 文字かかるため、Nbytes*2であり、結果はbytes << 1.

Android用のGuavaを含めてHashingビルダーを使用しない理由がよくわかりません:

String hash = Hashing.sha1().hashString(deviceId, Charsets.UTF_8).toString();

これは 1 行であり、チェック例外をスローしません。

于 2012-11-08T17:34:38.210 に答える
1

ビットシフトについて: 左に 1 シフトすることは、2 を乗算することと同じです。文字列の各バイトは 2 つの 16 進文字で表されるため、結果の文字列はハッシュのバイト数の 2 倍の長さになります。

これにより、 のようなフォーマット文字列が作成%032xされ、整数値がゼロで埋められた 32 文字の文字列として出力されます。

于 2012-11-08T17:27:19.323 に答える
1

オブジェクトではなく文字データをハッシュするように、文字列ではなくバイトをハッシュする必要があります。Stringオブジェクトは、特定の文字シーケンスに対して予測できない内部状態を持つ可能性があります。

これは BigInteger に変換されるため、1 バイトあたり 2 桁の 16 進数で一貫してフォーマットできます。(これが、左シフトで長さが 2 倍になる理由です。)

基本的に、すべての質問に対する答えは次のとおりです。異なるプラットフォームでも、信頼性が高く再現性のある結果が得られるようにするためです

于 2012-11-08T17:31:44.310 に答える