[英]Regenerating SHA-1 hash not matching stored database hash
我正在嘗試通過鍵擴展結合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));
}
}
您確定在調用validatePassword()
之前正確設置了this.password
嗎? 您是否在createUser()
和validatePassword()
中都檢查了inputText
的初始值,以確保它們匹配?
這種散列密碼的方法並不安全。 由於哈希函數輸出中的沖突,您執行的迭代次數越多,生成的哈希將包含的熵越少。 為了保持原始密碼中相同級別的不可預測性,您需要將密碼添加到每一輪哈希中。
最好的方法是使用現有的密碼哈希庫(例如scrypt或bcrypt)或至少一個密鑰派生函數(例如PBKDF2),該函數已內置在大多數Java運行時中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.