CodeProject - A C# Password Generator(一个C#密码产生器)

原作者:Kevin Stewart

文章出处:http://www.codeproject.com/csharp/pwdgen.asp<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


Introduction

This article illustrates how to create a very simple password generator using C#. Password generators are useful in many applications:

  • Registration/membership systems for Web sites

  • Auto-creation of passwords according to a specified rule

  • Securing application-specific data

介绍

 

这篇文章举例说明怎么使用C#来创建一个简单的密码产生器。密码产生器在很多软件中都很有用:

  • 网站的 注册/会员 系统

  • 根据特定规则的密码自动创建器

  • 为软件的特定数据提供保护

The PasswordGenerator class is fairly simple. It exposes several properties that control how the password will be generated.

  • Exclusions: Specifies the set of characters to exclude in password generation.

  • Minimum: Specifies the minimum length of the generated password.

  • Maximum: Specifies the maximum length of the generated password.

  • ConsecutiveCharacters: Controls generation of consecutive characters in the generated password.

  • RepeatingCharacters: Controls generation of repeating characters in the generated password.

  • ExcludeSymbols: Excludes symbols from the set of characters used to generate the password

 PasswordGenerator类很简单。它使用了一些属性,这些属性控制密码怎么产生。

  • Exclusions: 指定排除在密码产生器中的特定字符集和。

  • Minimum: 指定获得密码的最小长度。

  • Maximum: 指定获得密码的最大长度。

  • ConsecutiveCharacters: 控制获得的密码是连续字符。

  • RepeatingCharacters: 控制获得的密码是使重复的字符。

  • ExcludeSymbols: 排除用来获得密码的的字符集和中的一些字符。

After setting your desired properties, call the Generate() method to create your new password.

在设置好你所需要的属性以后,调用Generate()方法来创建你的新密码:

 

None.gif namespace  WorkingCode.CodeProject.PwdGen
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
using System;
InBlock.gif    
using System.Security.Cryptography;
InBlock.gif    
using System.Text;
InBlock.gif
InBlock.gif    
public class PasswordGenerator
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public PasswordGenerator() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.Minimum               = DefaultMinimum;
InBlock.gif            
this.Maximum               = DefaultMaximum;
InBlock.gif            
this.ConsecutiveCharacters = false;
InBlock.gif            
this.RepeatCharacters      = true;
InBlock.gif            
this.ExcludeSymbols        = false;
InBlock.gif            
this.Exclusions            = null;
InBlock.gif
InBlock.gif            rng 
= new RNGCryptoServiceProvider();
ExpandedSubBlockEnd.gif        }
        
InBlock.gif        
InBlock.gif        
protected int GetCryptographicRandomNumber(int lBound, int uBound)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{   
InBlock.gif            
// Assumes lBound >= 0 && lBound < uBound
InBlock.gif            
// returns an int >= lBound and < uBound
InBlock.gif
            uint urndnum;   
InBlock.gif            
byte[] rndnum = new Byte[4];   
InBlock.gif            
if (lBound == uBound-1)  
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// test for degenerate case where only lBound can be returned
InBlock.gif
                return lBound;
ExpandedSubBlockEnd.gif            }

InBlock.gif                                                              
InBlock.gif            
uint xcludeRndBase = (uint.MaxValue -
InBlock.gif                (
uint.MaxValue%(uint)(uBound-lBound)));   
InBlock.gif            
InBlock.gif            
do 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{      
InBlock.gif                rng.GetBytes(rndnum);      
InBlock.gif                urndnum 
= System.BitConverter.ToUInt32(rndnum,0);      
ExpandedSubBlockEnd.gif            }
 while (urndnum >= xcludeRndBase);   
InBlock.gif            
InBlock.gif            
return (int)(urndnum % (uBound-lBound)) + lBound;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected char GetRandomCharacter()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{            
InBlock.gif            
int upperBound = pwdCharArray.GetUpperBound(0);
InBlock.gif
InBlock.gif            
if ( true == this.ExcludeSymbols )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                upperBound 
= PasswordGenerator.UBoundDigit;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
int randomCharPosition = GetCryptographicRandomNumber(
InBlock.gif                pwdCharArray.GetLowerBound(
0), upperBound);
InBlock.gif
InBlock.gif            
char randomChar = pwdCharArray[randomCharPosition];
InBlock.gif
InBlock.gif            
return randomChar;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        
public string Generate()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// Pick random length between minimum and maximum   
InBlock.gif
            int pwdLength = GetCryptographicRandomNumber(this.Minimum,
InBlock.gif                
this.Maximum);
InBlock.gif
InBlock.gif            StringBuilder pwdBuffer 
= new StringBuilder();
InBlock.gif            pwdBuffer.Capacity 
= this.Maximum;
InBlock.gif
InBlock.gif            
// Generate random characters
InBlock.gif
            char lastCharacter, nextCharacter;
InBlock.gif
InBlock.gif            
// Initial dummy character flag
InBlock.gif
            lastCharacter = nextCharacter = '\n';
InBlock.gif
InBlock.gif            
for ( int i = 0; i < pwdLength; i++ )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                nextCharacter 
= GetRandomCharacter();
InBlock.gif
InBlock.gif                
if ( false == this.ConsecutiveCharacters )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
while ( lastCharacter == nextCharacter )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        nextCharacter 
= GetRandomCharacter();
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
if ( false == this.RepeatCharacters )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
string temp = pwdBuffer.ToString();
InBlock.gif                    
int duplicateIndex = temp.IndexOf(nextCharacter);
InBlock.gif                    
while ( -1 != duplicateIndex )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        nextCharacter 
= GetRandomCharacter();
InBlock.gif                        duplicateIndex 
= temp.IndexOf(nextCharacter);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
if ( ( null != this.Exclusions ) )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
while ( -1 != this.Exclusions.IndexOf(nextCharacter) )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        nextCharacter 
= GetRandomCharacter();
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                pwdBuffer.Append(nextCharacter);
InBlock.gif                lastCharacter 
= nextCharacter;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
if ( null != pwdBuffer )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return pwdBuffer.ToString();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return String.Empty;
ExpandedSubBlockEnd.gif            }
    
