- 技術 💻
Base64エンコード各言語コード一覧|sha256ハッシュのコマンド早見表
Base64とは、任意のバイト列を「A〜Z・a〜z・0〜9・+・/」の64種類の文字だけで表す符号化(エンコード)方式です。SHA-256は、任意のデータから256ビット(16進数で64文字)の固定長の値を作るハッシュ関数です。 どちらも「バイト列を扱う」点が共通しており、文字コードや改行の違いで結果が変わるという同じつまずきがあります。
この記事では、同じ入力「タスク完了?」から、8つの言語・コマンドで同じBase64とSHA-256が出ることを実際に実行して確認した早見表をまとめました。オンライン変換ツールでは分からない「btoaが日本語でエラーになる理由」「echo だとハッシュが変わる理由」「CRLF・BOMでの不一致」も、実行結果つきで再現して直し方を示します。
Base64・sha256の早見表
確認環境:Python 3.11 / Node.js 22.22.2 / Chromium 141 / Go 1.27.1 / Java 21.0.10 / PHP 8.4.21 / Ruby 3.3.6 / .NET SDK 8.0.131 / PowerShell 7.6.6 / GNU coreutils 9.4 / OpenSSL 3.0.13。
入力「タスク完了?」(UTF-8で18バイト)の正解値
| 種類 | 値 |
|---|---|
| Base64(標準) | 44K/44K544Kv5a6M5LqGPw== |
| Base64URL(パディングなし) | 44K_44K544Kv5a6M5LqGPw |
| SHA-256(hex) | 1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115 |
| SHA-256(Base64) | GmymiwoqBbiKDGDbuR51yqflZKkZ4LXhcUXwzT6SoRU= |
言語別のエンコード・デコード・URLセーフ・SHA-256
| 言語 | エンコード | デコード | URLセーフ | SHA-256(hex) |
|---|---|---|---|---|
| JS(ブラウザ) | u8.toBase64() / btoa(バイナリ文字列) |
Uint8Array.fromBase64(s) / atob(s) |
toBase64({alphabet:"base64url"}) |
crypto.subtle.digest("SHA-256", u8) |
| Node.js | Buffer.from(s).toString("base64") |
Buffer.from(b,"base64") |
toString("base64url") |
createHash("sha256").update(s).digest("hex") |
| Python | base64.b64encode(b) |
base64.b64decode(s) |
base64.urlsafe_b64encode(b) |
hashlib.sha256(b).hexdigest() |
| Go | base64.StdEncoding.EncodeToString(b) |
StdEncoding.DecodeString(s) |
base64.RawURLEncoding |
sha256.Sum256(b) |
| Java | Base64.getEncoder().encodeToString(b) |
Base64.getDecoder().decode(s) |
getUrlEncoder().withoutPadding() |
MessageDigest.getInstance("SHA-256") |
| PHP | base64_encode($s) |
base64_decode($s, true) |
strtr で +/→-_ |
hash('sha256', $s) |
| Ruby | Base64.strict_encode64(s) |
Base64.strict_decode64(s) |
Base64.urlsafe_encode64(s, padding: false) |
Digest::SHA256.hexdigest(s) |
| C# | Convert.ToBase64String(b) |
Convert.FromBase64String(s) |
Replace('+','-') 等 |
SHA256.HashData(b) |
| シェル | base64 / openssl base64 -A |
base64 -d |
basenc --base64url |
sha256sum / shasum -a 256 |
| PowerShell | [Convert]::ToBase64String($b) |
[Convert]::FromBase64String($s) |
-replace で置換 |
Get-FileHash |
どの言語でも「文字列をUTF-8のバイト列にしてから」処理すれば、結果は一致します。 一致しないときは、ほぼ「文字コード」「改行」「BOM」「標準とURLセーフの取り違え」のどれかです。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Base64エンコード各言語コード一覧|sha256ハッシュのコマンド早見表」
Base64の仕組み:3バイトを4文字にする
Base64は、入力を3バイト(24ビット)ずつ区切り、6ビットずつ4つに分けて、それぞれを64種類の文字に置き換えます。 6ビットは0〜63の64通りなので、64文字で表せます。
flowchart LR
A["入力 3バイト<br>M a n"] --> B["24ビット<br>010011 010110 000101 101110"]
B --> C["6ビット×4<br>19 22 5 46"]
C --> D["4文字<br>T W F u"]
| 入力 | バイト数 | 出力 | 説明 |
|---|---|---|---|
Man |
3 | TWFu |
ちょうど3バイト→4文字 |
Ma |
2 | TWE= |
1バイト足りない→ = 1つ |
M |
1 | TQ== |
2バイト足りない→ = 2つ |
= はパディング(詰め物)で、「最後のブロックが何バイトだったか」を表します。 出力は必ず4の倍数の文字数になります。
サイズが約1.33倍になる理由
3バイトが4文字(4バイト)になるので、サイズは4/3 ≒ 1.333倍です。短いデータではパディング分だけ比率が大きくなります。Python で確かめた結果です。
import base64
for n in [1, 2, 3, 4, 100, 1000, 1048576]:
e = base64.b64encode(b"a" * n)
print(n, len(e), round(len(e) / n, 3))
1 4 4.0
2 4 2.0
3 4 1.333
4 8 2.0
100 136 1.36
1000 1336 1.336
1048576 1398104 1.333
出力の長さは「ceil(入力バイト数 ÷ 3) × 4」で計算できます。1MBの画像をBase64にしてJSONに埋め込むと約1.33MBになるので、大きなファイルはマルチパート送信やURL参照のほうが軽くなります。さらに、メール(MIME)形式では76文字ごとに改行が入るため、その分も増えます。
標準とURLセーフの違い
| 種類 | 62・63番目の文字 | パディング | 使われる場所 |
|---|---|---|---|
| Base64(標準、RFC 4648 §4) | + / |
あり | メール添付、data URL、一般的なAPI |
| Base64URL(RFC 4648 §5) | - _ |
省略が多い | JWT、URLのクエリ、ファイル名 |
+ / = はURLの中で特別な意味を持つため、URLやファイル名に入れるならBase64URLを使います。
言語別コード(コピペ用・実行結果つき)
すべて入力は「タスク完了?」、ファイルはUTF-8(BOMなし)で保存しています。
JavaScript(ブラウザ):btoaの日本語エラーと直し方
btoa() は「1文字=1バイト(Latin1)」の文字列しか受け付けないため、日本語をそのまま渡すとエラーになります。 Chromium 141 で実行したエラー文です。
InvalidCharacterError: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
直し方は2つです。 新しいブラウザなら Uint8Array.prototype.toBase64()、広い環境で動かすなら TextEncoder でUTF-8のバイト列にしてから btoa() に渡します。
// 方法1:Uint8Array.toBase64 / fromBase64(Baseline 2025)
const u8 = new TextEncoder().encode("タスク完了?");
console.log(u8.toBase64()); // 標準
console.log(u8.toBase64({ alphabet: "base64url", omitPadding: true })); // URLセーフ
const back = Uint8Array.fromBase64("44K_44K544Kv5a6M5LqGPw", { alphabet: "base64url" });
console.log(new TextDecoder().decode(back));
44K/44K544Kv5a6M5LqGPw==
44K_44K544Kv5a6M5LqGPw
タスク完了?
// 方法2:TextEncoder + btoa(対応ブラウザが広い)
const text = "タスク完了?";
const bytes = new TextEncoder().encode(text);
const bin = Array.from(bytes, (b) => String.fromCharCode(b)).join("");
const std = btoa(bin);
const url = std.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
console.log(std, url);
// デコード
const decoded = Uint8Array.from(atob(std), (c) => c.charCodeAt(0));
console.log(new TextDecoder().decode(decoded));
// SHA-256(Web Crypto API。HTTPS か localhost のページで使う)
const buf = await crypto.subtle.digest("SHA-256", bytes);
const hex = Array.from(new Uint8Array(buf), (b) => b.toString(16).padStart(2, "0")).join("");
console.log(hex);
44K/44K544Kv5a6M5LqGPw== 44K_44K544Kv5a6M5LqGPw
タスク完了?
1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115
| API | 対応状況(2026年10月時点で確認) |
|---|---|
btoa / atob |
すべての主要ブラウザ・Node.js 16以降 |
Uint8Array.toBase64 / fromBase64 / toHex |
MDNで Baseline 2025(2025年9月〜)。Chromium 141で動作を確認。Node.js 22.22.2 では undefined でした |
crypto.subtle |
安全なコンテキスト(HTTPS・localhost)でのみ利用可。about:blank で試すと undefined でした |
方法2は Node.js 22.22.2 のグローバルAPIで実行して確認しました。
Node.js(Buffer・crypto)
// b64.mjs 実行: node b64.mjs
import { createHash } from "node:crypto";
const text = "タスク完了?";
const buf = Buffer.from(text, "utf8");
console.log("std :", buf.toString("base64"));
console.log("url :", buf.toString("base64url"));
console.log("dec :", Buffer.from("44K/44K544Kv5a6M5LqGPw==", "base64").toString("utf8"));
console.log("dec2:", Buffer.from("44K_44K544Kv5a6M5LqGPw", "base64url").toString("utf8"));
const d = createHash("sha256").update(text, "utf8").digest();
console.log("hex :", d.toString("hex"));
console.log("b64 :", d.toString("base64"));
std : 44K/44K544Kv5a6M5LqGPw==
url : 44K_44K544Kv5a6M5LqGPw
dec : タスク完了?
dec2: タスク完了?
hex : 1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115
b64 : GmymiwoqBbiKDGDbuR51yqflZKkZ4LXhcUXwzT6SoRU=
Node.jsの "base64url" はパディングなしで出力します。
Python
# b64.py 実行: python3 b64.py
import base64, hashlib
text = "タスク完了?"
data = text.encode("utf-8")
std = base64.b64encode(data).decode("ascii")
url = base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")
print("std :", std)
print("url :", url)
print("dec :", base64.b64decode(std).decode("utf-8"))
# URLセーフ版は = を戻してからデコード
print("dec2:", base64.urlsafe_b64decode(url + "=" * (-len(url) % 4)).decode("utf-8"))
digest = hashlib.sha256(data)
print("hex :", digest.hexdigest())
print("b64 :", base64.b64encode(digest.digest()).decode("ascii"))
std : 44K/44K544Kv5a6M5LqGPw==
url : 44K_44K544Kv5a6M5LqGPw
dec : タスク完了?
dec2: タスク完了?
hex : 1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115
b64 : GmymiwoqBbiKDGDbuR51yqflZKkZ4LXhcUXwzT6SoRU=
ファイルのハッシュは hashlib.file_digest(f, "sha256")(Python 3.11以降)で、大きなファイルも少しずつ読み込んで計算できます。
Go(標準ライブラリのみ)
// main.go 実行: go run main.go
package main
import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
)
func main() {
data := []byte("タスク完了?")
std := base64.StdEncoding.EncodeToString(data)
url := base64.RawURLEncoding.EncodeToString(data) // Raw = パディングなし
fmt.Println("std :", std)
fmt.Println("url :", url)
dec, err := base64.StdEncoding.DecodeString(std)
if err != nil {
panic(err)
}
fmt.Println("dec :", string(dec))
sum := sha256.Sum256(data)
fmt.Println("hex :", hex.EncodeToString(sum[:]))
fmt.Println("b64 :", base64.StdEncoding.EncodeToString(sum[:]))
}
出力は Node.js・Python と同じ5行(std / url / dec / hex / b64)になることを確認しました。Goは StdEncoding・URLEncoding(パディングあり)・RawStdEncoding・RawURLEncoding(なし)の4種類から選びます。
Java(Java 21、単一ファイル実行)
// B64.java 実行: java -Dstdout.encoding=UTF-8 B64.java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.HexFormat;
public class B64 {
public static void main(String[] args) throws Exception {
byte[] data = "タスク完了?".getBytes(StandardCharsets.UTF_8);
String std = Base64.getEncoder().encodeToString(data);
String url = Base64.getUrlEncoder().withoutPadding().encodeToString(data);
System.out.println("std : " + std);
System.out.println("url : " + url);
System.out.println("dec : " + new String(Base64.getDecoder().decode(std), StandardCharsets.UTF_8));
byte[] sum = MessageDigest.getInstance("SHA-256").digest(data);
System.out.println("hex : " + HexFormat.of().formatHex(sum)); // Java 17+
System.out.println("b64 : " + Base64.getEncoder().encodeToString(sum));
}
}
つまずきポイント: ロケール未設定(LANG= が空)の端末で -Dstdout.encoding=UTF-8 を付けずに実行すると、エンコード結果やハッシュは正しいのに、dec : ?????? と表示だけが文字化けしました。値の問題ではなく標準出力の文字コードの問題です。getBytes() には必ず StandardCharsets.UTF_8 を渡します。
PHP(8.4)
<?php
// b64.php 実行: php b64.php
$data = "タスク完了?";
$std = base64_encode($data);
$url = rtrim(strtr($std, '+/', '-_'), '=');
echo "std : $std\n";
echo "url : $url\n";
echo "dec : " . base64_decode($std, true) . "\n"; // true = 不正な文字があれば false を返す
echo "hex : " . hash('sha256', $data) . "\n";
echo "b64 : " . base64_encode(hash('sha256', $data, true)) . "\n"; // true = 生バイト
出力は他の言語と同じ値でした。hash() の第3引数 true で生のバイト列が返り、それをBase64にするのがポイントです(hex文字列をBase64にすると別の値になります)。
Ruby(3.3)
# b64.rb 実行: ruby b64.rb
require "base64" # Ruby 3.4 以降は bundled gem(Bundler 利用時は Gemfile に追加)
require "digest"
data = "タスク完了?"
std = Base64.strict_encode64(data)
url = Base64.urlsafe_encode64(data, padding: false)
puts "std : #{std}"
puts "url : #{url}"
puts "dec : #{Base64.strict_decode64(std).force_encoding('UTF-8')}"
puts "enc64: #{Base64.encode64(data).inspect}"
puts "hex : #{Digest::SHA256.hexdigest(data)}"
puts "b64 : #{Digest::SHA256.base64digest(data)}"
std : 44K/44K544Kv5a6M5LqGPw==
url : 44K_44K544Kv5a6M5LqGPw
dec : タスク完了?
enc64: "44K/44K544Kv5a6M5LqGPw==\n"
hex : 1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115
b64 : GmymiwoqBbiKDGDbuR51yqflZKkZ4LXhcUXwzT6SoRU=
Base64.encode64 は60文字ごとと末尾に改行が入ります。 APIやJSONに入れるなら strict_encode64 を使います。
C#(.NET 8)
// Program.cs(dotnet new console で作成) 実行: dotnet run
using System.Security.Cryptography;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
byte[] data = Encoding.UTF8.GetBytes("タスク完了?");
string std = Convert.ToBase64String(data);
string url = std.TrimEnd('=').Replace('+', '-').Replace('/', '_');
Console.WriteLine($"std : {std}");
Console.WriteLine($"url : {url}");
Console.WriteLine($"dec : {Encoding.UTF8.GetString(Convert.FromBase64String(std))}");
byte[] sum = SHA256.HashData(data);
Console.WriteLine($"hex : {Convert.ToHexString(sum).ToLowerInvariant()}");
Console.WriteLine($"b64 : {Convert.ToBase64String(sum)}");
.NET SDK 8.0.131 で他の言語と同じ値を確認しました。Convert.ToHexString は大文字で返すので、小文字のhexと比べるときは ToLowerInvariant() を付けます。.NET 9以降は System.Buffers.Text.Base64Url クラスでURLセーフ版を直接扱えます(公式ドキュメントで確認、本記事では未実行)。
コマンドでBase64・sha256を求める
Linux・macOS
# Base64(GNU coreutils 9.4)
printf '%s' 'タスク完了?' | base64 # 44K/44K544Kv5a6M5LqGPw==
printf '%s' 'タスク完了?' | base64 | tr '+/' '-_' | tr -d '=' # 44K_44K544Kv5a6M5LqGPw
printf '%s' 'タスク完了?' | basenc --base64url # 44K_44K544Kv5a6M5LqGPw==
printf '%s' '44K/44K544Kv5a6M5LqGPw==' | base64 -d # タスク完了?
printf '%s' 'タスク完了?' | openssl base64 -A # 44K/44K544Kv5a6M5LqGPw==
# SHA-256
printf '%s' 'タスク完了?' | sha256sum # 1a6ca68b...3e92a115 -
printf '%s' 'タスク完了?' | shasum -a 256 # 1a6ca68b...3e92a115 -
printf '%s' 'タスク完了?' | openssl dgst -sha256 # SHA2-256(stdin)= 1a6ca68b...
printf '%s' 'タスク完了?' | openssl dgst -sha256 -binary | base64 # GmymiwoqBbiKDGDbuR51yqflZKkZ4LXhcUXwzT6SoRU=
# ファイルの検証
sha256sum lf.txt > SHA256SUMS
sha256sum -c SHA256SUMS # lf.txt: OK
| コマンド | 押さえどころ |
|---|---|
base64 |
GNU版は76文字ごとに改行。1行で欲しいときは base64 -w 0(macOS版は改行しない、デコードは -d または -D) |
openssl base64 |
64文字ごとに改行。-A で1行 |
sha256sum |
Linux(coreutils)。-c でチェックサムファイルを検証 |
shasum -a 256 |
macOS標準(Perl製)。Linuxにもあることが多い |
openssl dgst -sha256 |
どの環境でもほぼ使える。-binary で生バイト |
GNU版 base64 で100バイトをエンコードすると、76文字+改行+残り60文字の2行に分かれ、-w 0 では136文字1行になることを確認しました。macOS版の挙動は公式のmanページの記載に基づいています(本記事では未実行)。
Windows(PowerShell・certutil)
# PowerShell 7.6.6 で実行
$text = "タスク完了?"
$bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
# Base64
$std = [Convert]::ToBase64String($bytes)
"std : $std"
"dec : " + [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($std))
# 文字列の SHA-256(Get-FileHash に -InputStream で渡す)
$stream = [System.IO.MemoryStream]::new($bytes)
(Get-FileHash -InputStream $stream -Algorithm SHA256).Hash
# ファイルの SHA-256(小文字で比べたいとき)
(Get-FileHash .\lf.txt -Algorithm SHA256).Hash.ToLower()
std : 44K/44K544Kv5a6M5LqGPw==
dec : タスク完了?
1A6CA68B0A2A05B88A0C60DBB91E75CAA7E564A919E0B5E17145F0CD3E92A115
5e974a5fe99c3a52053d8b30be6ba912b332db596e9e7ae58a148918795585e8
Get-FileHash は大文字のhexを返します。 値は同じなので、比較するときは大文字・小文字をそろえます(PowerShellの -eq は大文字・小文字を区別しません)。
コマンドプロンプトでは次のコマンドが使えます(Windows固有のため本記事では未実行。Microsoft公式ドキュメントの書式です)。
certutil -hashfile lf.txt SHA256
certutil -encode input.bin output.b64
certutil -decode output.b64 input.bin
certutil -encode は出力ファイルの先頭と末尾に -----BEGIN CERTIFICATE----- 形式の行を付けるため、純粋なBase64だけが欲しいときはPowerShellの [Convert] を使うほうが扱いやすくなります。
hexとBase64の違い:同じハッシュの別表記
SHA-256の結果は32バイトのバイナリで、hexとBase64はその「見せ方」の違いです。
| 表記 | 長さ | 例(「タスク完了?」) | よく使う場所 |
|---|---|---|---|
| hex(16進数) | 64文字 | 1a6ca68b0a2a…3e92a115 |
sha256sum、ダウンロードページのチェックサム、Gitなど |
| Base64 | 44文字(=含む) |
GmymiwoqBbiKDGDbuR51yqflZKkZ4LXhcUXwzT6SoRU= |
Subresource Integrity(sha256-…)、CSPのハッシュ、HTTPの Digest 系ヘッダー |
よくある取り違え:hex文字列(64文字のテキスト)をさらにBase64にすると、別の値(88文字)になります。 Base64にするのは「生のダイジェスト(32バイト)」です。シェルなら openssl dgst -sha256 -binary | base64、PHPなら hash(..., true)、Pythonなら .digest() を使います。
ハッシュが一致しない原因と直し方(改行・CRLF・BOM)
echoは末尾に改行を足す
echo 'タスク完了?' | sha256sum
echo -n 'タスク完了?' | sha256sum
printf '%s' 'タスク完了?' | sha256sum
5e974a5fe99c3a52053d8b30be6ba912b332db596e9e7ae58a148918795585e8 -
1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115 -
1a6ca68b0a2a05b88a0c60dbb91e75caa7e564a919e0b5e17145f0cd3e92a115 -
echo は末尾に改行(\n)を付けるため、1バイト多い入力のハッシュになります。 Base64でも同様で、echo だと 44K/44K544Kv5a6M5LqGPwo=(末尾の Pwo= が改行入り)になりました。echo -n はシェルによって挙動が違うことがあるので、スクリプトでは printf '%s' を使うのが確実です。
改行コード(CRLF)とBOMで値が変わる
見た目が同じ3つのファイルを作ってハッシュを比べました。
printf 'タスク完了?\n' > lf.txt
printf 'タスク完了?\r\n' > crlf.txt
printf '\xef\xbb\xbfタスク完了?\n' > bom.txt
sha256sum lf.txt crlf.txt bom.txt
file lf.txt crlf.txt bom.txt
5e974a5fe99c3a52053d8b30be6ba912b332db596e9e7ae58a148918795585e8 lf.txt
7e50e446ca4a9cee41e99c20df1f40de70ea59700f8413acfbfde49b54e2046d crlf.txt
3197a739d67a5bf2b1f5da4dfebde5c92b6e5d5f531bf4e2abfd9ccf549abb00 bom.txt
lf.txt: Unicode text, UTF-8 text
crlf.txt: Unicode text, UTF-8 text, with CRLF line terminators
bom.txt: Unicode text, UTF-8 (with BOM) text
直し方:比べる前にCRLFやBOMを取り除くと、LFのファイルと同じ値に戻りました。
tr -d '\r' < crlf.txt | sha256sum # 5e974a5f...795585e8 -
sed '1s/^\xEF\xBB\xBF//' bom.txt | sha256sum # 5e974a5f...795585e8 -
| 原因 | 見分け方 | 直し方 |
|---|---|---|
echo の改行 |
Base64の末尾が o= や Cg== |
printf '%s' を使う |
| CRLF | file で with CRLF line terminators |
tr -d '\r'、.gitattributes で eol=lf |
| BOM | 先頭3バイトが ef bb bf |
エディタで「UTF-8(BOMなし)」で保存 |
| 文字コード違い | Shift_JISとUTF-8で同じ文字でもバイト列が違う | すべてUTF-8にそろえる |
デコード時のエラー文
import base64
base64.b64decode("44K/44K544Kv5a6M5LqGPw") # パディングなし
base64.b64decode("44K_44K544Kv5a6M5LqGPw==", validate=True) # URLセーフ文字
binascii.Error: Incorrect padding
binascii.Error: Only base64 data is allowed
validate=False(既定)でURLセーフ文字を渡すと、_ が読み飛ばされて number of data characters (21) cannot be 1 more than a multiple of 4 というエラーになりました。GNU base64 -d にURLセーフ文字を渡すと base64: invalid input で終了コード1です。一方 Node.js の Buffer.from(s, "base64") は両方の文字セットを受け付け、エラーになりません。言語によって寛容さが違うので、URLセーフかどうかを送る側と受ける側で決めておくのが確実です。
Base64は暗号化ではない・ハッシュ単体はパスワード保存に向かない
| 処理 | 元に戻せるか | 鍵 | 主な用途 |
|---|---|---|---|
| Base64(エンコード) | 誰でも戻せる | なし | テキストしか通らない経路でバイナリを運ぶ |
| 暗号化(AES など) | 鍵があれば戻せる | あり | 内容を秘密にする |
| ハッシュ(SHA-256) | 戻せない(一方向) | なし | 改ざん検知、同一性の確認 |
- Base64は誰でもデコードできる「表記の変換」です。秘密にしたい値は暗号化し、通信はHTTPSで保護します。
- SHA-256は高速に計算できるよう設計されているため、パスワード保存には bcrypt・Argon2 などの専用関数を使います。 詳しくは別記事「パスワードのハッシュ化|bcrypt・Argon2の推奨値と実測・移行コード」で解説しています。
- 鍵つきで改ざんを検知したいときは、SHA-256単体ではなく HMAC-SHA256 を使います(例:Pythonの
hmac.new(key, msg, hashlib.sha256))。
よくある質問
Q. Base64の末尾の「=」は削ってもよいですか?
A. 受け取る側がパディングなしに対応していれば削れます。 JWTなどBase64URLでは省略が一般的です。Pythonの b64decode のように = が必要な実装では、"=" * (-len(s) % 4) を足してからデコードします。
Q. 同じ文字列なのに、言語によってsha256が違います。
A. ほとんどが入力のバイト列の違いです。 末尾の改行、CRLF、BOM、文字コード(UTF-8かどうか)を確認してください。本記事の8環境では、UTF-8・改行なしでそろえるとすべて 1a6ca68b…3e92a115 になりました。
Q. JavaScriptで日本語をBase64にするとエラーになります。
A. btoa() はLatin1の範囲の文字しか扱えません。new TextEncoder().encode(文字列) でUTF-8のバイト列にしてから、toBase64() か btoa() に渡します。
まとめ
- Base64は3バイトを4文字にする符号化で、サイズは約1.33倍。
=は最後のブロックの不足分を表します。 - URLやJWTにはBase64URL(
-_、パディング省略)を使い、標準版と取り違えないようにします。 - どの言語でも「UTF-8のバイト列」にそろえれば同じ結果になることを8環境で確認しました。
- ブラウザの
btoaは日本語を直接扱えないので、TextEncoderを通すかUint8Array.toBase64()を使います。 - ハッシュが合わないときは、echoの改行・CRLF・BOMを疑い、
printf '%s'やtr -d '\r'で直します。 - hexとBase64は同じダイジェストの別表記。Base64にするのは生の32バイトです。
- Base64は暗号化ではなく、パスワード保存にはbcrypt・Argon2を使います。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Base64エンコード各言語コード一覧|sha256ハッシュのコマンド早見表」
株式会社RJCでは、言語をまたいでデータを正しく扱う知識を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。