Java 密码加密

Java 密码加密,java,encryption,cryptography,password-encryption,Java,Encryption,Cryptography,Password Encryption,我正在尝试编写一个密码加密类,可以用来加密和存储用户密码。我想确保我做得正确。这段代码运行良好,似乎生成了一个加密密码,但我想在这里发布它以获得一些反馈。对我来说,这是相当复杂的,我知道任何加密技术都很容易犯错误,而没有意识到你在犯错误 这是我的密码: public CipherHandler { public String encryptPassword(char[] plaintext, String encoding) throws Exception {

我正在尝试编写一个密码加密类,可以用来加密和存储用户密码。我想确保我做得正确。这段代码运行良好,似乎生成了一个加密密码,但我想在这里发布它以获得一些反馈。对我来说,这是相当复杂的,我知道任何加密技术都很容易犯错误,而没有意识到你在犯错误

这是我的密码:

    public CipherHandler {

        public String encryptPassword(char[] plaintext, String encoding) throws Exception {

            MessageDigest msgDigest = null;
            String hashValue = null;

            /* Convert char array plaintext to byte array */
            byte[] b = new byte[plaintext.length << 1];
            for (int i = 0; i < plaintext.length; i++) {
                b[i] = (byte) plaintext[i]; //will this work regardless of encoding?
            }

            try {
                msgDigest = MessageDigest.getInstance("SHA-256");
                msgDigest.update(b);
                byte rawByte[] = msgDigest.digest();
                hashValue = (new BASE64Encoder()).encode(rawByte);
            } catch (NoSuchAlgorithmException e) {
                System.out.println("No Such Algorithm Exists");
            }

            System.out.println(hashValue);
            return hashValue;
        }            
    }
由于这是我第一次尝试,我想我忽略了一些东西。我对任何建议或意见都感兴趣。不过,我确实有几个具体问题:

  • 当我将char[]转换为byte[]时,我不相信我这样做是正确的。我如何知道使用哪种编码?在这里,我加入了“UTF-8”,主要是作为占位符,但我担心在某些情况下这可能会失败

  • 我已经读到我应该在密码被消化后使用salt和迭代,但我不知道如何做到这一点。有人能给我一些建议吗

  • 我正在使用SHA-256。这是建议的算法吗?我也读过MD5。是否有一种算法更适合密码加密


  • 谢谢你的帮助。我很感激

    密码通常通过散列而不是加密来存储

    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] hash = md.digest(password.getBytes("UTF-8"));
    
    然后将新生成的哈希值与存储在数据库中或任何地方的哈希值进行比较


    对密码加盐也是一个好主意——这是一个明文值,在对密码进行散列之前,您可以将其附加到密码中。这使得有人更难执行离线暴力攻击。

    MD5已经死了,UTF-8应该是你最不担心的了。阅读
    当然,根据您对密码进行加密的目的(取决于您的目标受众类型),如果您在security stackexchange中搜索足够长的时间,您将很快找到您的挑战的完整答案。


    就我的0.02美元

    见。SHA-256不适合密码哈希,你需要一个盐。盐是不够的,你还需要一个昂贵的哈希。最好是scrypt、bcrypt或PBKDF2,但迭代SHA-2也可以。单次迭代SHA-2不行,谢谢。您发布的代码与我的代码有何不同?您使用的是一个字符串密码(大概是),我读过它是个坏主意,因为它们是不可变的,可以在内存中保存一段时间。我使用的是char[],这需要更多的步骤才能转换成byte[],但是当我比较这两个代码段时,它们都使用了MessageDigest变量并对该变量进行了摘要。出于返回目的,我将加密(散列)密码转换回字符串,但它们看起来基本相同。我错过什么了吗?谢谢我同意你的看法。有人能建议我怎么做吗?我被困在这一点上。这显示了某种方式,这有一个完整的示例使用byte[]salt=new byte[16],new Random()。nextBytes(salt)生成salt-您可以使用SecureRandom,但这并没有增加多少,因为salt不是秘密。然后使用System.arraycopy将salt和密码复制到数组中,对其进行散列,然后将其删除。
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] hash = md.digest(password.getBytes("UTF-8"));