Password generator

From Rosetta Code
Revision as of 19:29, 25 April 2016 by rosettacode>Gerard Schildberger (added an HTML comment.)
Password generator is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
File:Passwords.jpg

Create a password generation program which will generate passwords containing random ASCII characters from the following groups:

  • lower-case letters: a-z
  • upper-case letters: A-Z
  • digits: 0-9
  • other printable characters excluding white-space, backslash and grave:  !"#$%&'()*+,-./:;<=>?@[]^_{|}~


The generated password(s) must include at least one lower-case letter, one upper-case letter and one character from digits and 'other'.

The user must be able to specify the password length and the number of passwords to generate.

The passwords should be displayed or written to a file, one per line.

The randomness should be from a system source or library.

The program should implement a help option or button which should describe the program and options when invoked.

You may also allow the user to specify a seed value, and give the option of excluding visually similar characters.

For example:         Il1     O0     5S     2Z         where the characters are:

  •   capitol eye, lowercase ell, the digit one
  •   capital oh, the digit zero
  •   the digit five, capital ess
  •   the digit two, capital zee



J

Implementation:

<lang J>thru=: <. + i.@(+*)@-~ chr=: a.&i.

lower=: 'a' thru&.chr 'z' upper=: 'A' thru&.chr 'Z' digit=: '0' thru&.chr '9' other=: ('!' thru&.chr '~')-.lower,upper,digit,'`\'

pwgen =:verb define"0 :: pwhelp

 sizes=. #/.~ (i.4),?(y-4)#4 NB. how many of each?
 NB. pick allocated characters from each group, then shuffle 
 (?~@# { ]) ;sizes (?@(##) { ])each lower;upper;digit;other
 pwgen x#y

)

pwhelp =:echo bind (noun define)

 [x] pwgen y - generates passwords of length y
 optional x says how many to generate (if you want more than 1)
 y must be at least 4 because 
 passwords must contain four different kinds of characters.

)</lang>

Example use (from J command line):

<lang J> pwgen'help'

 [x] pwgen y - generates passwords of length y
 optional x says how many to generate (if you want more than 1)
 y must be at least 4 because 
 passwords must contain four different kinds of characters.
  pwgen 10

