Base54 は,任意バイト列をアルファベットと数字で表現する方式。Base64 と同等の機能だが,記号(+,/,=)と,アルファベットのうち数字と紛らわしい I,L,O,S を除いた大/小文字の 54 文字を使う。MD5 などで求めたハッシュ値をパスワードとして扱う時などに最適。
Base54 is an explaination of any bytes like Base64 encoding,
but it doesn't use punctions (+, /, =) and alphabets I, L, O and
S both cases, because they are confusing with digits 1, 0 and 5.
E.g., you can treat the result of Base54 as "password" easy.
パスワードとしての利用は,ファイルを他者に見られないよう保護したい時に使うパスワードを生成するために,このサイトで使う PPOP で採用している。PPOP については,以下を参照。
なお,このサイトの管理者(石川)が勝手に作った規格のため,必死になって検索で調べたりしないよーに。
● 概略 / SYNOPSIS
「User-ID+パスワード種」から MD5 で求めた 128 ビットバイナリ値を Base54 で文字列化したものをパスワードとして使う例。
use Base54; # This module use Digest::MD5; # an example my $pws ="PasswordSeed"; print " User-ID :"; my $uid = <STDIN>; chomp $uid; my $pwright = encode_base54( md5( "$pws:$uid" ) ); print "Password :"; my $pwinput = <STDIN>; chomp $pwinput; print( ($pwinput eq $pwright)?"OK!\n":"NG!\n" );
● 関数 / FUNCTION
Perl のモジュールで,使えるようになる関数は以下の2つ。
- encode_base54( $bytestring ) # returns a Base54 string.
- decode_base54( $base54string ) # returns a Bytestring.
ソースコードは公開未定
◆ encode_base54( $bytestring )
任意バイト列から Base54 文字列を作って返す。使用される文字は,数字と,アルファベットから I,L,O,S を除いた 22 文字のそれぞれ大文字と小文字の 44 文字,合わせて 54 文字。
必要な文字数は以下の式で求められる。
base54chars = int( ( bytelength * 32 + 22 )/ 23 )
◆ decode_base54( $base54string )
Base54 文字列から元のバイト列に直して返す。Base54 の文字数から求まるバイト数は以下の通り。
bytelength = int( ( base54chars * 23 )/ 32 )
● 詳細 / DETAIL
54^4 ≒ 2^23 であることを利用し,54 種類の文字を使って,任意のバイト列を 23 ビットごとに区切り4文字ずつ符号化する。Base64 とは異なり,下位ビットから符号化する。バイトの並びは Intel 形式の整数(Little-endian integer)に近い扱いになる。
使用する文字は,数字と,アルファベットから I,L,O,S を除いた
22 文字のそれぞれ大文字と小文字の 44 文字の,合わせて 54 文字。以下の順に「数字」として扱う。0~F(大文字)は 16 進数と同じで,a(小文字)は 32,z は 53 を表す「数字」として扱う。
0123456789ABCDEFGHJKMNPQRTUVWXYZabcdefghjkmnpqrtuvwxyz
文字列の作り方は,23 ビット整数の 54 の「剰余」を求めて上記の文字に割り当て,54 の商に対してまた 54 の「剰余」を求めて……を3回繰り返し,最後の「商」を4文字目として扱う。
たとえば,3バイトの並びが 0x12, 0x34, 0x56 の場合,16 進数の
0x563412 として扱う。23 ビット整数として文字化すると……。
0x563412 = 5649426(10) 5649426 mod 54 = 0 →"0" int( 5649426 / 54 )= 104619, 104619 mod 54 = 21 →"N" int( 104619 / 54 )= 1937, 1937 mod 54 = 47 →"t" int( 1937 / 54 )=35 →"d" result: "0Ntd"
3バイトから 23 ビットを符号化すると1ビット余るので,それは次の 22 ビットの最下ビットに追加して符号化していく。たとえば上記の次に 0x78, 0x9A, 0xBC というバイト並びが来る場合は,ここから 22
ビット取り出した 0x3C9A78 を左に1ビットシフトして,前述の最上位ビットの0(ゼロ)を加算した 0x7934F0 から文字列を求める。
余った2ビット(2)は,続くバイトから 21 ビット持ってきて左に2ビットシフトし,2を加算した結果から文字列を求める。以降同様。
バイト列終端で 23 ビットに満たなかったビットは,上位ビットを0(ゼロ)で埋めて 23 ビット整数として扱って文字にする。余ったビット数に応じて追加する文字数を決める。
- 余ったビット数 1-5: 1 文字追加
- 余ったビット数 6-11: 2 文字追加
- 余ったビット数 12-17: 3 文字追加
- 余ったビット数 18-22: 4 文字追加
冗長度は約 139%(=32/23)となる(Base64 は 133%=4/3)。