ExpandedSubBlockEnd.gif        }

InBlock.gif            
InBlock.gif        
public string Exclusions
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.exclusionSet;  }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis.exclusionSet = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int Minimum
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.minSize; }
InBlock.gif            
set    
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
this.minSize = value;
InBlock.gif                
if ( PasswordGenerator.DefaultMinimum > this.minSize )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
this.minSize = PasswordGenerator.DefaultMinimum;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int Maximum
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.maxSize; }
InBlock.gif            
set    
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
this.maxSize = value;
InBlock.gif                
if ( this.minSize >= this.maxSize )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
this.maxSize = PasswordGenerator.DefaultMaximum;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool ExcludeSymbols
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.hasSymbols; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set    dot.gifthis.hasSymbols = value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool RepeatCharacters
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.hasRepeating; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set    dot.gifthis.hasRepeating = value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool ConsecutiveCharacters
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.hasConsecutive; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set    dot.gifthis.hasConsecutive = value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private const int DefaultMinimum = 6;
InBlock.gif        
private const int DefaultMaximum = 10;
InBlock.gif        
private const int UBoundDigit    = 61;
InBlock.gif
InBlock.gif        
private RNGCryptoServiceProvider    rng;
InBlock.gif        
private int             minSize;
InBlock.gif        
private int             maxSize;
InBlock.gif        
private bool            hasRepeating;
InBlock.gif        
private bool            hasConsecutive;
InBlock.gif        
private bool            hasSymbols;
InBlock.gif        
private string          exclusionSet;
InBlock.gif        
private char[] pwdCharArray = "abcdefghijklmnopqrstuvwxyzABCDEFG" +
InBlock.gif            
"HIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+[]{}\\|;:'\",<" + 
InBlock.gif
            ".>/?".ToCharArray();                                        
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

The previous version of this class was intended for use in a much larger project (I will be publishing articles on various components of that project soon.). Due to many factors, that code was rushed and proved to be inefficient. In fact, I wish I could go back in time and unpublish it! While this version is definitely better, there is still room for improvement. The generation algorithm can still be optimized. Also, it would be interesting to use regular expressions to both define and validate the passwords we wish to generate. I would have done this, but it's been a long time since I wrote a parser. Maybe for the next version...


这个类的前一个版本本来想用在一个更大的项目中(我会陆续发表关于这个项目的各种组成成分的文章)。由于许多因素,那个类写得太匆忙了,而且被证实是没有效率的。事实上,我希望我能回到过去,不发表它该多好!尽管这个版本明显好多了,其实还有改进的空间。密码产生算法还可以优化。如果能用正则表达式定义和验证我们得到的密码那不是很有趣嘛。我将完成这个功能,但可能会很久因为我在写一个剖析器(parser)。也许在下一个版本吧


In previous articles, I have used the NAnt tool as my build solution. Unfortunately, that team has not produced a stable release that integrates NUnit 2.0. I COULD get the source from the CVS tree, but I'm way too lazy for that. Instead, I have decided to go back to Visual Studio .NET as my development environment. I'm also getting used to test-driven development with NUnit 2.0. If you aren't using this tool for unit testing, I highly recommend you give it a try http://www.nunit.org/. Its use of attributes and reflection to specify test suites, test fixtures and tests, and is quite remarkable and easy to use. I've included my unit test fixture with the source code. Also, try the NUnit Addin for Visual Studio .NET; it's very handy for running your tests within the IDE.


在先前的文章里,我使用了NAnt工具作为我的创建方案。不幸的是,那个队伍没有发布一个稳定的版本来整合NUnit2.0。我可以从CVS树里获得源码,但我太懒没做那事。反而,我决定返回去把Visual Studio .NET作为我的开发环境。我也习惯于NUnit2.0test-driven的开发方式。如果你现在没有用这个工具来做测试,我强烈建议你去http://www.nunit.org/下载它。它使用属性和反射来指定测试套件(?),测试属性(?)和测试,而且非常不错,易于使用。我已经把我的单元测试属性(?)包含在源码中了。也可以试试用一下为Visual Studio .NET 开发的NUnit插件;这个在使用IDE做测试的时候非常方便。


The demo project is a simple Windows Forms UI that allows one to configure the password generator's properties. I must say that while VS.NET is fairly complete and powerful, I just don't like the feel of the forms designer. However, it definitely does the job.


演示程序是一个简单的Windows窗体用户界面,允许你配置密码生成器的属性。我不得不说VS.NET是这么的完善和强大,我只是不太喜欢窗体设计器的感觉。当然,它明确地完成了任务。


Many thanks to Mike Asher and Julian Roberts for their feedback on the first version of the password generator. Julian was kind enough to test the code in an ASP.NET project and confirmed that it performs much better. Also, I reverted to my old C++ bracing style just to make <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Nish happy...hope you appreciate the sacrifice! :-)


十分感谢(Many thanks,呵呵,第一次听到这种说法)Mike Asher Julian Roberts对第一版的密码产生器所作的建议。Julian十分友善地在ASP.NET项目中作了测试,证实它表现地好多了。还有,我回归了以前的C++ bracing风格,只是为了让Nish能够高兴(呵呵)希望你能赏识我的奉献!:-)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值