java存储过程示例_安全密码存储–请勿做的事和Java示例

java存储过程示例

安全存储密码的重要性
作为软件开发人员,我们最重要的职责之一就是保护用户的个人信息。 如果没有我们应用程序的技术知识,用户别无选择,只能相信我们正在履行这一责任。 令人遗憾的是,在密码方面,软件开发社区的记录不一。
尽管不可能构建一个100%安全的系统,但幸运的是,我们可以采取一些简单的步骤来使用户的密码足够安全,以使潜在的黑客能够寻找更容易的猎物。
如果您不希望所有背景知识,请随时跳到下面的Java SE示例
不要
首先,让我们快速讨论一些在构建需要身份验证的应用程序时不应该做的事情:
  • 除非确实需要,否则不要存储身份验证数据。 这似乎是一个解决方案,但是在开始构建用户凭据数据库之前,请考虑让其他人来处理它。 如果您要构建公共应用程序,请考虑使用OAuth提供程序,例如GoogleFacebook 。 如果要构建内部企业应用程序,请考虑使用任何可能已经存在的内部身份验证服务,例如公司LDAP或Kerberos服务。 无论是公共应用程序还是内部应用程序,您的用户都将无需记住其他用户ID和密码,这将是不胜枚举的选择,而且数据库供黑客攻击的少得多。
  • 如果您必须存储身份验证数据,那么就Gosling而言,请不要以明文形式存储密码 。 这应该很明显,但是值得一提。 让我们至少让黑客大汗淋漓。
  • 除非您确实需要检索明文密码,否则不要使用双向加密。 仅当您使用他们的凭据代表他们与外部系统交互时,才需要知道他们的明文密码。 即使这样,您最好还是让用户直接通过该系统进行身份验证。 为了清楚起见, 您无需使用用户的原始明文密码在应用程序中执行身份验证 。 稍后我将对此进行更详细的介绍,但是在执行身份验证时,您将对用户输入的密码应用加密算法,并将其与您存储的加密密码进行比较。
  • 不要使用像MD5这样的过时的哈希算法 。 老实说,用MD5散列密码实际上是没有用的。 这是MD5哈希密码: 569a70c2ccd0ac41c9d1637afe8cd932 。 转到http://www.md5hacker.com/ ,您可以在几秒钟内将其解密。
  • 不要提出自己的加密方案。 世界上有一些杰出的加密专家,能够胜过黑客并设计出新的加密算法。 我不是其中之一,很可能您也不是。 如果黑客可以访问您的用户数据库,那么他们也可能也可以获取您的代码。 除非您发明了PBKDF2bcrypt的下一个伟大的后继产品,否则它们将疯狂地破解,因为它们会Swift破解所有用户的密码并将其发布在Darknet上
Dos
好的,对不应该做的事情进行充分的讲授。 这是您需要重点关注的事项:
  • 选择一种单向加密算法。 如前所述,一旦您加密并存储了用户密码,就无需再知道真实的价值了。 用户尝试进行身份验证时,只需将相同的算法应用于他们输入的密码,然后将其与您存储的加密密码进行比较。
  • 使加密速度尽可能慢,以使应用程序可以容忍 。 任何现代的密码加密算法都应允许您提供增加密码加密所需时间的参数(即,在PBKDF2中,指定迭代次数)。 为什么慢的好? 您的用户不会注意到是否需要花费额外的100毫秒来加密密码,但是尝试进行暴力攻击的黑客会在数十亿次运行该算法时注意到这种差异。
  • 选择一个众所周知的算法 。 美国国家标准技术研究院(NIST) 建议使用PBKDF2作为密码。 bcrypt是一种流行且已建立的替代方法,而scrypt是一种相对较新的算法,已广受欢迎。 所有这些都是受欢迎的原因:它们很好。
