0

キーストレッチングと UUID をソルトとして組み合わせた SHA1 パスワードハッシュを実装しようとしています。ソルトは、データベース バックエンド内の usersTable の列として保存されるため、各ユーザーは独自の固有のソルトが生成されます。

私の問題は、パスワード ハッシュを再生成しようとすると、ハッシュが一致せず、問題がどこにあるのかわからないことです。

registerUser は、createUser からユーザー オブジェクトをフェッチし、それをデータベースに保持します。次に、validatePassword を使用してハッシュを再生成します。完全なコード スニペットについては、以下を参照してください。これは、パスワードを保護するための私の最初の試みです。明らかに、どこかでおかしくなりましたが、バグを見つけることができません。

public void registerUser() {
    try {

        Usertable newUser = createUser();

        // user constructed at this point, persist it to the database.
        utx.begin();
        em.persist(newUser);
        utx.commit();

        // Register user with Meter
        Meter myMeter = (Meter) em.createNamedQuery("Meter.findByMeterid").setParameter("meterid", this.meterId).getSingleResult();
        myMeter.setUsername(newUser);

        utx.begin();
        em.merge(myMeter);
        utx.commit();

    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NotSupportedException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SystemException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (RollbackException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicMixedException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicRollbackException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalStateException ex) {
        Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex);
    }

}

private Usertable createUser() throws NoSuchAlgorithmException {
    Security securityLevel = (Security) em.createNamedQuery("Security.findBySecurityid").setParameter("securityid", SECURITY_LEVEL_USER).getSingleResult();
    Usertable newUser = new Usertable();

    // generate UUID to be used as a salt.
    UUID salt = UUID.randomUUID();

    // generate hash
    MessageDigest msgDigest = MessageDigest.getInstance("SHA-1");
    String inputText = new String(salt.toString() + this.password);
    for (int i = 0; i < ITERATIONS; i++) {
        msgDigest.update(inputText.getBytes());
        byte rawByte[] = msgDigest.digest();
        inputText = (new BASE64Encoder()).encode(rawByte);
    }

    String hashValue = inputText;

    newUser.setUsername(this.userName);
    newUser.setSecurityid(securityLevel);
    newUser.setSalt(salt.toString());
    newUser.setPassword(hashValue);

    return newUser;
}

public void validatePassword(FacesContext context, UIComponent ui, Object passwordField) {
    try {
        UIInput userNameInput = (UIInput) context.getViewRoot().findComponent("regform:userName");
        String userName = (String) userNameInput.getValue();

        Usertable myUser = (Usertable) em.createNamedQuery("Usertable.findByUsername").setParameter("username", userName).getSingleResult();

        // generate hash
        MessageDigest msgDigest = MessageDigest.getInstance("SHA-1");
        String inputText = new String(myUser.getSalt() + this.password);
        for (int i = 0; i < ITERATIONS; i++) {
            msgDigest.update(inputText.getBytes());
            byte rawByte[] = msgDigest.digest();
            inputText = (new BASE64Encoder()).encode(rawByte);
        }

        if (!inputText.equals(myUser.getPassword())) {
            String message = "Username or password incorrect";
            throw new ValidatorException(new FacesMessage(message));
        } else {
            // password is valid, store user into session and mark logged in.
            this.myUser = myUser;
        }

    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoResultException ex) {
        String message = "Username or password incorrect";
        throw new ValidatorException(new FacesMessage(message));
    }

}
4

1 に答える 1

1

が呼び出されるthis.password前に正しく設定されていますか? 両方のvalidatePassword()の初期値を調べて、それらが一致していることを確認しましたか?inputTextcreateUser()validatePassword()

パスワードをハッシュするこの方法は安全ではありません。ハッシュ関数の出力で衝突が発生するため、実行する反復が多いほど、結果のハッシュに含まれるエントロピーが少なくなります。元のパスワードと同じレベルの予測不可能性を維持するには、ハッシュの各ラウンドにパスワードを追加する必要があります。

これを行う最善の方法は、scrypt や bcrypt などの既存のパスワード ハッシュ ライブラリ、またはほとんどの Java ランタイムに組み込まれている PBKDF2 などのキー派生関数を少なくとも使用することです。

于 2013-11-27T00:06:51.287 に答える