Linux（CentOS8）のパスワード

Linux（CentOS8）のユーザーのパスワードについて確認してみたので、その時のメモを残します。

# 環境
+ OS：CentOS Linux release 8.5.2111
+ Perl：v5.26.3
+ OpenSSL：OpenSSL 1.1.1k FIPS 25 Mar 2021

```console:バージョン
[root@centos85 ~]# cat /etc/redhat-release
CentOS Linux release 8.5.2111
[root@centos85 ~]# perl -version

This is perl 5, version 26, subversion 3 (v5.26.3) built for x86_64-linux-thread-multi
(with 56 registered patches, see perl -V for more detail)

Copyright 1987-2018, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

[root@centos85 ~]# openssl version
OpenSSL 1.1.1k  FIPS 25 Mar 2021
[root@centos85 ~]#
```

なお、CentOS8では`/etc/login.defs`の`ENCRYPT_METHOD`を確認すると`SHA512`となっています。

```console:ENCRYPT_METHOD確認
[root@centos85 ~]# grep ^ENCRYPT_METHOD /etc/login.defs
ENCRYPT_METHOD SHA512
[root@centos85 ~]#
```

`ENCRYPT_METHOD`は、Linuxシステムにおけるパスワードハッシュアルゴリズムの設定を指定するパラメータです。
この設定により、新たに設定されるユーザーのパスワードや既存のパスワードを変更する際に使用されるハッシュアルゴリズムが決まります。

# 1. ユーザーを追加
`useradd`コマンドで、OSユーザーを追加します。
以下のコマンドで、「testuser1」と「testuser2」を追加し、パスワードを設定します。
ここでは「testuser1」と「testuser2」のパスワードに`password`を設定します。
`useradd testuser1 && passwd testuser1`
`useradd testuser2 && passwd testuser2`

```console:testuser1とtestuser2のユーザー追加とパスワード設定
[root@centos85 ~]# useradd testuser1 && passwd testuser1
ユーザー testuser1 のパスワードを変更。
新しいパスワード:
よくないパスワード: このパスワードは辞書チェックに失敗しました。 - 辞書の単語に 基づいています
新しいパスワードを再入力してください:
passwd: すべての認証トークンが正しく更新できました。
[root@centos85 ~]# useradd testuser2 && passwd testuser2
ユーザー testuser2 のパスワードを変更。
新しいパスワード:
よくないパスワード: このパスワードは辞書チェックに失敗しました。 - 辞書の単語に 基づいています
新しいパスワードを再入力してください:
passwd: すべての認証トークンが正しく更新できました。
[root@centos85 ~]#
```

# 2. パスワードが保存されている/etc/shadowを確認

以下のコマンドで`/etc/shadow`に保存されている「testuser1」と「testuser2」のパスワードを確認してみます。
`cat /etc/shadow | grep -e testuser1 -e testuser2`

```console:実行結果
[root@centos85 ~]# cat /etc/shadow | grep -e testuser1 -e testuser2
testuser1:$6$ZsEyWv3POC7eGBjO$z34GP7kYzOy/s0MmLjlGDxHb2QckvtOaVWSiNTkMXdHEvt/tfLN90HHyt5n.9.2tmF7ZapYw6kRU4LiCQAt4n1:19947:0:99999:7:::
testuser2:$6$n.VSBPS6KxMQ1rNf$im1dy0sHZZZaoboVDeqnVd1aBmzFYNF64.46HcusL3C3GlpAYrbCfejs9VoUDCHxCESSYjoz.ip6Dwdm6ZO1I0:19947:0:99999:7:::
[root@centos85 ~]#
```

`/etc/shadow`は`:`区切りで以下が記載されています。

|項目|内容|
|:---|:---|
|第1フィールド|ユーザ名|
|第2フィールド|パスワード|
|第3フィールド|パスワードを最後に変更した日|
|第4フィールド|変更可能最短期間|
|第5フィールド|未変更可能最長期間|
|第6フィールド|未変更時警告日|
|第7フィールド|ログインしない場合に無効になる日数|
|第8フィールド|アカウントが失効になるまでの日数|
|第9フィールド|フラグ|

第2フィールドがパスワードなので、
testuser1は
`$6$ZsEyWv3POC7eGBjO$z34GP7kYzOy/s0MmLjlGDxHb2QckvtOaVWSiNTkMXdHEvt/tfLN90HHyt5n.9.2tmF7ZapYw6kRU4LiCQAt4n1`

testuser2は
`$6$n.VSBPS6KxMQ1rNf$im1dy0sHZZZaoboVDeqnVd1aBmzFYNF64.46HcusL3C3GlpAYrbCfejs9VoUDCHxCESSYjoz.ip6Dwdm6ZO1I0`
となっています。

