テキストを UTF-16 の Base64 にエンコードする方法
- 入力 · テキスト にテキストを入力するか貼り付けます。文字コード は UTF-16LE に設定済みです。
- 出力 · Base64 から Base64 をコピーします。入力 の数値は UTF-16 でのバイト数で、普通の英語のテキストなら文字数の 2 倍です。
- ビッグエンディアンの受け手向けには、文字コード を UTF-16BE に切り替えます。
- 入れ替え で結果をもう一度デコードして手早く確認できます。専用のデコーダーは Base64 を UTF-16 に です。
UTF-16LE と UTF-16BE
UTF-16 は各文字を 16 ビットのコードユニット 1 つまたは 2 つで保存します。リトルエンディアンは下位バイトを先に、ビッグエンディアンは上位バイトを先に書きます。Windows と .NET はリトルエンディアンを、Java の UTF-16 エンコーダーや多くのネットワーク形式はビッグエンディアンを使います。
| テキスト | UTF-16LE のバイト列 | UTF-16LE の Base64 | UTF-16BE の Base64 |
|---|---|---|---|
Hi | 48 00 69 00 | SABpAA== | AEgAaQ== |
Hello | 10 バイト | SABlAGwAbABvAA== | AEgAZQBsAGwAbw== |
€ | AC 20 | rCA= | IKw= |
👋 | 3D D8 4B DC | PdhL3A== | 2D3cSw== |
基本多言語面(BMP)の外にある文字は、絵文字を含めて、サロゲートペアと呼ばれる 2 つのコードユニットを使います。👋(U+1F44B)は D83D DC4B になり、これが最後の行の 4 バイトです。
ASCII の文字それぞれにゼロのバイトが組み合わされるので、英語のテキストの UTF-16 の Base64 には A があちこちに現れます。正体不明の文字列にこのパターンがあれば、UTF-16 としてデコードしてみる価値があります。
UTF-16 の Base64 が使われる場面
- PowerShell の
-EncodedCommand。powershell -EncodedCommand RwBlAHQALQBEAGEAdABlAA==はGet-Dateを実行します。こうしたコマンドが失敗するよくある原因は、スクリプトを UTF-8 でエンコードしたことです。PowerShell EncodedCommand ツール はコマンドのプレフィックスを付け、cmd.exeの長さ制限について警告し、ログで見つけたコマンドのデコードもできます。 - .NET のコード。 C# の
Encoding.Unicodeは UTF-16LE なので、Convert.ToBase64String(Encoding.Unicode.GetBytes(s))はこのページと同じ出力になります。 - Windows のデータ。 レジストリの文字列、SQL Server でバイナリにキャストした
NVARCHARカラム、多くの Windows API の文字列は UTF-16LE です。
バイトオーダーマーク(BOM)
このツールはバイトオーダーマークを書き込みません。PowerShell やほとんどの API が求めるのはこの形です。ライブラリによっては自動で BOM を付けます。
| 出力元 | 先頭のバイト | Hi の Base64 |
|---|---|---|
| このツール、UTF-16LE | 48 00 | SABpAA== |
Python の "Hi".encode("utf-16") | FF FE 48 00 | //5IAGkA |
Java の "Hi".getBytes(UTF_16) | FE FF 00 48 | /v8ASABp |
それらのどれかと Base64 を一致させる必要がある場合は、以下のようにコードでバイト順を明示してエンコードしてください。
コードで UTF-16 を Base64 に
import base64
base64.b64encode("Get-Date".encode("utf-16-le")).decode() # 'RwBlAHQALQBEAGEAdABlAA=='
base64.b64encode("Hi".encode("utf-16-be")).decode() # 'AEgAaQ=='
// Node.js has a little-endian codec only
Buffer.from("Get-Date", "utf16le").toString("base64"); // "RwBlAHQALQBEAGEAdABlAA=="
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('Get-Date'))
BOM が不要なら、Python では utf-16 ではなく utf-16-le を使ってください。ほかの例は Python と Node.js にあります。
よくある質問
PowerShell で UTF-16LE の Base64 が必要なのはなぜですか?
powershell -EncodedCommand は、スクリプトの UTF-16LE バイト列を Base64 にしたものを想定しています。Windows は内部で文字列をその形式で保持しているからです。UTF-8 の Base64 では違う文字にデコードされ、コマンドは失敗します。PowerShell EncodedCommand ツール ならコマンドライン全体を組み立てられます。
UTF-16LE と UTF-16BE の違いは何ですか?
各コードユニットの 2 バイトの並び順です。H はリトルエンディアンでは 48 00、ビッグエンディアンでは 00 48 なので、Hi は SABpAA== または AEgAaQ== になります。
出力の先頭にバイトオーダーマークは付きますか?
いいえ。エンコードされるのはテキスト自体のバイト列だけです。Python の "utf-16" コーデックや Java の UTF_16 文字セットは BOM を付けるので、それらの Base64 は //5 や /v8 で始まります。
UTF-16 の Base64 がこんなに長いのはなぜですか?
UTF-16 は 1 文字に最低 2 バイトを使うので、英語のテキストは Base64 で 3 分の 1 増える前に、まず 2 倍の大きさになります。Hello は UTF-8 なら Base64 で 8 文字、UTF-16 なら 16 文字です。