PBKDF2
在向您展示一些具体代码之前,让我们先谈谈为什么PBKDF2是加密密码的理想选择:
  • 由NIST推荐。 特殊出版物800-132的 5.3节建议使用PBKDF2加密密码。 安全官员会喜欢的。
  • 可调式按键伸展功能可以克服蛮力攻击密钥扩展的基本思想是,在将哈希算法应用于密码之后,您将继续对结果多次应用同一算法(迭代计数)。 如果黑客试图破解您的密码,那么这将大大增加尝试数十亿种可能的密码所需的时间。 如前所述,速度越慢越好。 PBKDF2允许您指定要应用的迭代次数,从而使其尽可能慢。
  • 一种必需的盐,可用来克服彩虹表攻击并防止与其他用户的冲突。 是每个用户唯一的随机生成的位序列,并作为哈希的一部分添加到用户密码中。 通过使结果的预先计算的列表不可行,可以防止彩虹表攻击 。 而且,由于每个用户都有自己的名字,即使两个用户使用相同的密码,加密值也将不同。 关于是否应将盐与加密密码分开存放的地方,存在许多相互矛盾的信息。 由于PBKDF2中的密钥扩展已经保护了我们免受暴力攻击,因此我认为没有必要隐藏盐。 NIST SP 800-132的3.1节还将盐定义为“非秘密的二进制值”,这就是我所要遵循的。
  • Java SE 6的一部分 。 无需其他库。 这对于在具有限制性开放源代码策略的环境中工作的人员特别有吸引力。
最后是一个具体的例子
好的,这是一些使用PBKDF2加密密码的代码。 仅需要Java SE 6。
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class PasswordEncryptionService {

 public boolean authenticate(String attemptedPassword, byte[] encryptedPassword, byte[] salt)
   throws NoSuchAlgorithmException, InvalidKeySpecException {
  // Encrypt the clear-text password using the same salt that was used to
  // encrypt the original password
  byte[] encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt);

  // Authentication succeeds if encrypted password that the user entered
  // is equal to the stored hash
  return Arrays.equals(encryptedPassword, encryptedAttemptedPassword);
 }

 public byte[] getEncryptedPassword(String password, byte[] salt)
   throws NoSuchAlgorithmException, InvalidKeySpecException {
  // PBKDF2 with SHA-1 as the hashing algorithm. Note that the NIST
  // specifically names SHA-1 as an acceptable hashing algorithm for PBKDF2
  String algorithm = "PBKDF2WithHmacSHA1";
  // SHA-1 generates 160 bit hashes, so that's what makes sense here
  int derivedKeyLength = 160;
  // Pick an iteration count that works for you. The NIST recommends at
  // least 1,000 iterations:
  // http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
  // iOS 4.x reportedly uses 10,000:
  // http://blog.crackpassword.com/2010/09/smartphone-forensics-cracking-blackberry-backup-passwords/
  int iterations = 20000;

  KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);

  SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm);

  return f.generateSecret(spec).getEncoded();
 }

 public byte[] generateSalt() throws NoSuchAlgorithmException {
  // VERY important to use SecureRandom instead of just Random
  SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

  // Generate a 8 byte (64 bit) salt as recommended by RSA PKCS5
  byte[] salt = new byte[8];
  random.nextBytes(salt);

  return salt;
 }
}
流程如下所示:
  1. 添加新用户时,请调用generateSalt() ,然后调用getEncryptedPassword() ,并存储加密的密码和盐。 不要存储明文密码。 不必担心将盐与加密的密码保存在单独的表或位置中; 如上所述,该盐是非秘密的。
  2. 对用户进行身份验证时,请从数据库中检索以前加密的密码和盐,然后将它们和他们输入的明文密码发送到authenticate() 。 如果返回true,则认证成功。
  3. 当用户更改密码时,可以安全地重用其旧版本; 您可以只用旧的盐调用getEncryptedPassword()
很容易,对吧? 如果您要构建或维护的应用程序违反了上述“禁止”之列, 帮您的用户一个忙,并使用PBKDF2或bcrypt之类的东西。 帮助他们,Obi-Wan开发人员,您是他们唯一的希望。

翻译自: https://www.javacodegeeks.com/2012/05/secure-password-storage-donts-dos-and.html

java存储过程示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值