生成具有最低特殊字符要求的Java安全随机密码

生成具有最低特殊字符要求的Java安全随机密码,第1张

生成具有最低特殊字符要求的Java安全随机密码

我最近了解了Passay。它在PasswordGenerator类中提供所需的必需功能。它会随机生成满足以下要求的密码,这些密码类似于使用CharacterRules而不是我下面所做的PasswordCharacterSets所写的内容。它不保留用于随机字符插入的未使用索引的列表,而只是在插入符合要求的字符后才重新洗改字符缓冲区。

以下是以前遗留下来的内容,如果您的许可允许,我建议您使用Passay,否则此代码应该可以正常工作,并详细说明了为什么生成的密码具有极高的密码强度

我最终两次编写了这段代码。曾经获得随机字符结果,但事实证明,字符的分布取决于字符集的大小(哇!)。我重写了它,现在您应该只复制/粘贴代码并将Main.java更改为所需的字符集。尽管可以采取不同的方法,但我认为这是获得正确结果的相对简单的方法,我鼓励重用,评论,批评和周密的编辑。

PasswordGenerator代码的控件如下:

  • 最小/最大长度 :使用随机数设置
  • PasswordCharacterSet :假定传递给PasswordGenerator的所有PasswordCharacterSet都由唯一字符集组成,如果不是,则随机字符将朝着重复字符倾斜。
  • PasswordCharacterSet最小字符 :用于此字符集的最小字符。

实际密码生成的主要位:

  • 随机性 :我们使用的是SecureRandom,它由加密功能强的PRNG支持,而不是不是由Random类支持。
  • 密码的随机字符顺序 :pw char数组的所有索引均添加到剩余索引数组中。当我们调用addRandomCharacters时,它会随机删除索引,然后使用删除的索引填充数组。
  • 随机字符 :在addRandomCharacters中,从我们正在使用的字符索引中选择一个随机索引,并将其添加到pw数组中。
  • 设置每种类型 的最小字符数:我们只需首先确定最小字符数即可。我们从每个字符集中选择最小数量的随机值,然后继续。
  • 剩余字符的随机分布 :设置最小值后,我们希望使其余字符在所有字符集中随机分布。所有字符都添加到单个数组中。其余的插槽使用与先前字符集相同的策略填充。

密码复杂度的描述:密码复杂度通常用熵来谈论。以下是您的键空间的可能数量:

计算可能性数的方式至少有一个大写字母字符(26个中的一个),一个小写字母字符(26个中的一个),一个数字(10个中的一个)和一个特殊字符(32个中的一个),这是您计算可能性的方式是每个字符的可能性数乘以字符数,因为它们被随机放置在字符串中。因此,我们知道其中四个字符的可能性是:

Required Characters = 26*26*10*32=216,320

其余所有角色每个都有94(26 + 26 + 10 + 32)个可能性

我们的计算是:

Characters  Possibilities      Bits of Entropy10 chars    216,320*94^6  = 149,232,631,038,033,920  ~2^5711 chars    216,320*94^7  = 14,027,867,317,575,188,480          ~2^6312 chars    216,320*94^8  = 1,318,619,527,852,067,717,120       ~2^7013 chars    216,320*94^9  = 123,950,235,618,094,365,409,280     ~2^7614 chars    216,320*94^10 = 11,651,322,148,100,870,348,472,320  ~2^83

考虑到这一点,如果您想要最安全的密码,则应始终选择尽可能多的字符,在这种情况下为14。

Main.java

package org.redtown.pw;import java.util.EnumSet;import java.util.HashSet;import java.util.Set;import org.redtown.pw.PasswordGenerator.PasswordCharacterSet;public class Main {    public static void main(String[] args) {        Set<PasswordCharacterSet> values = new HashSet<PasswordCharacterSet>(EnumSet.allOf(SummerCharacterSets.class));        PasswordGenerator pwGenerator = new PasswordGenerator(values, 10, 14);        for(int i=0; i < 10; ++i) { System.out.println(pwGenerator.generatePassword());        }    }    private static final char[] ALPHA_UPPER_CHARACTERS = { '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' };    private static final char[] ALPHA_LOWER_CHARACTERS = { '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' };    private static final char[] NUMERIC_CHARACTERS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };    private static final char[] SPECIAL_CHARACTERS = { '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', '\', '|', ';', ':', ''', '"', ',', '<', '.', '>', '/', '?' };    private enum SummerCharacterSets implements PasswordCharacterSet {        ALPHA_UPPER(ALPHA_UPPER_CHARACTERS, 1),        ALPHA_LOWER(ALPHA_LOWER_CHARACTERS, 1),        NUMERIC(NUMERIC_CHARACTERS, 1),        SPECIAL(SPECIAL_CHARACTERS, 1);        private final char[] chars;        private final int minUsage;        private SummerCharacterSets(char[] chars, int minUsage) { this.chars = chars; this.minUsage = minUsage;        }        @Override        public char[] getCharacters() { return chars;        }        @Override        public int getMinCharacters() { return minUsage;        }    }}

