安全地创建和存储密码
幾乎每次涉及用戶配置文件時,都必須管理用戶憑據,從而能夠創建和存儲用戶密碼。 通常應該使用散列密碼和鹽分密碼來準備數據庫公開和通過使用Rainbow表進行散列反轉的密碼。
但是,找到以明文形式存儲的密碼并不少見(很不幸)(我們將跳過一些必須努力學習正確操作方法的大公司名單)。 當具有未加密,未哈希和未加鹽的密碼的數據庫泄漏時,后果很明顯……..第二種最糟糕的方法是使用哈希但未加鹽的密碼。 在這種情況下彩虹表或哈希逆轉喜歡在網絡上的服務這個或這是巨大的幫助。 最后,第三種最糟糕的方法是僅依靠加密記錄-一旦密鑰或解密數據庫泄露,游戲就結束了!
那么怎么做對呢? 簡單的答案是:將PBKDF2WithHmacSHA1與鹽值一起使用。 例如,可以在此處找到如何使用它的示例。 該實現看起來很成熟,但是很復雜。 如果您只是想了解鹽腌密碼的概念,則可能需要查看以下演示代碼:
public static final String HASH_ALGORITHM = "SHA-256"; public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");private static final char[] PASSWORD_CHARS = new char[]{'!', '@', '#', '$', '%', '&', '*', '(', ')', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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'}; public String getRandomString(final int length) {/** Don't try to seed SecureRandom yourself unless you know * what you are doing! * @see Randomly failed! Weaknesses in Java Pseudo Random Number Generators (PRNGs).*/ SecureRandom secureRandom = new SecureRandom(); StringBuilder sb = new StringBuilder(length);int position = 0;// create a random string of the requested length from a set of allowed charsfor (int i = 0; i < length; i++ ) {position = secureRandom.nextInt(PASSWORD_CHARS.length);sb.append(PASSWORD_CHARS[position]);}return sb.toString();}public static byte[] createPasswordHash(final String password,final String salt) {byte[] result = null;try {MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);digest.update(salt.getBytes(DEFAULT_CHARSET));digest.update(password.getBytes(DEFAULT_CHARSET));result = digest.digest();} catch (NoSuchAlgorithmException e) {// TODO Logging}return result;}public static boolean checkPassword(final User user, final String password) {boolean result = false;String storedPasswordHash = user.getPwHash();String salt = user.getSalt();byte[] checkPasswordHashBytes = createPasswordHash(password, salt);String checkPasswordHash = encodeBase64(checkPasswordHashBytes); // for simplicity let's say we use Base64if (checkPasswordHash != null && storedPasswordHash != null&& checkPasswordHash.equals(storedPasswordHash)) {result = true;}return result;}該代碼期望某種帶有pwHash和salt字段的用戶對象(這兩個字段都不敏感!)來存儲必要的信息。 可以安全地保留此User對象(以防萬一沒有其他敏感數據鏈接到該對象)。 即使數據庫泄漏,攻擊者也必須蠻力地使用密碼和鹽的組合,或者為鹽腌的密碼計算出彩虹表。 請注意,該彩虹表不能與帶有不同鹽的相同密碼重復使用! 這意味著,使用隨機選擇的鹽,即使密碼保持不變,攻擊者也將需要彩虹表來反轉每種鹽的哈希函數。
上面的代碼保持盡可能簡單。 例如,getRandomString可以重新用于創建鹽值,并可能在注冊過程中用于生成臨時密碼。 但是請記住,此代碼遠非在生產環境中可用!
最后一些注意事項:確保使用足夠長的鹽,防止鹽重用,并使用強大的算法進行哈希處理!
翻譯自: https://www.javacodegeeks.com/2013/08/safely-create-and-store-passwords.html
總結
以上是生活随笔為你收集整理的安全地创建和存储密码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 抛出异常–缓慢而丑陋
- 下一篇: 处理缓慢的资源泄漏