# 3. パスワードの項目の確認
`/etc/shadow`の第2フィールドのパスワードの項目は`$`区切りで以下が記載されています。

|項目|内容|
|:---|:---|
|第1フィールド|id、ハッシュアルゴリズム<br>`$1`：MD5 <br>`$5`：SHA-256<br>`$6`：SHA-512）<br>`$2a`：bcrypt 2a(Blowfish)|
|第2フィールド|ソルト（ランダムな値）|
|第3フィールド|ソルトとパスワードから生成されたハッシュ値|

testuser1は以下の通りです。
|項目|内容|
|:---|:---|
|ハッシュアルゴリズム|`$6`：SHA-512|
|ソルト|ZsEyWv3POC7eGBjO|
|ソルトとパスワードから生成されたハッシュ値|z34GP7kYzOy/s0MmLjlGDxHb2QckvtOaVWSiNTkMXdHEvt/tfLN90HHyt5n.9.2tmF7ZapYw6kRU4LiCQAt4n1|

testuser2は以下の通りです。
|項目|内容|
|:---|:---|
|ハッシュアルゴリズム|`$6`：SHA-512|
|ソルト|n.VSBPS6KxMQ1rNf|
|ソルトとパスワードから生成されたハッシュ値|im1dy0sHZZZaoboVDeqnVd1aBmzFYNF64.46HcusL3C3GlpAYrbCfejs9VoUDCHxCESSYjoz.ip6Dwdm6ZO1I0|

# 4. ソルトと平文パスワードからハッシュ値を生成
以下のコマンドで「testuser1」と「testuser2」のソルトとパスワードからそれぞれハッシュ値を生成してみます。
`crypt`関数の第1引数には平文のパスワードを、第2引数にはソルトを入れます。（`$`を`\`でエスケープします。）
`perl -e 'print crypt("password", "\$6\$ZsEyWv3POC7eGBjO");'`
`perl -e 'print crypt("password", "\$6\$n.VSBPS6KxMQ1rNf");'`

```console:ソルトと平文のパスワードからハッシュ値を生成
[root@centos85 ~]# perl -e 'print crypt("password", "\$6\$ZsEyWv3POC7eGBjO");'
$6$ZsEyWv3POC7eGBjO$z34GP7kYzOy/s0MmLjlGDxHb2QckvtOaVWSiNTkMXdHEvt/tfLN90HHyt5n.9.2tmF7ZapYw6kRU4LiCQAt4n1[root@centos85 ~]#
[root@centos85 ~]# perl -e 'print crypt("password", "\$6\$n.VSBPS6KxMQ1rNf");'
$6$n.VSBPS6KxMQ1rNf$im1dy0sHZZZaoboVDeqnVd1aBmzFYNF64.46HcusL3C3GlpAYrbCfejs9VoUDCHxCESSYjoz.ip6Dwdm6ZO1I0[root@centos85 ~]#
```

`/etc/shadow`の第2フィールドと内容が一致することを確認することができます。

なお、`openssl passwd`を使った以下のコマンドでも確認することができます。
`openssl passwd -6 -salt=ZsEyWv3POC7eGBjO password`
`openssl passwd -6 -salt=n.VSBPS6KxMQ1rNf password`

```console:openssl passwdでの実行結果
[root@centos85 ~]# openssl passwd -6 -salt=ZsEyWv3POC7eGBjO password
$6$ZsEyWv3POC7eGBjO$z34GP7kYzOy/s0MmLjlGDxHb2QckvtOaVWSiNTkMXdHEvt/tfLN90HHyt5n.9.2tmF7ZapYw6kRU4LiCQAt4n1
[root@centos85 ~]# openssl passwd -6 -salt=n.VSBPS6KxMQ1rNf password
$6$n.VSBPS6KxMQ1rNf$im1dy0sHZZZaoboVDeqnVd1aBmzFYNF64.46HcusL3C3GlpAYrbCfejs9VoUDCHxCESSYjoz.ip6Dwdm6ZO1I0
[root@centos85 ~]#
```

# 5. 補足


パスワードをハッシュ化する際には、ソルトに加えて、ハッシュ値を再度ハッシュ化するプロセスを繰り返すストレッチング（stretching）が行われます。（デフォルトで5000回）
ストレッチングを行うことで、ブルートフォース攻撃や辞書攻撃に対する耐性が高まります。攻撃者が大量のパスワード候補を試す場合、計算に時間がかかるため、攻撃のコストが大幅に増加します。

---

以上