oUVT[+l2pk

  5 pwgen 10

456u;mJ#{Y WT^bf2|50) r&fLIY0IvW 4UZQC5!y:8 I}G86(;1Ob</lang>

REXX

This REXX code was written as generically and idiomatically as possible so that the   special characters   and  
the lowercase and uppercase alphabets may be extended with letters from other alphabets. <lang rexx>/*REXX program generates a random password according to the Rosetta Code task's rules.*/ @abcL= 'abcdefghijklmnopqrstuvwxyz'; @abcU=@abc /*define a lower & uppercase alphabet. */ upper @abcU; @digs= 0123456789 /*uppercase a value; define numerals. */ @spec= '!"#$%&()+,-./:;<=>?@[]^{|}~' || "'" /*define a bunch of special characters.*/ parse arg L N seed . /*obtain optional arguments from the CL*/ if L=='?' then call help /*does user want documentation shown? */ if L== | L=="," then L=8 /*Not specified? Then use the default.*/ if N== | N=="," then N=1 /* " " " " " " */ if datatype(seed,'W') then call random ,,seed /*the seed for repeatable RANDOM BIF #s*/ if \datatype(L, 'W') then call ser "password length, it isn't an integer: " L if L<4 then call ser "password length, it's too small: " L if L>80 then call ser "password length, it's too large: " L if \datatype(N, 'W') then call ser "number of passwords, it isn't an integer: " N if N<0 then call ser "number of passwords, it's too small: " N

   do g=1  for N                                /*generate  N  passwords (default is 1)*/
   $=letterL()||letterU()||numeral()||special() /*generate  4  random  PW constituents.*/
           do k=5  to  L;       z=random(1, 4)  /* [↓]  flush out PW with more parts.  */
           if z==1  then $=$ || letterL()       /*maybe append random lowercase letter.*/
           if z==2  then $=$ || letterU()       /*  "      "      "   uppercase    "   */
           if z==3  then $=$ || numeral()       /*  "      "      "       numeral      */
           if z==4  then $=$ || special()       /*  "      "      "   special character*/
           end   /*k*/                          /* [↓]  code below randomizes PW chars.*/
   t=length($)                                  /*the length of the password (in bytes)*/
           do L+L                               /*perform a random number of char swaps*/
           a=random(1,t);     x=substr($,a,1)   /*A: 1st char location;  X is the char.*/
           b=random(1,t);     y=substr($,b,1)   /*B: 2nd   "      "      Y  "  "    "  */
           $=overlay(x,$,b);  $=overlay(y,$,a)  /*(both statements) swap the two chars.*/
           end  /*swaps*/                       /* [↑]  perform extra swap to be sure. */
   say right(g,length(N))  'password is: ' $    /*display the  Nth  password to console*/
   end       /*g*/

exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ ser: say; say '***error*** invalid' arg(1); exit 13 /*display an error message*/ letterL: return substr(@abcL, random(1, length(@abcL)), 1) /*return random lowercase.*/ letterU: return substr(@abcU, random(1, length(@abcU)), 1) /* " " uppercase.*/ numeral: return substr(@digs, random(1, length(@digs)), 1) /* " " numeral. */ special: return substr(@spec, random(1, length(@spec)), 1) /* " " special char*/ /*──────────────────────────────────────────────────────────────────────────────────────*/ help: signal .; .: do j=sigL+2 to sourceline()-1; say sourceline(j); end; exit 0 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~ documentation begins on next line.~~~~~~~~~~~~~~~~~~~~~~~~~ ╔═════════════════════════════════════════════════════════════════════════════╗ ║ Documentation for the GENPW program: ║ ║ ║ ║ The format of the GENPW command is: ║ ║ ║ ║ ║ ║ ║ ║ GENPW  ? ◄─── shows this documentation. ║ ║ GENPW ◄─── generates 1 password. ║ ║ GENPW length ◄─── generates (all) passwords with this length. ║ ║ GENPW length howMany ◄─── generates howMany passwords. ║ ║ GENPW , howMany ◄─── uses the default for the length of the PWs.║ ║ ║ ║ ║ ╟─── where: ║ ║ length is the length of the passwords to be generated. ║ ║ The default is 8. ║ ║ If a comma (,) is specified, the default is used. ║ ║ The minimum is 4, the maximum is 80. ║ ║ ║ ║ howMany is the number of passwords to be generated. ║ ║ The default is 1. ║ ╚═════════════════════════════════════════════════════════════════════════════╝ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~documentation ends on the previous line.~~~~~~~~~~~~~~~~~~~*/</lang> output   when using the inputs of:   10   20

 1 password is:  17=6@@&6@l
 2 password is:  [:Bc13B;@A
 3 password is:  za@.3AxAoC
 4 password is:  x}Az!aj{6@
 5 password is:  k378BC,7w,
 6 password is:  v@<$B82C:0
 7 password is:  8aj4$+[+0@
 8 password is:  u:{ut7@{@C
 9 password is:  dA$)2l@+5C
10 password is:  ^A>|Cbc9gC
11 password is:  "@j0=C@#9<
12 password is:  w:AB8BCw99
13 password is:  tAu)7vrc0|
14 password is:  494b2o<B&A
15 password is:  18A92A84t(
16 password is:  B?eb82B:?3
17 password is:  @A+5ohB]CB
18 password is:  @nAt@^e['2
19 password is:  AaBB522/@w
20 password is:  yv8CB9A#[2

zkl

Put the fallowing code into a file (such as pwdg.zkl): <lang zkl>var pwdLen=10, pwds=1, xclude="";

argh:=Utils.Argh( L("+xclude","","Don't use these characters",fcn(arg){ xclude=arg }), L("+len","","Number of characters in password", fcn(arg){ pwdLen=arg.toInt() } ), L("+num","","Number of passwords to generate", fcn(arg){ pwds=arg.toInt() } ), ); try{ argh.parse(vm.arglist) }catch{ System.exit(1) }

g1,g2,g3:=["a".."z"].walk(), ["A".."Z"].walk(), ["0".."9"].walk(); g4:="!\"#$%&'()*+,-./:;<=>?@[]^_{|}~".split(""); all:=(g1.extend(g2,g3,g4).concat() - xclude).split("");

do(pwds){

  pwd:=(T(g1,g2,g3,g4).pump(String,"shuffle",T("get",0)) - xclude).split("");
  println(pwd.extend(all.shuffle()[0,pwdLen - pwd.len()]).shuffle().concat());

}</lang> This is a command line program so output can be redirected.

Output:
$ zkl pwdg.zkl -?
Unknown option: ?
Options:
  --len <arg>: Number of characters in password
  --num <arg>: Number of passwords to generate
  --xclude <arg>: Don't use these characters

$ zkl pwdg.zkl --len 20 --xclude "012345678" --num 5
O?a~siD&lK&<vL]od$|(
yhHVH})#S'F@<~%,Tb-L
?pOq"fmHAPtxgWM$n~u9
h&"#!bZGCm)dXt]$*)/p
x]*x>qH/Wde;asRzhZ.)