1

データベースのテーブルにパスワードがプレーンテキストであるプロジェクトを継承しました。MD5に変換する場合は、次のようにします

UPDATE users SET encrypted_password = MD5(password);

MD5 の代わりに Java BCrypt クラスを使用しています。テーブルには約 300 万人のユーザーがいます。各平文パスワードを新しい「encrypted_pa​​ssword」列に暗号化する最適な方法はありますか?

私が考えることができる唯一の方法は、各ユーザーの ResultSet をループし、プレーンテキストのパスワードを選択し、それを bcrypt してから、行を更新することです。これには半永久がかかると何かが言っています。もっと速いものはありますか?

4

1 に答える 1

0

それが唯一の方法かもしれないと思いますが、それには永遠に時間がかかりましたが、各行を反復処理し、プレーンテキストのパスワードを BCrypt して保存する単純なクラスを作成するだけになりました。正気を保つために、BCrypting 後に一致が良好かどうかを確認しました。不一致はまったくありませんでした。Encryption クラスは、私が他の多くの暗号化メソッドで使用している実際のクラスの一部にすぎません。わかりやすくするために、関連するメソッドを含めただけです。それが誰かを助けるなら、ここにコードがあります:

public class Bcrypter {

    public static void main(String args []) {

        int lower = Integer.parseInt(args[0]);
        int upper = Integer.parseInt(args[1]);

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        int row = 0;
        try {
            conn = Database.getConnection();
            pstmt = conn.prepareStatement("SELECT id, user_pass, user_pass_bcrypt FROM users ORDER BY id LIMIT ?, ?",
                    ResultSet.TYPE_SCROLL_INSENSITIVE,
                    ResultSet.CONCUR_UPDATABLE);
            pstmt.setInt(1, lower);
            pstmt.setInt(2, upper);
            rs = pstmt.executeQuery();

            while (rs.next()) {

                String user_pass = rs.getString("user_pass");
                String user_pass_encrypted = Encryption.encrypt(user_pass);

                if (Encryption.isMatch(user_pass, user_pass_encrypted)) {
                    rs.updateString("user_pass_bcrypt", user_pass_encrypted);
                    rs.updateRow();

                    if (++row % 10000 == 0) {
                        System.out.println(row);
                    }

                } else {
                    System.out.println("Mismatch " + user_pass);
                }
            }
            System.out.print("DONE");

        } catch (SQLException e) {
            e.printStackTrace();
            System.out.print(e);
        } finally {
            Database.closeConnection(conn, pstmt, rs);
        }
    }
}


public final class Encryption {

    private Encryption() {
        // can't instantiate
    }

    /**
     * Encrypts a password. The gensalt() method's default param is
     * 10 but it's lowered here, assuming better performance.
     */
    public static String encrypt (String plainPassword) {
        return BCrypt.hashpw(plainPassword, BCrypt.gensalt(5));
    }

    /**
     * Checks whether a plaintext password matches one that has been
     * hashed previously
     */
    public static Boolean isMatch(String plainPassword, String hashedPassword) {
        return (BCrypt.checkpw(plainPassword, hashedPassword));
    }
}
于 2013-10-15T16:29:16.047 に答える