MySQL で実行できます。ただし、ランダムな単語生成はそれほどきれいではありません。塩の生成と適用に関しては、その部分は難しくありません。
2 つのステートメントを使用して、最初に全員のソルトを生成し、次にそれらを適用します。(注: 本当に 1 つのアカウントにのみ適用する場合は、WHERE 句を追加してください。)
mysql> select * from salty;
+------+------+------+
| id | pw | salt |
+------+------+------+
| 1 | fish | NULL |
| 2 | bird | NULL |
| 3 | fish | NULL |
+------+------+------+
(ユーザー 1 と 3 はたまたま同じパスワードを持っていることに注意してください。ただし、一度ソルト化してハッシュ化すると、それらが同じになることは望ましくありません。)
mysql> update salty set salt=SUBSTRING(MD5(RAND()), -10);
mysql> select * from salty;
+------+------+------------+
| id | pw | salt |
+------+------+------------+
| 1 | fish | 00fe747c35 |
| 2 | bird | ee4a049076 |
| 3 | fish | 6a8285f03c |
+------+------+------------+
(注: 特定のアルファベットのバージョンは後で示します)
mysql> update salty set pw=sha1(concat(pw,salt));
mysql> select * from salty;
+------+------------------------------------------+------------+
| id | pw | salt |
+------+------------------------------------------+------------+
| 1 | ac1b74c36b4d2426460562e8710bd467bd034fc8 | 00fe747c35 |
| 2 | d63d035f9cac1ac7c237774613b8b702d8c227df | ee4a049076 |
| 3 | 6a0b1e36f489ef959badf91b3daca87d207fb5de | 6a8285f03c |
+------+------------------------------------------+------------+
2 つのステートメントがあり、各行は一意にソルト化およびハッシュ化されています。
指定されたアルファベットの単語をランダムに生成するために、ELT() には醜いトリックがあります。64 文字のアルファベットの 10 文字の単語の場合:
UPDATE salty SET salt=CONCAT(
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9'),
ELT(1+FLOOR(RAND()*64),
'.','/',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9')
)
mysql> select * from salty;
+------+------+------------+
| id | pw | salt |
+------+------+------------+
| 1 | fish | TzHO0e5I/k |
| 2 | bird | 65xLptoDZ3 |
| 3 | fish | JNok/SfmkG |
+------+------+------------+
恐ろしいですね。しかし、単一の MySQL ステートメントでそれを行うと、特に数百万のレコードを持つテーブルに適用する必要がある場合に、PHP でループして行ごとに 1 つ (または 2 つ) のクエリを作成するよりもはるかに高速になる場合があります。一度に何百万ものクエリを作成するのではなく、1 つの醜いクエリを作成します。
しかし、他の人が言うように、SHA1 はもはや十分なハッシュではありません。
大量のレコードがある場合は、そのような MySQL クエリをいくつか使用して、暫定的な解決策として SHA2 を使用するようにすべてのレコードを更新し、PHP を使用して時間の経過とともにそれらをより強力なハッシュに個別に更新することが理にかなっている場合があります。もちろん、特定のレコードがどのハッシュを使用したかを知る方法が必要です。
補足として、(例のように) 1 つの行のみを更新する場合、MySQL 変数を使用して、行の 2 つの列を更新するのに十分な長さのランダムに生成された文字列を一時的に保持できます。
mysql> SET @salt=SUBSTRING(MD5(RAND()), -10); UPDATE salty SET salt=@salt,pw=SHA1(CONCAT(pw,@salt)) WHERE id=2; SET @salt=NULL;
このようにして、@salt の同じ値がソルトの設定と pw 計算の両方に使用されます。ただし、複数の行の更新では機能しません (それらはすべて同じソルトになってしまいます)。