postgresql の chkpass を使って 9文字以上のパスワードを確認する

今まで postgresql の contrib の chkpass は知ってたけど、先頭8文字のみが考慮されるというのは知らなんだ。
[マニュアル](https://www.postgresql.jp/document/9.4/html/chkpass.html)にはちゃんと書いてた。

一般的には 40バイトくらいは入力できないと要件満たせないと思うけど、楽なのでどうしても使いたい。そんな時の案です。

まずは、動作に必要な環境を作るところから
> postgres=# create extension chkpass;
> CREATE EXTENSION

この環境についてはこちら
> postgres=# SELECT version();
>                                                     version
> 
> -------------------------------------------------------------
>  PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-16), 64-bit
> (1 行)

21バイト(abcdefghijklmnopqrstu)と4バイト(hoge)の文字列を変数にセットする。これら値をパスワードとする。
> postgres=# \set password_string1 abcdefghijklmnopqrstu
> postgres=# \set password_string2 hoge
> postgres=# \echo :password_string1
> abcdefghijklmnopqrstu
> postgres=# \echo :password_string2
> hoge

最大24バイトのパスワードを格納できるテーブルを作成する。24バイト/8バイト=3 なので 3カラム用意する。（カラム passstring は確認用）
> postgres=# create table test(
> postgres(#   id integer
> postgres(# , passstring varchar(24)
> postgres(# , pass1 chkpass
> postgres(# , pass2 chkpass
> postgres(# , pass3 chkpass);
> CREATE TABLE

変数password_string1、password_string2 を使ってパスワード文字列を分割して登録する。
> postgres=# insert into test values(1
> postgres(# ,:'password_string1'
> postgres(# ,substring(rpad(:'password_string1',24),1,8)::chkpass
> postgres(# ,substring(rpad(:'password_string1',24),9,8)::chkpass
> postgres(# ,substring(rpad(:'password_string1',24),17,8)::chkpass
> postgres(# );
> INSERT 0 1
> postgres=# insert into test values(2
> postgres(# ,:'password_string2'
> postgres(# ,substring(rpad(:'password_string2',24),1,8)::chkpass
> postgres(# ,substring(rpad(:'password_string2',24),9,8)::chkpass
> postgres(# ,substring(rpad(:'password_string2',24),17,8)::chkpass
> postgres(# );
> INSERT 0 1
> postgres=# select * from test;
>  id |      passstring       |     pass1      |     pass2      |     pass3
> ----+-----------------------+----------------+----------------+----------------
>   1 | abcdefghijklmnopqrstu | :DcTDaTQ4YtH6g | :zaYEyktbrpYH. | :QPU2Mw7yCpA2c
>   2 | hoge                  | :oSgBR0rKFEbVk | :HP59N8oM5FNrk | :iThQNMgadFKe6
> (2 行)

パスワードが間違えているとレコード選択できない。
> postgres=# \set wrong_password hogehoge
> postgres=# select * from test
> postgres-# where pass1=substring(rpad(:'wrong_password',24),1,8)
> postgres-# and pass2=substring(rpad(:'wrong_password',24),9,8)
> postgres-# and pass3=substring(rpad(:'wrong_password',24),17,8);
>  id | passstring | pass1 | pass2 | pass3
> ----+------------+-------+-------+-------
> (0 行)

正しいパスワードだとそのレコードが選択できる。
> postgres=# \set password_string1 abcdefghijklmnopqrstu
> postgres=# select * from test
> postgres-# where pass1=substring(rpad(:'password_string1',24),1,8)
> postgres-# and pass2=substring(rpad(:'password_string1',24),9,8)
> postgres-# and pass3=substring(rpad(:'password_string1',24),17,8);
>  id |      passstring       |     pass1      |     pass2      |     pass3
> ----+-----------------------+----------------+----------------+----------------
>   1 | abcdefghijklmnopqrstu | :DcTDaTQ4YtH6g | :zaYEyktbrpYH. | :QPU2Mw7yCpA2c
> (1 行)

> postgres=# \set password_string2 hoge
> postgres=# select * from test
> postgres-# where pass1=substring(rpad(:'password_string2',24),1,8)
> postgres-# and pass2=substring(rpad(:'password_string2',24),9,8)
> postgres-# and pass3=substring(rpad(:'password_string2',24),17,8);
>  id | passstring |     pass1      |     pass2      |     pass3
> ----+------------+----------------+----------------+----------------
>   2 | hoge       | :oSgBR0rKFEbVk | :HP59N8oM5FNrk | :iThQNMgadFKe6
> (1 行)