ハッシュの表現とテキストの再エンコードは異なります

SHA-256の結果は256ビット、32バイトです。RFC 4648のBase16は1バイトを16進数2桁で表すため64文字になります。同じ32バイトをパディング付き標準Base64で表すと44文字です。一方、64文字の16進数文字列をUTF-8テキストとしてエンコードすると入力は64バイトで、結果は88文字です。88文字の結果は生のハッシュではなく、ハッシュを表示したテキストのエンコードです。

生ハッシュ32バイトからBase64の44文字、HEXテキスト64バイトから88文字への比較
独自制作のバイト処理図。Aは生のハッシュバイト、Bは64文字のHEXテキストです。Base64の44・88はパディング込みの文字数です。

RFC 6234: SHA-256 digest size

RFC 4648 §4, §8: Base64 / Base16

ツールを使う前に入力を確認する

abcをSHA-256で計算して両経路をコードで再現しました。Moyoutilのハッシュツールは16進数テキストを出力します。これをBase64ツールに貼り付けるとテキストのUTF-8バイトがエンコードされ88文字になります。このBase64ツールはHEX入力を生ハッシュバイトとして解釈しません。以下の別のWeb Crypto例は生バイトとHEXテキストを区別し、両経路の長さを出力します。

const raw = new Uint8Array(await crypto.subtle.digest(
  'SHA-256', new TextEncoder().encode('abc')));
const hex = Array.from(raw,
  n => n.toString(16).padStart(2, '0')).join('');
const rawBase64 = btoa(String.fromCharCode(...raw));
const textBase64 = btoa(hex); // ASCII HEX text
console.log(raw.length, hex.length,
            rawBase64.length, textBase64.length);
// 32 64 44 88

受信側システムの文書で必要な表現を確認してください。Base64とBase64url、パディング、エンコード対象は別条件です。文字列の長さが合っても同じチェックサムと確認したことにはなりません。この記事は表現変換の説明であり、署名検証やファイルの安全性判定ではありません。

よくある質問

Base64への変換はハッシュの再計算ですか?

いいえ。生ハッシュバイトのエンコードは表示方法を変えます。HEXテキストのエンコードは入力データが異なります。元データのSHA-256再計算と区別してください。