- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2018-05-10T00:16:43+09:00;2018-05-10T00:10:15+09:00","","")
#author("2019-03-01T23:26:15+09:00","","")
* パスワードハッシュアルゴリズムのSHA-2対応 [#i424f475]
- ページ: [[BugTrack]]
- 投稿者: [[umorigu]]
- 優先順位: 低
- 状態: 完了
- カテゴリー: 本体新機能
- 投稿日: 2018-04-28 (土) 00:51:06
- バージョン: 1.5.1
- リリース予定バージョン: 1.5.2
** メッセージ [#z673f016]
//パスワード用のハッシュアルゴリズムにSHA-2(SHA-256, SHA-384, SHA-512)を利用できるようにする
パスワード用のハッシュアルゴリズムにSHA-2(SHA-256, SHA-512)を利用できるようにする
関連:
- [[BugTrack/709]]: パスワードのフォーマットを選択可能に(LDAP互換に)
- [[official:質問箱/5298]]: アカウント登録のリモート登録
--------
*** 使用できるフォーマット (追加) [#p7b992f7]
|~ |>|~保存フォーマット / scheme prefix | アルゴリズム |ソルト(seed)|h
| | | |CENTER: |CENTER: |c
| 1| PHP hash('sha512')関数の出力 | {x-php-sha512} | SHA-512 | なし |
| 2| PHP hash('sha256')関数の出力 | {x-php-sha256} | SHA-256 | なし |
| 1| LDAP SSHA512 (sha-512 with a seed) | {SSHA512} | SHA-512 | ''あり'' |
| 2| LDAP SHA512 | {SHA512} | SHA-512 | なし |
//| 3| LDAP SSHA384 (sha-384 with a seed) | {SSHA384} | SHA-384 | ''あり'' |
//| 4| LDAP SHA384 | {SHA384} | SHA-384 | なし |
| 5| LDAP SSHA256 (sha-256 with a seed) | {SSHA256} | SHA-256 | ''あり'' |
| 6| LDAP SHA256 | {SHA256} | SHA-256 | なし |
| 7| PHP hash('sha512')関数の出力 | {x-php-sha512} | SHA-512 | なし |
//| 8| PHP hash('sha384')関数の出力 | {x-php-sha384} | SHA-384 | なし |
| 9| PHP hash('sha256')関数の出力 | {x-php-sha256} | SHA-256 | なし |
*** 参考文献など (追加) [#e800f99b]
*** 使用例 [#h1efc54c]
//$adminpass = 'pass'; // Cleartext
//$adminpass = '{SSHA512}e/6TcRqTNIviKydZM8Alb62LbUPw8itUzVoxEekKUT9NwUpJg9iDysPz/QhonidaaNOysTJcWxbnLGnbAYvrLKNJUuQ/6b8v';
//$adminpass = '{SHA512}W3IrMH/ObJRJBdEyaR1eSiIUt/6StziSDrP846kEIKGVEcMBCg53ErBU2u9bV7rVnsvZOzKA8hBXj1R/Su1NJQ==';
// //$adminpass = '{SSHA384}QjFEKtJxCeqMSInJZaGwcj0CsLxPEsvdfVPJXSqaA4xzHOtsOQ/Wxf7lxpOILbo7UoPo09e4gO0=';
// //$adminpass = '{SHA384}rREZcHCKr/B1JNgfcVgpUrda3nSVHrs8JegB/Eo/F96NPo+8fCcRFEYv5j9n0zU2';
//$adminpass = '{SSHA256}ghLA4HsiVHGnj9uFEG17o/LacIQ837dueFryAUYWnlUHquqB+mDpdA==';
//$adminpass = '{SHA256}10/w7o2juYBrGMh32/KbveULW9jk2tejpyUAD+uC6PE=';
//$adminpass = '{x-php-sha512}5b722b307fce6c944905d132691d5e4a2214b7fe92b738920eb3fce3a90420a' .
// '19511c3010a0e7712b054daef5b57bad59ecbd93b3280f210578f547f4aed4d25';
// //$adminpass = '{x-php-sha384}ad111970708aaff07524d81f71582952b75ade74951ebb3c25e801fc4a3f17d' .
// // 'e8d3e8fbc7c271114462fe63f67d33536';
//$adminpass = '{x-php-sha256}d74ff0ee8da3b9806b18c877dbf29bbde50b5bd8e4dad7a3a725000feb82e8f1';
*** SHA-2 ハッシュの生成方法 [#z9e39f86]
基本的にオフラインで((信用できないネットワークを経由せずに))生成することを推奨します。
- OpenLDAP付属 の slappasswd コマンドによる生成方法 (CentOS 7 (7.4.1708) with openldap (openldap-2.4.44-5) の場合)
$ alias slappasswd="slappasswd -o module-path=/usr/lib64/openldap -o module-load=pw-sha2"
$ slappasswd -h '{SHA256}' -s pass
// $ slappasswd -h '{SHA384}' -s pass
$ slappasswd -h '{SHA512}' -s pass
$ slappasswd -h '{SSHA256}' -s pass # saltは指定不可、ランダム、固定長
// $ slappasswd -h '{SSHA384}' -s pass # saltは指定不可、ランダム、固定長
$ slappasswd -h '{SSHA512}' -s pass # saltは指定不可、ランダム、固定長
-- 備考: pw-sha2 モジュールが使用するsaltの長さ(上記ソースコードより / Base64 で処理する前)
slapd-sha2.c:#define SHA2_SALT_SIZE 8
slapd-sha2.c: char saltdata[SHA2_SALT_SIZE];
- OpenLDAP pw-sha2 モジュールのソースコード 上のREADMEに 以下が紹介されている
$ echo -n "secret" | openssl dgst -sha256 -binary | openssl enc -base64
// $ echo -n "secret" | openssl dgst -sha384 -binary | openssl enc -base64
$ echo -n "secret" | openssl dgst -sha512 -binary | openssl enc -base64
- openssl_slappasswd.sh -- OpenLDAP slappasswd(with pw-sha2)-compatible hash generator and verifier, only with openssl and shellscript -- https:// github.com/henoheno/openssl_slappasswd.sh
$ ./openssl_slappasswd.sh -h '{SHA256}' -s pass
// $ ./openssl_slappasswd.sh -h '{SHA384}' -s pass
$ ./openssl_slappasswd.sh -h '{SHA512}' -s pass
$ ./openssl_slappasswd.sh -h '{SSHA256}' -s pass # saltを指定しない場合ランダム、固定長
// $ ./openssl_slappasswd.sh -h '{SSHA384}' -s pass # saltを指定しない場合ランダム、固定長
$ ./openssl_slappasswd.sh -h '{SSHA512}' -s pass # saltを指定しない場合ランダム、固定長
-- 上記の openssl を用いるアイデアを拡張し、SHA-2に関してslappasswd互換+αの機能性を持たせたシェルスクリプト。OpenLDAPが不要であるところがポイント。saltを指定可能。
*** 参考文献など [#e800f99b]
- RFC 6234: US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF) https:// tools.ietf.org/html/rfc6234
-- パスワードハッシュアルゴリズム SHA-2 (SHA-256, SHA-384, SHA-512を含む) について
- Internet-Draft: Lightweight Directory Access Protocol (LDAP): Hashed Attribute values for 'userPassword' (March 13, 2013)
https:// tools.ietf.org/html/draft-stroeder-hashed-userpassword-values-01
-- OpenLDAPが使用している scheme prefix の名称 "{SHA256}" "{SSHA256}" 等について
- OpenLDAP pw-sha2 モジュールのソースコード (GitHub上のミラー)
-- github.com/openldap/openldap/tree/master/contrib/slapd-modules/passwd/sha2
- 他製品での事例
-- Dovecot v2.x documentation: Authentication / Password Schemes https:// wiki2.dovecot.org/Authentication/PasswordSchemes
{SSHA256}SoR/78T5q0UPFng8UCXWQxOUKhzrJZlwfNtllAupAeUT+kQv
-- CA Directory - 12.6: 管理 / CA Directory を管理するツール / DXtools
https:// docops.ca.com/cad126jp/%E7%AE%A1%E7%90%86/ca-directory/dxtools/dxpassword
-- iRedMail: Password hashes supported by iRedMail https:// docs.iredmail.org/password.hashes.html
{SSHA512}FxgXDhBVYmTqoboW+ibyyzPv/wGG7y4VJtuHWrx+wfqrs/lIH2Qxn2eA0jygXtBhMvRi7GNFmL++6aAZ0kXpcy1fxag=
-- Hashcat: Example hashes https:// hashcat.net/wiki/doku.php?id=example_hashes
--- AIXは少々イレギュラーのようだ
--------
- 対応しました。[[commit:077c9e1a83]] {x-php-sha256} と {x-php-sha512} が使えるようになりました -- [[umorigu]] &new{2018-04-28 (土) 23:14:57};
- 対応しました。[[commit:4669d6b232]] {x-php-sha256} と {x-php-sha512} が使えるようになりました -- [[umorigu]] &new{2018-04-28 (土) 23:14:57};
- 上記を受けて{x-php-sha384} {SHA256} {SSHA256} {SHA384} {SSHA384} {SHA512} {SSHA512} を実装しました。{SHA256} {SSHA256} {SHA384} {SSHA384} {SHA512} {SSHA512} については OpenLDAP 2.4.44 の slappasswd (with pw-sha2) で生成したハッシュを利用できる(互換性がある)事をテストしてあります。すみませんpukiwiki.ini.php や md5.inc.phpについては触っていません。(特にセキュリティにからむ部分であるため、ソースコードは別途メールで(も)お渡ししました) -- [[henoheno]] &new{2018-05-09 (水) 23:15:37};
- OpenLDAPでSHA-2の指定方法があるのですね。RFCにはなっていないようですが、取り込みました。ありがとうございます [[commit:9d67cfb2c0]] -- [[umorigu]] &new{2018-05-10 (木) 05:24:41};
-- (解説とまとめです) OpenLDAP互換、という [[BugTrack/709]] の方向性を維持しているものの、 {CLEARTEXT}、{SMD5}、{SSHA}、{SHAnnn}、{SSHAnnn} は RFC 2307 に則った scheme prefix ではありません。 -- [[henoheno]] &new{2018-06-16 (土) 16:29:11};
-- 上にある様にInternet-Draftも発行されているので、{SMD5}、{SSHA}、{SHAnnn}、{SSHAnnn}がRFCに追加されていた未来もあったのかもしれませんが、そこには至らなかった ようです。 -- [[henoheno]] &new{2018-06-16 (土) 16:29:32};
-- x- で始まる scheme prefix は、RFC 2307に則った「その他のスキーム」の(元々 想定されていた)表記方法です。 -- [[henoheno]] &new{2018-06-16 (土) 16:29:41};
-- SHA-224, SHA-512/224, SHA-512/256 が実装対象でない理由は、単純にOpenLDAP(のpw-sha2)がそれらを実装していないからです。 -- [[henoheno]] &new{2018-06-16 (土) 16:35:55};
#comment
※PukiWiki 1.5.2 に収録されている話題はここまで
--------
** メッセージ (SSHA-2パッチ) [#k12520ad]
- 上記を受けて{x-php-sha384} {SHA256} {SSHA256} {SHA384} {SSHA384} {SHA512} {SSHA512} を実装しました。{SHA256} {SSHA256} {SHA384} {SSHA384} {SHA512} {SSHA512} については OpenLDAP 2.4.44 の slappasswd (with pw-sha2) で生成したハッシュを利用できる(互換性がある)事をテストしてあります。すみませんpukiwiki.ini.php や md5.inc.phpについては触っていません。お好みでどうぞ。 -- [[henoheno]] &new{2018-05-09 (水) 23:15:37};
|~ |>|~保存フォーマット / scheme prefix | アルゴリズム |ソルト(seed)|h
| | | |CENTER: |CENTER: |c
| 1| LDAP SSHA512 (sha-512 with a seed) | {SSHA512} | SHA-512 | ''あり'' |
| 2| LDAP SHA512 | {SHA512} | SHA-512 | なし |
| 3| LDAP SSHA384 (sha-384 with a seed) | {SSHA384} | SHA-384 | ''あり'' |
| 4| LDAP SHA384 | {SHA384} | SHA-384 | なし |
| 5| LDAP SSHA256 (sha-256 with a seed) | {SSHA256} | SHA-256 | ''あり'' |
| 6| LDAP SHA256 | {SHA256} | SHA-256 | なし |
| 7| PHP hash('sha384')関数の出力 | {x-php-sha384} | SHA-384 | なし |
-
--- a/lib/auth.php
+++ b/lib/auth.php
@@ -85,6 +85,12 @@ function pkwk_hash_compute($phrase = '', $scheme = '{x-php-md5}', $prefix = TRUE
hash('sha256', $phrase);
break;
+ // PHP sha384
+ case '{x-php-sha384}' :
+ $hash = ($prefix ? ($canonical ? '{x-php-sha384}' : $scheme) : '') .
+ hash('sha384', $phrase);
+ break;
----
*** 1.5.x [#nef467d4]
- md5.inc.php について (1) SHA-384が漏れていたので追加 (2)とりあえずSHA256をデフォルトに (3)HTML出力を見やすく (4) schemeの並び順を調整 (5) plugin_md5_get_algos_enabled() を整理しました。branch_r1_5 へのパッチですが、1.5.2 にこれを無理に取り込んでいただく必要はありません。なぜならばcliのみで動作チェックしており、統合テスト的なaction周りの動作確認を行っていません。また、各自がmd5.inc.phpではなく外部でハッシュを生成するのであれば影響ありません -- [[henoheno]] &new{2018-06-16 (土) 21:31:01};
diff --git a/plugin/md5.inc.php b/plugin/md5.inc.php
index 854baa0..67e2bad 100644
--- a/plugin/md5.inc.php
+++ b/plugin/md5.inc.php
@@ -5,12 +5,16 @@
// License: GPL v2 or (at your option) any later version
//
// MD5 plugin: Allow to convert password/passphrase
-// * PHP sha1() -- If you have sha1() or mhash extension
// * PHP md5()
-// * PHP hash('sha256')
-// * PHP hash('sha512')
-// * LDAP SHA / SSHA -- If you have sha1() or mhash extension
+// * PHP sha1() -- If you have sha1() or mhash extension
+// * PHP hash('sha256') -- If you have hash() (PHP 5 >= 5.1.2)
+// * PHP hash('sha384') --
+// * PHP hash('sha512') --
// * LDAP MD5 / SMD5
+// * LDAP SHA / SSHA -- If you have sha1() or mhash extension
+// * LDAP SHA256 / SSHA256 -- If you have hash() (PHP 5 >= 5.1.2)
+// * LDAP SHA384 / SSHA384 --
+// * LDAP SHA512 / SSHA512 --
// User interface of pkwk_hash_compute() for system admin
function plugin_md5_action()
@@ -39,6 +43,9 @@ function plugin_md5_action()
if ($algos_enabled->sha256) {
array_push($scheme_list, 'x-php-sha256', 'SHA256', 'SSHA256');
}
+ if ($algos_enabled->sha384) {
+ array_push($scheme_list, 'x-php-sha384', 'SHA384', 'SSHA384');
+ }
if ($algos_enabled->sha512) {
array_push($scheme_list, 'x-php-sha512', 'SHA512', 'SSHA512');
}
@@ -67,8 +74,10 @@ function plugin_md5_show_form($nophrase = FALSE, $value = '')
}
if ($value != '') $value = 'value="' . htmlsc($value) . '" ';
$algos_enabled = plugin_md5_get_algos_enabled();
- $sha1_checked = $md5_checked = '';
- if ($algos_enabled->sha1) {
+ $sha256_checked = $sha1_checked = $md5_checked = '';
+ if ($algos_enabled->sha256) {
+ $sha256_checked = 'checked="checked" ';
+ } elseif ($algos_enabled->sha1) {
$sha1_checked = 'checked="checked" ';
} else {
$md5_checked = 'checked="checked" ';
@@ -85,48 +94,68 @@ EOD;
<input type="hidden" name="plugin" value="md5" />
<label for="_p_md5_phrase">Phrase:</label>
<input type="text" name="phrase" id="_p_md5_phrase" size="60" $value/><br />
+
// PHP sha512
case '{x-php-sha512}' :
$hash = ($prefix ? ($canonical ? '{x-php-sha512}' : $scheme) : '') .
@@ -125,6 +131,48 @@ function pkwk_hash_compute($phrase = '', $scheme = '{x-php-md5}', $prefix = TRUE
base64_encode(pkwk_hex2bin(sha1($phrase . $salt)) . $salt);
break;
+ // LDAP SHA256
+ case '{sha256}' :
+ $hash = ($prefix ? ($canonical ? '{SHA256}' : $scheme) : '') .
+ base64_encode(hash('sha256', $phrase, TRUE));
+ break;
+
+ // LDAP SSHA256
+ case '{ssha256}' :
+ // SHA-2 SHA-256 Key length = 256bits = 32bytes
+ $salt = ($salt != '' ? substr(base64_decode($salt), 32) : substr(crypt(''), -8));
+ $hash = ($prefix ? ($canonical ? '{SSHA256}' : $scheme) : '') .
+ base64_encode(hash('sha256', $phrase . $salt, TRUE) . $salt);
+ break;
EOD;
- $form .= <<<EOD
- <input type="radio" name="scheme" id="_p_md5_md5" value="x-php-md5" />
- <label for="_p_md5_md5">PHP md5</label><br />
+ if ($algos_enabled->sha512) $form .= <<<EOD
+ <input type="radio" name="scheme" id="_p_md5_sha512" value="x-php-sha512" />
+ <label for="_p_md5_sha512">PHP sha512</label><br />
+
+ // LDAP SHA384
+ case '{sha384}' :
+ $hash = ($prefix ? ($canonical ? '{SHA384}' : $scheme) : '') .
+ base64_encode(hash('sha384', $phrase, TRUE));
+ break;
EOD;
- if ($algos_enabled->sha1) $form .= <<<EOD
- <input type="radio" name="scheme" id="_p_md5_sha1" value="x-php-sha1" />
- <label for="_p_md5_sha1">PHP sha1</label><br />
+ if ($algos_enabled->sha384) $form .= <<<EOD
+ <input type="radio" name="scheme" id="_p_md5_sha384" value="x-php-sha384" />
+ <label for="_p_md5_sha384">PHP sha384</label><br />
+
+ // LDAP SSHA384
+ case '{ssha384}' :
+ // SHA-2 SHA-384 Key length = 384bits = 48bytes
+ $salt = ($salt != '' ? substr(base64_decode($salt), 48) : substr(crypt(''), -8));
+ $hash = ($prefix ? ($canonical ? '{SSHA384}' : $scheme) : '') .
+ base64_encode(hash('sha384', $phrase . $salt, TRUE) . $salt);
+ break;
EOD;
if ($algos_enabled->sha256) $form .= <<<EOD
<input type="radio" name="scheme" id="_p_md5_sha256" value="x-php-sha256" />
<label for="_p_md5_sha256">PHP sha256</label><br />
+
+ // LDAP SHA512
+ case '{sha512}' :
+ $hash = ($prefix ? ($canonical ? '{SHA512}' : $scheme) : '') .
+ base64_encode(hash('sha512', $phrase, TRUE));
+ break;
+EOD;
+ if ($algos_enabled->sha1) $form .= <<<EOD
+ <input type="radio" name="scheme" id="_p_md5_sha1" value="x-php-sha1" />
+ <label for="_p_md5_sha1">PHP sha1</label><br />
+
+ // LDAP SSHA512
+ case '{ssha512}' :
+ // SHA-2 SHA-512 Key length = 512bits = 64bytes
+ $salt = ($salt != '' ? substr(base64_decode($salt), 64) : substr(crypt(''), -8));
+ $hash = ($prefix ? ($canonical ? '{SSHA512}' : $scheme) : '') .
+ base64_encode(hash('sha512', $phrase . $salt, TRUE) . $salt);
+ break;
+EOD;
+ $form .= <<<EOD
+ <input type="radio" name="scheme" id="_p_md5_md5" value="x-php-md5" />
+ <label for="_p_md5_md5">PHP md5</label><br />
+
// LDAP CLEARTEXT and just cleartext
case '{cleartext}' : /* FALLTHROUGH */
case '' :
EOD;
if ($algos_enabled->sha512) $form .= <<<EOD
- <input type="radio" name="scheme" id="_p_md5_sha512" value="x-php-sha512" />
- <label for="_p_md5_sha512">PHP sha512</label><br />
+ <input type="radio" name="scheme" id="_p_md5_lssha512" value="SSHA512" />
+ <label for="_p_md5_lssha512">LDAP SSHA512 (sha-512 with a seed) *</label><br />
+ <input type="radio" name="scheme" id="_p_md5_lsha512" value="SHA512" />
+ <label for="_p_md5_lsha512">LDAP SHA512 (sha-512)</label><br />
+
+EOD;
+ if ($algos_enabled->sha384) $form .= <<<EOD
+ <input type="radio" name="scheme" id="_p_md5_lssha384" value="SSHA384" />
+ <label for="_p_md5_lssha384">LDAP SSHA384 (sha-384 with a seed) *</label><br />
+ <input type="radio" name="scheme" id="_p_md5_lsha384" value="SHA384" />
+ <label for="_p_md5_lsha384">LDAP SHA384 (sha-384)</label><br />
+
+EOD;
+ if ($algos_enabled->sha256) $form .= <<<EOD
+ <input type="radio" name="scheme" id="_p_md5_lssha256" value="SSHA256" />
+ <label for="_p_md5_lssha256">LDAP SSHA256 (sha-256 with a seed) *</label><br />
+ <input type="radio" name="scheme" id="_p_md5_lsha256" value="SHA256" $sha256_checked/>
+ <label for="_p_md5_lsha256">LDAP SHA256 (sha-256)</label><br />
+
EOD;
if ($algos_enabled->sha1) $form .= <<<EOD
<input type="radio" name="scheme" id="_p_md5_lssha" value="SSHA" $sha1_checked/>
<label for="_p_md5_lssha">LDAP SSHA (sha-1 with a seed) *</label><br />
<input type="radio" name="scheme" id="_p_md5_lsha" value="SHA" />
<label for="_p_md5_lsha">LDAP SHA (sha-1)</label><br />
+
EOD;
$form .= <<<EOD
<input type="radio" name="scheme" id="_p_md5_lsmd5" value="SMD5" $md5_checked/>
<label for="_p_md5_lsmd5">LDAP SMD5 (md5 with a seed) *</label><br />
<input type="radio" name="scheme" id="_p_md5_lmd5" value="MD5" />
<label for="_p_md5_lmd5">LDAP MD5</label><br />
-EOD;
- if ($algos_enabled->sha256) $form .= <<<EOD
- <input type="radio" name="scheme" id="_p_md5_lssha256" value="SSHA256"/>
- <label for="_p_md5_lssha256">LDAP SSHA256 (sha256 with a seed) *</label><br />
- <input type="radio" name="scheme" id="_p_md5_lsha256" value="SHA256" />
- <label for="_p_md5_lsha256">LDAP SHA256</label><br />
-EOD;
- if ($algos_enabled->sha512) $form .= <<<EOD
- <input type="radio" name="scheme" id="_p_md5_lssha512" value="SSHA512"/>
- <label for="_p_md5_lssha512">LDAP SSHA512 (sha512 with a seed) *</label><br />
- <input type="radio" name="scheme" id="_p_md5_lsha512" value="SHA512" />
- <label for="_p_md5_lsha512">LDAP SHA512</label><br />
-EOD;
- $form .= <<<EOD
+
<input type="checkbox" name="prefix" id="_p_md5_prefix" checked="checked" />
<label for="_p_md5_prefix">Add scheme prefix (RFC2307, Using LDAP as NIS)</label><br />
@@ -139,6 +168,7 @@ EOD;
<p>* = Salt enabled<p/>
</div>
</form>
+
EOD;
return $form;
@@ -149,21 +179,11 @@ EOD;
*/
function plugin_md5_get_algos_enabled()
{
- $sha1_enabled = function_exists('sha1');
- $sha256_enabled = false;
- $sha512_enabled = false;
- if (function_exists('hash') && function_exists('hash_algos')) {
- $algos = hash_algos();
- if (in_array('sha256', $algos)) {
- $sha256_enabled = true;
- }
- if (in_array('sha512', $algos)) {
- $sha512_enabled = true;
- }
- }
+ $algos = function_exists('hash_algos') ? hash_algos() : array();
return (object) array(
- 'sha1' => $sha1_enabled,
- 'sha256' => $sha256_enabled,
- 'sha512' => $sha512_enabled,
+ 'sha1' => function_exists('sha1'),
+ 'sha256' => in_array('sha256', $algos),
+ 'sha384' => in_array('sha384', $algos),
+ 'sha512' => in_array('sha512', $algos),
);
}
#comment