htpasswdコマンドのことをそろそろ本気出して覚える

この記事は[LIGアドベントカレンダー2018](https://qiita.com/advent-calendar/2018/lig)の5日目の記事です。

まだ僕らにはBASIC認証が必要で、なんかいつも認証かけるのにググってる気がするので、いいかげん `htpasswd` を覚えます。

## usage

```shell
$ htpasswd # オプション何もつけないとusage出てくる
Usage:
	htpasswd [-cimBdpsDv] [-C cost] passwordfile username
	htpasswd -b[cmBdpsDv] [-C cost] passwordfile username password

	htpasswd -n[imBdps] [-C cost] username
	htpasswd -nb[mBdps] [-C cost] username password
 -c  Create a new file.
 -n  Don't update file; display results on stdout.
 -b  Use the password from the command line rather than prompting for it.
 -i  Read password from stdin without verification (for script usage).
 -m  Force MD5 encryption of the password (default).
 -B  Force bcrypt encryption of the password (very secure).
 -C  Set the computing time used for the bcrypt algorithm
     (higher is more secure but slower, default: 5, valid: 4 to 31).
 -d  Force CRYPT encryption of the password (8 chars max, insecure).
 -s  Force SHA encryption of the password (insecure).
 -p  Do not encrypt the password (plaintext, insecure).
 -D  Delete the specified user.
 -v  Verify password for the specified user.
On other systems than Windows and NetWare the '-p' flag will probably not work.
The SHA algorithm does not use a salt and is less secure than the MD5 algorithm.
```

## -c

ユーザーとパスワードが書かれたファイルを新規作成/上書きする。上書きされたくなければ `-c` を取って、ファイル名を指定する。

```shell
$ htpasswd -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
$ cat .htpasswd
user1:$apr1$YXJ9sgt8$4q2zD6n.dhWuR3BIslZAW0
```

## -n

ファイルを作らない。結果を画面に表示する。

```shell
$ htpasswd -n user1
New password:
Re-type new password:
user1:$apr1$UkWrOYVg$/iGEgMrCAMDYzZVXyTgaj0
```

## -b

パスワードをコマンドラインから入力する。履歴に残っちゃうのであんまり気持ちよくない。

```shell
$ htpasswd -b -c ./.htpasswd user1 test
Adding password for user user1
$ cat .htpasswd
user1:$apr1$IfYLGS8L$/u/mQfNjTadAfPZEvkjgU/
```

## -i

標準入力からパスワードを取得する。

```shell
$ echo 'test' | htpasswd -i -c ./.htpasswd user1
Adding password for user user1
$ cat .htpasswd
user1:$apr1$mDpbk/7h$hksMgs/rthAnXaiBvcGq80
```

## -m

MD5でパスワードを作る。デフォルトの挙動。MD5も特に安全じゃない気がするんだけど、そのへんどうなんでしょうね。

```shell
$ htpasswd -m -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
$ cat .htpasswd
user1:$apr1$aCrvoR8E$rP6llmYrpPWbTGBJzBc800
```

## -B

bcryptでパスワードを作る。MD5で作ったときよりセキュリティ強度が高い。

```shell
htpasswd -B -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
ito_masakuni@lig-mi % cat .htpasswd
user1:$2y$05$3fVDcJJBTXg4F3POLKcQ/eTf3v0x8Oq90Ed24y5TmitRY5CrqI89.
```

パスワード先頭の `2y` が暗号化のバージョンを表していて、 `05` がストレッチング回数を表している。ストレッチング回数はハッシュ化を何回繰り返すかだが、この辺のことはもっと調べないと正しく書けない。

## -C

上述のストレッチング回数を4〜31の範囲で変更する。数を増やすと処理時間が増える。（＝それを解くために必要な処理時間も必要になるのでセキュリティ強度が高くなる）

```shell
$ time htpasswd -B -C 5 -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
htpasswd -B -C 5 -c ./.htpasswd user1  0.02s user 0.01s system 0% cpu 2.652 total
$ time htpasswd -B -C 20 -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
htpasswd -B -C 20 -c ./.htpasswd user1  54.45s user 0.20s system 95% cpu 57.485 total
```

ちなみに `-B` を付けないと、 `-C` も無視される。

```
$ htpasswd -C 20 -c ./.htpasswd user1
Warning: Ignoring -C argument for this algorithm.
```

## -d

パスワードにcryptを使う。安全じゃないので使っちゃいけない。パスワードに9文字以上使えない。使うと8文字に切り落とされて使用されてしまうため、昔困ったことがある。

```shell
$ htpasswd -d -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
$ cat .htpasswd
user1:Lc4ctM/X.UJwI
```

## -s

パスワードにSHAを使う。もう安全じゃないので使っちゃいけない。

```shell
$ htpasswd -s -c ./.htpasswd user1
New password:
Re-type new password:
Adding password for user user1
$ cat .htpasswd
user1:{SHA}qUqP5cyxm6YcTAhz05Hph5gvu9M=
```

## -p

パスワードをプレーンに保存する。安全とかそういう問題じゃないので使っちゃいけない。

```shell
$ htpasswd -p -c ./.htpasswd user1
Warning: storing passwords as plain text might just not work on this platform.
New password:
Re-type new password:
Adding password for user user1
$ cat .htpasswd
user1:test
```

## -D

ファイルに記載されたユーザーを削除する。

```shell
$ htpasswd -b -c ./.htpasswd user1 test
Adding password for user user1
$ htpasswd -b ./.htpasswd user2 test
Adding password for user user2
$ cat .htpasswd
user1:$apr1$YZhDpLj7$o/AYANqaGRVdOnXttmORb0
user2:$apr1$1Y.2xmse$BtN2GYz7RS8E0Oig3hYO.1
$ htpasswd -D ./.htpasswd user1
Deleting password for user user1
$ cat .htpasswd
user2:$apr1$1Y.2xmse$BtN2GYz7RS8E0Oig3hYO.1
```

## -v

パスワードが正しいかチェックする。

```shell
$ htpasswd -b -c ./.htpasswd user1 test
Adding password for user user1
$ htpasswd -v ./.htpasswd user1
Enter password: # パスワードを間違える
password verification failed
$ htpasswd -v ./.htpasswd user1
Enter password:　# 正しいパスワードを入れる
Password for user user1 correct.
```