PasswordGenerator.java

package org.redtown.pw;import java.security.SecureRandom;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Collections;import java.util.List;import java.util.Random;public class PasswordGenerator {    private final List<PasswordCharacterSet> pwSets;    private final char[] allCharacters;    private final int minLength;    private final int maxLength;    private final int presetCharacterCount;    public PasswordGenerator(Collection<PasswordCharacterSet> origPwSets, int minLength, int maxLength) {        this.minLength = minLength;        this.maxLength = maxLength;        // Make a copy of the character arrays and min-values so they cannot be changed after initialization        int pwCharacters = 0;        int preallocatedCharacters = 0;        List<PasswordCharacterSet> pwSets = new ArrayList<PasswordCharacterSet>(origPwSets.size());        for(PasswordCharacterSet origpwSet : origPwSets) { PasswordCharacterSet newPwSet = new PwSet(origpwSet); pwSets.add(newPwSet); pwCharacters += newPwSet.getCharacters().length; preallocatedCharacters += newPwSet.getMinCharacters();        }        this.presetCharacterCount = preallocatedCharacters;        this.pwSets = Collections.unmodifiableList(pwSets);        if (minLength < presetCharacterCount) { throw new IllegalArgumentException("Combined minimum lengths "         + presetCharacterCount         + " are greater than the minLength of " + minLength);        }        // Copy all characters into single array so we can evenly access all members when accessing this array        char[] allChars = new char[pwCharacters];        int currentIndex = 0;        for(PasswordCharacterSet pwSet : pwSets) { char[] chars = pwSet.getCharacters(); System.arraycopy(chars, 0, allChars, currentIndex, chars.length); currentIndex += chars.length;        }        this.allCharacters = allChars;    }    public char[] generatePassword() {        SecureRandom rand = new SecureRandom();        // Set pw length to minLength <= pwLength <= maxLength        int pwLength = minLength + rand.nextInt(maxLength - minLength + 1);        int randomCharacterCount = pwLength - presetCharacterCount;        // Place each index in an array then remove them randomly to assign positions in the pw array        List<Integer> remainingIndexes = new ArrayList<Integer>(pwLength);        for(int i=0; i < pwLength; ++i) { remainingIndexes.add(i);        }        // Fill pw array        char[] pw = new char[pwLength];        for(PasswordCharacterSet pwSet : pwSets) { addRandomCharacters(pw, pwSet.getCharacters(), pwSet.getMinCharacters(), remainingIndexes, rand);        }        addRandomCharacters(pw, allCharacters, randomCharacterCount, remainingIndexes, rand);        return pw;    }    private static void addRandomCharacters(char[] pw, char[] characterSet, int numCharacters, List<Integer> remainingIndexes, Random rand) {        for(int i=0; i < numCharacters; ++i) { // Get and remove random index from the remaining indexes int pwIndex = remainingIndexes.remove(rand.nextInt(remainingIndexes.size())); // Set random character from character index to pwIndex int randCharIndex = rand.nextInt(characterSet.length); pw[pwIndex] = characterSet[randCharIndex];        }    }    public static interface PasswordCharacterSet {        char[] getCharacters();        int getMinCharacters();    }        private static final class PwSet implements PasswordCharacterSet {        private final char[] chars;        private final int minChars;        public PwSet(PasswordCharacterSet pwSet) { this.minChars = pwSet.getMinCharacters(); char[] pwSetChars = pwSet.getCharacters(); // Defensive copy this.chars = Arrays.copyOf(pwSetChars, pwSetChars.length);        }        @Override        public char[] getCharacters() { return chars;        }        @Override        public int getMinCharacters() { return minChars;        }    }}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5003467.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-15
下一篇 2022-11-14

发表评论

登录后才能评论

评论列表(0条)

保存