🙆

Base64で少しつまずいた話(padding)

2024/06/23に公開

始めに

ちょっと自分でWebauthnを実装してみようかな…と考えて読んでた時にBase-Nエンコードについて少し学びがあったので書いてみます。
今回はお恥ずかしながらBase64のパディングについて知らなかったので、その辺りを中心に書いていきます。
不備等あればお気軽に指摘お願いしますmm

本題

Base64とは

Base64はバイナリからテキストへの変換を行うエンコーディング方式の一つです。
このような非文字データをテキストデータ(ASCII文字列)に変換するとデータの格納や転送が保証できます。
この由来はMIMEで使われるようになったのが元となっているようです。
詳細はRFC4648を参照してください。
https://datatracker.ietf.org/doc/html/rfc4648
https://developer.mozilla.org/ja/docs/Glossary/Base64

変換のされ方

Base64は6ビットのブロックに分割してエンコードします。
’000000’なら’A’に,’111111’なら’/’に変換されるという感じです。
また,エンコードされた文字列は4文字ずつをひとまとまりとして扱うようです。
https://datatracker.ietf.org/doc/html/rfc4648#section-4

またバイナリデータ末尾が中途半端なときは拡張されるようです。
(Ex. ’000001 01’ ー> '000001 010000' -> 'BQ==')

数学的な話で少し面白い記事がありました。

パディングについて

Base64とBase32には普通パディングを使用します。
基本的にはエンコードされたテキストにはアルファベット以外の文字は無視されます。
末尾につく”=”はパディングとして使われますが,無視されます。
この’無視される’というのがポイントで,バイナリに変換すると空になってくれます。

パディングをつけないという選択肢

ここでつまづきました。
webauthnだとrawIdやattestationObjectを転送する際にBase64エンコードされたデータをやりとりします。これはもちろんパディングをつけてやりとりします。(転送なので)
ですがエンコードするデータがわかっている場合この限りではないです。
そもそもパディングをつけるのは単純なプロトコルで文字列が連結されるときに末尾の情報が失われて復元できなくなるからです。
なので元々使用されるデータがわかっているものであれば正しくデコードできます。
今回だとwebauthnのパラメータは既に定まっているのでパディングをつけなくても問題ない理由です(むしろつけないでくれと言われています;;)。
ということで躓いたのはちゃんとプロトコルを理解していなかったからですね…

まとめ

ここで躓いて1日の大半を潰してしまった罪悪感からこの記事をしたためました。
プロトコルに則った実装を目指しましょう;;
それはそうとして普段何気に使っているBase64も理解できたのかもしれません…

Discussion