この記事に書いてあること
シェルコマンドでSHA256ハッシュをおこなう方法をメモしておきます。
hex形式(16進数)で出力
$ echo -n "abcde12345xyz" | sha256sum | awk '{ print $1 }' 5b4538f8719e2662a2be85365d53d6b583bf06d92dd98cc1d682ecb3b69e977e
Base64形式で出力
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | base64 W0U4+HGeJmKivoU2XVPWtYO/Btkt2YzB1oLss7ael34=
もしくはbasencコマンドを使ってBase64形式で出力
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | basenc --base64 W0U4+HGeJmKivoU2XVPWtYO/Btkt2YzB1oLss7ael34=
Base64URL形式で出力
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | base64 | sed s/\\+/-/g | sed s/\\//_/g | sed -E s/=+$// W0U4-HGeJmKivoU2XVPWtYO_Btkt2YzB1oLss7ael34
もしくはbasencコマンドを使ってBase64URL形式で出力
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | basenc --base64url | sed -E s/=+$// W0U4-HGeJmKivoU2XVPWtYO_Btkt2YzB1oLss7ael34
コマンドの詳細
$ echo -n "abcde12345xyz" | sha256sum | awk '{ print $1 }' 5b4538f8719e2662a2be85365d53d6b583bf06d92dd98cc1d682ecb3b69e977e
上のコマンドについて見ていきます。
echoコマンドの-n
オプションによって改行コードを出力しないようにしています。除外しないと改行コードまでSHA256ハッシュ化されてしまいます。
また、awkコマンドによって、sha256sumコマンドで出力される余計な文字列(-*
)を除外しています。
echoコマンドの-n
オプションとawkコマンドを使わないと以下のようになります。
改行コードまでハッシュ化しているので、値が変わってしまいました。
$ echo "abcde12345xyz" | sha256sum 33630eeb0ed053423d052d0f59bccb654bd1c1edc872124df9f85b66d0a1e525 *-
xxdコマンド
xxdコマンドはファイルまたは標準入力を16進数で出力するコマンドですが、-r
オプションで反対に16進数からファイルに変換できます。
-p
は-ps
と同じオプションだが、ポストスクリプト形式の16進ダンプ(プレーン16進ダンプ)で出力する、らしいです。
よくわからないけど必要だったのでつけています。
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | base64 W0U4+HGeJmKivoU2XVPWtYO/Btkt2YzB1oLss7ael34=
base64コマンド
ファイルまたは標準入力をBase64形式にエンコード、Base64形式からデコードするコマンド。
また、今回は不要ですが-d
オプション(--decode
)によってデコードをおこなうことができます。
$ echo -n "abcde12345xyz" | base64 YWJjZGUxMjM0NXh5eg==
$ echo -n "YWJjZGUxMjM0NXh5eg==" | base64 -d abcde12345xyz
basencコマンド
ファイルまたは標準入力をBase64形式またはBase64URL形式にエンコード、Base64形式またはBase64URL形式からデコードするコマンド。 入っていないディストリビューションもあるようなので、注意(手元のUbuntu 20.04.1には入っていませんでした)。
今回はエンコードしたいので、オプションで--base64
または--base64url
を指定しています。
注意点としては、basencコマンドのBase64URL形式は末尾のパディング=
を削除してくれないので、sedコマンドで削除しています。
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | basenc --base64 W0U4+HGeJmKivoU2XVPWtYO/Btkt2YzB1oLss7ael34=
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | basenc --base64url | sed -E s/=+$// W0U4-HGeJmKivoU2XVPWtYO_Btkt2YzB1oLss7ael34
basencコマンドが使えない場合には、sedコマンドを使ってBase64形式からBase64URL形式に変換することもできます。
$ echo -n "abcde12345xyz" | sha256sum | xxd -r -p | base64 | sed s/\\+/-/g | sed s/\\//_/g | sed -E s/=+$// W0U4-HGeJmKivoU2XVPWtYO_Btkt2YzB1oLss7ael34
basencコマンドでBase64URL形式をデコードするにはパディングをつける必要がある
前述のとおり、basencコマンドではBase64URL形式にパディングがつけられてしまいます。
$ echo -n "abcde12345xyz" | basenc --base64url YWJjZGUxMjM0NXh5eg==
パディングはsedコマンドで削除できます。
$ echo -n "abcde12345xyz" | basenc --base64url | sed -E s/=+$// YWJjZGUxMjM0NXh5eg
basencコマンドは-d
オプション(--decode
)によってデコードをおこなうことができますが、パディングを削除したBase64URL形式の文字列をデコードしようとするとエラーになります。
正しい値のあとにエラーメッセージが続くというバグのような怪しい動作になっています。
$ echo -n "YWJjZGUxMjM0NXh5eg" | basenc -d --base64url abcde12345xyzbasenc: invalid input
これを回避するにはパディングを補ってやる必要があります。 パディングは4の倍数になるようにつけられるので、以下のようにデコードしたい文字列の長さに合わせてパディングをつけてデコードをおこないます。
$ str="YWJjZGUxMjM0NXh5eg"; echo -n "${str}====" | fold -w 4 | sed '$ d'| basenc --base64url -d abcde12345xyz
変数strにデコードしたい文字列を入れます。 foldコマンドによって4文字ずつ改行をおこない、sedコマンドによって最後の行を削除することでパディングを適切な長さにしています。
basencコマンドが使えないとき、Base64URL形式からデコードするには一度Base64形式にしてからbase64コマンドでデコードします。
$ str="YWJjZGUxMjM0NXh5eg"; echo -n "${str}====" | sed s/-/\\+/g | sed s/_/\\//g | fold -w 4 | sed '$ d'| base64 -d abcde12345xyz
参考
- sha1コマンドからハッシュ値だけを取り出す方法 | クロジカ
- SHA-256ダイジェストをBase64で得る(hex形式をBase64に変換する) - Lambdaカクテル
- 【 xxd 】コマンド――ファイルを16進数でダンプする、ダンプから復元する:Linux基本コマンドTips(254) - @IT
- シェルスクリプトでBase64を使う方法のまとめ + POSIXコマンドのみを使った独自実装 #Linux - Qiita
- base64コマンド: decodeした時にエラーが出る原因と対処方法(パディングが必要) #ShinobiLayer - Qiita
- shell - How to encode and decode data in base64 and base64URL by using unix commands? - Stack Overflow