代码之家  ›  专栏  ›  技术社区  ›  Brian Matthews

需要安全密码生成器建议[关闭]

  •  15
  • Brian Matthews  · 技术社区  · 15 年前

    有人能推荐一个安全的密码生成器,可以在Apache或LGPL许可证下使用吗?

    7 回复  |  直到 12 年前
        1
  •  18
  •   user21767    13 年前

    我不会太担心生成难以置信的强一次性密码。让密码变长,这不应该是蛮力授予你的问题,限制密码的有效时间。如果密码仅在1小时内有效,那么如果密码保持未使用状态,则不会出现问题。在这段时间内,不太可能有人会用暴力破解它。

    同样重要的是,您只允许一次性密码工作一次。这样,如果密码被截取,用户将注意到一次性密码何时过期,并可以采取适当的操作。

    我要去阿帕奇公地 RandomStringUtils 密码是10-15个字母和数字。

    …尽管这一直是一个关于你有多偏执的问题。对于一个普通的Web应用程序来说,这个解决方案是很好的,但对于银行来说还不够好…

        2
  •  6
  •   Matthew Vines    15 年前

    它在.NET中,但转换起来应该很简单。对大多数人来说可能有点太多了,但这是我在应用程序中经常使用的一种入门级实现。这是我一段时间前发现的一个实现,并做了一些修改,我记不起原来的作者,但我会做一个快速的搜索,看看我是否能给他适当的学分。

    public static string GenerateRandomString(int minLength, int maxLength, int minLCaseCount, int minUCaseCount, int minNumCount, int minSpecialCount)
            {
                char[] randomString;
    
                const string LCaseChars = "abcdefgijkmnopqrstwxyz";
                const string UCaseChars = "ABCDEFGHJKLMNPQRSTWXYZ";
                const string NumericChars = "23456789";
                const string SpecialChars = "*$-+?_&=!%{}/";
    
                Hashtable charGroupsUsed = new Hashtable();
                charGroupsUsed.Add("lcase", minLCaseCount);
                charGroupsUsed.Add("ucase", minUCaseCount);
                charGroupsUsed.Add("num", minNumCount);
                charGroupsUsed.Add("special", minSpecialCount);
    
                // Because we cannot use the default randomizer, which is based on the
                // current time (it will produce the same "random" number within a
                // second), we will use a random number generator to seed the
                // randomizer.
    
                // Use a 4-byte array to fill it with random bytes and convert it then
                // to an integer value.
                byte[] randomBytes = new byte[4];
    
                // Generate 4 random bytes.
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                rng.GetBytes(randomBytes);
    
                // Convert 4 bytes into a 32-bit integer value.
                int seed = (randomBytes[0] & 0x7f) << 24 |
                            randomBytes[1] << 16 |
                            randomBytes[2] << 8 |
                            randomBytes[3];
    
                // Create a randomizer from the seed.
                Random random = new Random(seed);
    
                // Allocate appropriate memory for the password.
                if (minLength < maxLength)
                {
                    randomString = new char[random.Next(minLength, maxLength + 1)];
                }
                else
                {
                    randomString = new char[minLength];
                }
    
                int requiredCharactersLeft = minLCaseCount + minUCaseCount + minNumCount + minSpecialCount;
    
                // Build the password.
                for (int i = 0; i < randomString.Length; i++)
                {
                    string selectableChars = "";
    
                    // if we still have plenty of characters left to acheive our minimum requirements.
                    if (requiredCharactersLeft < randomString.Length - i)
                    {
                        // choose from any group at random
                        selectableChars = LCaseChars + UCaseChars + NumericChars + SpecialChars;
                    }
                    else // we are out of wiggle room, choose from a random group that still needs to have a minimum required.
                    {
                        // choose only from a group that we need to satisfy a minimum for.
                        foreach (DictionaryEntry charGroup in charGroupsUsed)
                        {
                            if ((int)charGroup.Value > 0)
                            {
                                switch (charGroup.Key.ToString())
                                {
                                    case "lcase":
                                        selectableChars += LCaseChars;
                                        break;
                                    case "ucase":
                                        selectableChars += UCaseChars;
                                        break;
                                    case "num":
                                        selectableChars += NumericChars;
                                        break;
                                    case "special":
                                        selectableChars += SpecialChars;
                                        break;
                                }
                            }
                        }
                    }
    
                    // Now that the string is built, get the next random character.
                    char nextChar = selectableChars[random.Next(0, selectableChars.Length - 1)];
    
                    // Tac it onto our password.
                    randomString[i] = nextChar;
    
                    // Now figure out where it came from, and decrement the appropriate minimum value.
                    if (LCaseChars.Contains(nextChar))
                    {
                        charGroupsUsed["lcase"] = (int)charGroupsUsed["lcase"] - 1;
                        if ((int)charGroupsUsed["lcase"] >= 0)
                        {
                            requiredCharactersLeft--;
                        }
                    }
                    else if (UCaseChars.Contains(nextChar))
                    {
                        charGroupsUsed["ucase"] = (int)charGroupsUsed["ucase"] - 1;
                        if ((int)charGroupsUsed["ucase"] >= 0)
                        {
                            requiredCharactersLeft--;
                        }
                    }
                    else if (NumericChars.Contains(nextChar))
                    {
                        charGroupsUsed["num"] = (int)charGroupsUsed["num"] - 1;
                        if ((int)charGroupsUsed["num"] >= 0)
                        {
                            requiredCharactersLeft--;
                        }
                    }
                    else if (SpecialChars.Contains(nextChar))
                    {
                        charGroupsUsed["special"] = (int)charGroupsUsed["special"] - 1;
                        if ((int)charGroupsUsed["special"] >= 0)
                        {
                            requiredCharactersLeft--;
                        }
                    }
                }
                return new string(randomString);
            }
    

    编辑

    我想我从发布的代码开始 http://www.obviex.com/Samples/Password.aspx . 尽管代码现在还有一些特性。

        3
  •  4
  •   Dave    15 年前

    下面是一个使用commons的例子。它创建一个8到20个字符长的字母数字密码。

    public String getRandomPassword() {
        StringBuffer password = new StringBuffer(20);
        int next = RandomUtils.nextInt(13) + 8;
        password.append(RandomStringUtils.randomAlphanumeric(next));
        return password.toString();
    }
    

    更新 randomutils.nextint返回一个介于0(含)和指定值(不含)之间的数字,因此若要获取介于8到20个字符(含)之间的值,参数值应为13。我已经更正了上面的代码。

    更新 正如下面的注释中所指出的,可以不使用StringBuffer编写它。以下是修改后的单行版本:

    return RandomStringUtils.randomAlphanumeric(RandomUtils.nextInt(13) + 8);
    
        4
  •  4
  •   eugene    12 年前

    对于那些感兴趣的人来说,这里是马修的代码,转换为Java

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    public class PasswordGenerator {
    
    public static String GenerateRandomString(int minLength, int maxLength, int minLCaseCount,     int minUCaseCount, int minNumCount, int minSpecialCount)
    {
        char[] randomString;
    
        String LCaseChars = "abcdefgijkmnopqrstwxyz";
        String UCaseChars = "ABCDEFGHJKLMNPQRSTWXYZ";
        String NumericChars = "23456789";
        String SpecialChars = "*$-+?_&=!%{}/";
    
        Map<String,Integer> charGroupsUsed = new HashMap<String,Integer>();
        charGroupsUsed.put("lcase", minLCaseCount);
        charGroupsUsed.put("ucase", minUCaseCount);
        charGroupsUsed.put("num", minNumCount);
        charGroupsUsed.put("special", minSpecialCount);
    
        // Because we cannot use the default randomizer, which is based on the
        // current time (it will produce the same "random" number within a
        // second), we will use a random number generator to seed the
        // randomizer.
    
        // Use a 4-byte array to fill it with random bytes and convert it then
        // to an integer value.
        byte[] randomBytes = new byte[4];
    
        // Generate 4 random bytes.
        new Random().nextBytes(randomBytes);
    
        // Convert 4 bytes into a 32-bit integer value.
        int seed = (randomBytes[0] & 0x7f) << 24 |
                    randomBytes[1] << 16 |
                    randomBytes[2] << 8 |
                    randomBytes[3];
    
        // Create a randomizer from the seed.
        Random random = new Random(seed);
    
        // Allocate appropriate memory for the password.
        int randomIndex = -1;
        if (minLength < maxLength)
        {
            randomIndex = random.nextInt((maxLength-minLength)+1)+minLength;
            randomString = new char[randomIndex];
        }
        else
        {
            randomString = new char[minLength];
        }
    
        int requiredCharactersLeft = minLCaseCount + minUCaseCount + minNumCount + minSpecialCount;
    
        // Build the password.
        for (int i = 0; i < randomString.length; i++)
        {
            String selectableChars = "";
    
            // if we still have plenty of characters left to acheive our minimum requirements.
            if (requiredCharactersLeft < randomString.length - i)
            {
                // choose from any group at random
                selectableChars = LCaseChars + UCaseChars + NumericChars + SpecialChars;
            }
            else // we are out of wiggle room, choose from a random group that still needs to have a minimum required.
            {
                // choose only from a group that we need to satisfy a minimum for.
                for(Map.Entry<String, Integer> charGroup : charGroupsUsed.entrySet())
                {
                    if ((int)charGroup.getValue() > 0)
                    {
                        if("lcase".equals(charGroup.getKey()) ){
                            selectableChars += LCaseChars;
                        }
                        else if("ucase".equals(charGroup.getKey())){
                            selectableChars += UCaseChars;
                        }
                        else if("num".equals(charGroup.getKey())){
                            selectableChars += NumericChars;
                        }
                        else if("special".equals(charGroup.getKey())){
                            selectableChars += SpecialChars;
                        }
                    }
                }
            }
    
            // Now that the string is built, get the next random character.
            randomIndex = random.nextInt((selectableChars.length())-1);
            char nextChar = selectableChars.charAt(randomIndex);
    
            // Tac it onto our password.
            randomString[i] = nextChar;
    
            // Now figure out where it came from, and decrement the appropriate minimum value.
            if (LCaseChars.indexOf(nextChar) > -1)
            {
                charGroupsUsed.put("lcase",charGroupsUsed.get("lcase") - 1);
                if (charGroupsUsed.get("lcase") >= 0)
                {
                    requiredCharactersLeft--;
                }
            }
            else if (UCaseChars.indexOf(nextChar) > -1)
            {
                charGroupsUsed.put("ucase",charGroupsUsed.get("ucase") - 1);
                if (charGroupsUsed.get("ucase") >= 0)
                {
                    requiredCharactersLeft--;
                }
            }
            else if (NumericChars.indexOf(nextChar) > -1)
            {
                charGroupsUsed.put("num", charGroupsUsed.get("num") - 1);
                if (charGroupsUsed.get("num") >= 0)
                {
                    requiredCharactersLeft--;
                }
            }
            else if (SpecialChars.indexOf(nextChar) > -1)
            {
                charGroupsUsed.put("special",charGroupsUsed.get("special") - 1);
                if (charGroupsUsed.get("special") >= 0)
                {
                    requiredCharactersLeft--;
                }
            }
        }
        return new String(randomString);
    }
    
    }
    

    单元测试

    import org.junit.Test;
    
    public class PasswordGeneratorTest {
    
    @Test
    public void testPasswordCreation(){
    
        System.out.println(PasswordGenerator.GenerateRandomString(8,25,3,1,1,1));
    
    }
    
    }
    
        5
  •  0
  •   Jherico    15 年前

    Password Safe 是开放源代码(在艺术许可证下),包括密码生成代码。

        6
  •  0
  •   Reese Moore    15 年前

    您可以使用随机和内置的MessageDigest实现轻松实现它。

    import java.util.Random;
    import java.security.*;
    import java.math.*;
    
    public class RandPassGen {
        public static String genPass( int chars ) {
            Random r = new Random();
            MessageDigest md = null;
    
            try {
                md = MessageDigest.getInstance("MD5");
            } catch ( NoSuchAlgorithmException e ) {
                System.out.println( "Unsupported Algorithm!" );
                return null;
            }
    
            byte[] entropy = new byte[1024];
            r.nextBytes(entropy);
            md.update( entropy , 0, 1024 );
    
            return new BigInteger(1, md.digest()).toString(16).substring(0, chars);
        }
    
        public static void main( String[] av ) {
            Integer chars = Integer.valueOf(av[0]);
            if ((chars < 0) || (chars > 32)) {
                System.out.println( "Generate between 0 and 32 characters." );
                return;
            }
    
            System.out.println( genPass( chars ) ); 
        }
    }
    
        7
  •  0
  •   Ryan    12 年前

    我添加了一个类似C/Java版本的Golang实现。它在Apache2.0下可用。源位于此处:

    https://github.com/deftlabs/dlshared/blob/master/password_utils.go

    推荐文章