The LXF puz­zle!....................

In our first LXF puz­zle Mi­halis Tsouka­los shows how to gen­er­ate com­plex pass­words in a range of lan­guages and chal­lenges you to do a bet­ter job.

Linux Format - - CONTENTS -

In our first (of many?) LXF puz­zles, Mi­halis Tsouka­los shows how to gen­er­ate com­plex pass­words in a range of lan­guages and chal­lenges you to do a bet­ter job.

By the end of this ar­ti­cle you’ll know how to gen­er­ate dif­fi­cult-to-guess pass­words in var­i­ous pro­gram­ming lan­guages. How­ever, the main pur­pose of this tu­to­rial is to get you in­volved into the process, make you think and per­haps even come up with a bet­ter so­lu­tion than the ones pre­sented here.

Some pro­gram­ming lan­guages might of­fer mod­ules and pack­ages that au­to­mat­i­cally gen­er­ate good pass­words. How­ever, the prob­lem is that they leave lit­tle space for learn­ing, cus­tomi­sa­tion and ex­per­i­men­ta­tion, which takes away the fun from the whole pro­gram­ming process.

A forth­com­ing issue of Linux Format might in­clude the code and the list of peo­ple who did well with the pre­sented chal­lenge. Watch this space...

Think­ing, is hard

Com­put­ers work with num­bers; there­fore com­put­ers are un­able to gen­er­ate letters or words di­rectly. You’ll have to find a way to cre­ate ran­dom num­bers and con­vert them to words that con­tain both letters and num­bers.

First of all we need to de­cide whether we’re going to gen­er­ate pass­words with Uni­code char­ac­ters or not. The an­swer is pretty easy: us­ing ASCII char­ac­ters can help you cre­ate pretty se­cure pass­words so you won’t need to add Uni­code char­ac­ters to them.

So, the real prob­lem here is how to go from a ran­dom num­ber to an ASCII char­ac­ter in C as well as in Python 3, Perl and Go. If you’re us­ing a dif­fer­ent pro­gram­ming lan­guage you’ll have to find the tech­nique your pro­gram­ming lan­guage uses for con­vert­ing an in­te­ger to an ASCII char­ac­ter.

The eas­i­est way to lower a big in­te­ger num­ber and make it fall within a given range, which will help you to con­vert it to an ASCII char­ac­ter, is with the help of the mod­ulo (aka mod­u­lus) oper­a­tion, which finds the re­main­der of the divi­sion be­tween two in­te­gers. If you di­vide a num­ber by 10, then the re­main­der will be an in­te­ger be­tween 0 and 9. Be­cause the num­ber of valid ASCII char­ac­ters is around 130, you’ll need to di­vide the gen­er­ated ran­dom num­ber with 130, but you can also choose a lower num­ber. How­ever, if your pro­gram­ming lan­guage can gen­er­ate ran­dom num­bers within a given range, you might not need to use the mod­ulo oper­a­tion.

So ran­dom!

The first step into solv­ing the orig­i­nal prob­lem is be­ing able to cre­ate ran­dom num­bers. So, this sec­tion will present a small C pro­gram that reads the seed and the num­ber of ran­dom num­bers that will gen­er­ated from the com­mand line, be­fore print­ing them on your screen.

The name of the pro­gram will be ran­dom.c – it con­tains the fol­low­ing C code:

#in­clude <stdio.h> #in­clude <stdlib.h> int main(int argc, char **argv) { if (argc != 3) { printf("Wrong num­ber of ar­gu­ments. Ex­it­ing...\n"); re­turn -1; int seed = atoi(argv[1]); int count = atoi(argv[2]); srand(seed);

int i= 0; for (i=1; i<=count; i++)

printf("%d ", rand()); printf("\n"); re­turn 0;

As you can see, the C pro­gram is rel­a­tively small. How­ever, the gen­er­a­tion of ran­dom num­bers in most script­ing lan­guages takes less than five lines of code.

You first read the two com­mand line ar­gu­ments of the pro­gram and you call the srand() func­tion in or­der to set the seed for your ran­dom num­ber gen­er­a­tor. Next, you just call the rand() func­tion as many times as the ran­dom num­bers you want to pro­duce.

If you use the same seed all the time, you’ll cre­ate the same out­put all the time. This makes the en­tire process not ran­dom and there­fore easy to be hacked: $ ./ran­dom 123 4 128959393 1692901013 436085873 748533630 $ ./ran­dom 123 3 128959393 1692901013 436085873 $ ./ran­dom 123 5 128959393 1692901013 436085873 748533630 776550279

As you can see, the first num­ber of all se­quences of ran­dom num­bers is al­ways the same when you’re us­ing the same seed, which also makes all con­sec­u­tive num­bers iden­ti­cal. So, is ran­dom.c a rel­a­tively good ran­dom gen­er­a­tor? The an­swer is yes, as long as you don’t use the same seed all the time. This teaches us that some­times small de­tails make all the dif­fer­ence and that we should be very care­ful. How­ever, there are bet­ter al­ter­na­tives around for set­ting the value of the seed, which is one of the sub­jects of the next sec­tion. Fig­ure1 shows the out­put from nu­mer­ous ex­e­cu­tions of the ran­dom.c pro­gram.

Even more ran­dom

The C code of this sec­tion will be saved as ran­domPass.c – the gen­eral idea is based on the code of ran­dom.c, which is used for gen­er­at­ing ran­dom num­bers. How­ever, this time the seed for the ran­dom num­ber gen­er­a­tor isn’t given as a com­mand line ar­gu­ment, which is a very com­mon prac­tice.

There are many ways to choose the seed, in­clud­ing us­ing the cur­rent time or a com­bi­na­tion of the cur­rent time with a net­work id, as well as the use of a UNIX de­vice such as /dev/ran­dom that’s able to gen­er­ate ran­dom num­bers with­out the need for writ­ing any code. Ad­di­tion­ally, this time the out­put of the pro­gram will be ASCII char­ac­ters in­stead of num­bers, which is the out­put we’re af­ter. The im­por­tant code of ran­domPass.c is as fol­lows: char c = FROM + rand() % TO­TAL + 1; printf("%c”, c); As you can see from the pre­vi­ous code, C has the eas­i­est method for con­vert­ing an in­te­ger into an ASCII char­ac­ter be­cause it treats ASCII char­ac­ters as in­te­ger num­bers and vice versa – al­though you should be aware that this kind of flex­i­bil­ity is be­hind many nasty bugs.

How­ever, it’s also in­ter­est­ing to know how ran­domPass.c gets the seed for the ran­dom num­ber gen­er­a­tor us­ing the /dev/ran­dom de­vice: int getSeed = open("/dev/ran­dom”, O_RDONLY); un­signed short mySeed; uin­t16_t myRead = read(getSeed, &mySeed, sizeof(mySeed));

You just read /dev/ran­dom as if it was a file. Fig­ure2 shows the out­put of nu­mer­ous ex­e­cu­tions of the

ran­domPass.c pro­gram, which takes just one ar­gu­ment that’s the length of the gen­er­ated ran­dom pass­word.

So, af­ter hav­ing a work­ing ver­sion in C, it makes sense to im­ple­ment pro­grams in other pro­gram­ming lan­guages. There are var­i­ous rea­sons for do­ing so, in­clud­ing the joy of learn­ing and in or­der to be able to com­pare the var­i­ous im­ple­men­ta­tions and find the ad­van­tages and dis­ad­van­tage of each pro­gram­ming lan­guage. So, next we’re going to de­velop a Python 3 pro­gram, a Perl pro­gram and a pro­gram in Go. All of them will gen­er­ate ran­dom pass­words us­ing the same prin­ci­ples that helped us de­velop the C pro­gram.

Ran­dom­ness in Python 3

This sec­tion will present a Python 3 pro­gram that’s based on the tech­nique used in ran­domPass.c. The name of the Python 3 script will be ran­domPass.py and its im­por­tant code is as fol­lows: for i in range(0, count): while True: ran­domNum­ber = ran­dom.ran­drange(MIN, MAX) char = str(chr(ran­domNum­ber)) if char.iss­pace() == False:

break print(char, end='') This code doesn’t use the mod­ulo op­er­a­tor be­cause the ran­drange() func­tion of the ran­dom mod­ule gen­er­ates ran­dom num­bers that fall within the de­sired range. The up­shot is that this makes things faster, be­cause the script needs to ex­e­cute less com­mands.

Ad­di­tion­ally, Python 3 has a very handy func­tion named iss­pace() that en­ables you to find out whether a char­ac­ter is a space char­ac­ter or not, and ex­clude it from the out­put. Fi­nally, the Python 3 ran­dom mod­ule au­to­mat­i­cally cre­ates a seed for you.

Ex­e­cut­ing ran­domPass.py will gen­er­ate the fol­low­ing kind of out­put: $ ./ran­domPass.py 20 eK1M;w#'F@Iudpm&W/G> $ ./ran­domPass.py 20 M8w[o/JROb&A_'"K)Bc>

Fig­ure3 shows the Python 3 code of ran­domPass.py. Gen­er­ally speak­ing, script­ing lan­guages re­quire less code than pro­gram­ming lan­guages such as C to solve the same prob­lem. How­ever, the ex­e­cutable files of com­piled pro­gram­ming lan­guages tend to be faster than scripts. If you have the time, it would also be use­ful to try to mea­sure the per­for­mance of each pro­gram pre­sented in this tu­to­rial. The best way to do so is by mod­i­fy­ing the code of each pro­gram in or­der to gen­er­ate 100,000 ran­dom pass­words and use the time(1) util­ity to mea­sure the time it took each one of them to ex­e­cute. Al­ways try to learn as much as you can when you’re ex­per­i­ment­ing.

Perl ran­dom pass­words

Perl is another good can­di­date for gen­er­at­ing ran­dom pass­words based on ran­dom num­bers, so this sec­tion will present a Perl pro­gram named ran­domPass.pl that en­ables you to pro­duce ran­dom pass­words. The ran­domPass.pl script is rel­a­tively small, yet it does the job pretty well and only takes one com­mand line ar­gu­ment, which is the length of the gen­er­ated pass­word.

The most im­por­tant code of ran­domPass.pl is this: print chr($OFF­SET + int(rand($MAX)));

All the job is done by the chr() func­tion, which takes an in­te­ger as in­put and re­turns a char­ac­ter. Af­ter con­vert­ing the ran­dom num­ber to an ASCII char­ac­ter, you just have to print it on your screen.

Ex­e­cut­ing ran­domPass.pl will gen­er­ate the fol­low­ing kind of out­put: $ ./ran­domPass.pl 20 [wPyWpJ6iUZ#%!F{:p45 $ ./ran­domPass.pl 10 ,H,4I>|G)a

Do­ing your job us­ing small scripts in any script­ing pro­gram­ming lan­guage is not a bad idea, be­cause it saves you time and ef­fort.

Se­cure old Go

Go is a mod­ern pro­gram­ming lan­guage that you can use for cre­at­ing ran­dom pass­words. The Go pro­gram dis­cussed here is called ran­domPass.go. The most im­por­tant part of the pro­gram is as fol­lows: for i= 0; i < LENGTH; i++ { anInt := int(ran­dom(MIN, MAX)) newChar := string(startChar[0] + byte(anInt)) if newChar == " " { i=i-i con­tinue } fmt.Print(newChar) As you can see, Go has a strange way of deal­ing with ASCII char­ac­ters. Learn­ing such things when writ­ing sim­ple ap­pli­ca­tions for fun is a huge ben­e­fit for every pro­gram­mer – this will def­i­nitely make your life eas­ier you when you want to de­velop big­ger ap­pli­ca­tions in Go in the fu­ture.

Ex­e­cut­ing ran­domPass.go will gen­er­ate the fol­low­ing kind of ran­dom pass­words:

$ go run ran­domPass.go 10 E=lZ$)&r.u $ go run ran­domPass.go 20 Gz4&OKcbL>.=mC=b]EYJ $ go run ran­domPass.go 30 *?S0”Yg-5-pZ_kUra­jJA/Z-bgEsp]z

Fig­ure4 shows the en­tire Go code of the ran­domPass.go pro­gram, which you can com­pare with the other im­ple­men­ta­tions.

Dic­tionary file

Af­ter work­ing through th­ese ex­am­ples, it’s not a bad idea to start play­ing more and maybe try­ing to im­ple­ment some crazy ideas. There­fore, this sec­tion will take a slightly dif­fer­ent ap­proach and use the dic­tionary file that comes with a Linux ma­chine as the start­ing point of the gen­er­ated pass­words.

If the dic­tionary file isn’t there, you might need to in­stall it on your Linux ma­chine us­ing your favourite pack­age man­ager. The good thing is that the pre­sented pro­gram takes the dic­tionary file, which is a plain text file, as a com­mand line ar­gu­ment so you’ll also be able to use your own text files with your de­sired list of words.

This sec­tion will use Python 3 for the im­ple­men­ta­tion of pass­words, be­cause the lan­guage en­ables you to tackle many tasks with­out the need to write too much code. The name of the Python 3 script will be dic­tPass.py and the first thing it will do is count the num­ber of words found in the dic­tionary file. Then, it will select a ran­dom word based on a ran­dom num­ber that it will gen­er­ate.

Af­ter se­lect­ing the word, it’ll need to make sure that its length is more than the de­sired num­bers of char­ac­ters you want on your pass­word. If the pass­word is smaller, it will gen­er­ate another ran­dom num­ber and choose another word from the dic­tionary un­til the gen­er­ated pass­word is equal or larger than the de­sired length. Be­cause the cur­rent pass­word will be based on dic­tionary words, the pro­gram will try to al­ter it by ran­domly re­plac­ing some of its letters with num­bers, up­per­case letters and other sym­bols. Af­ter that, the pass­word will be dis­played on the screen, ready to be used.

All the pre­vi­ous steps will be shown in the out­put of the dic­tPass.py script to make things clearer for you.

The core func­tion­al­ity of dic­tPass.py is im­ple­mented in the fol­low­ing Python 3 code: lineNum­ber = randint(1, length) ran­domLine = file.get­line(lineNum­ber) ran­domLine = ran­domLine.rstrip() print(":”, ran­domLine) pass­word = pass­word + ran­domLine The pre­vi­ous Python 3 code con­structs the first ver­sion of the pass­word by choos­ing a word from the dic­tionary file. The only dis­ad­van­tage of dic­tPass.py is that it reads the dic­tionary file many times, which might slow down the process. Ex­e­cut­ing dic­tPass.py will gen­er­ate the fol­low­ing type of out­put: $ ./dic­tPass.py 10 /usr/share/dict/amer­i­can-english voLu<43.1aCh)s

As you can see, the dic­tPass.py script gen­er­ates pretty good pass­words – the power of dic­tPass.py doesn’t come from the use of Python 3 but from the clever and un­usual way it gen­er­ates the pass­words. Fig­ure5 shows more ex­e­cu­tions of the dic­tPass.py pro­gram, which is a very good in­di­ca­tion of how far your imag­i­na­tion can take you.

Do you find the gen­er­ated pass­words good enough? Can you make the pro­gram any bet­ter? Can you think of a bet­ter tech­nique to cre­ate more dif­fi­cult pass­words? Can you come up with a sim­pler tech­nique to cre­ate bet­ter ran­dom strings? Im­ple­ment it as a pro­gram and send it to us, and you might get pub­lished.

Is this tu­to­rial the end of ran­dom pass­word gen­er­a­tion? Of course not. This is just the be­gin­ning of your jour­ney to cre­at­ing bet­ter and more se­cure pass­words for you, your friends, your com­pany and your fam­ily.

Fig­ure 1: the out­put of the ran­dom.c pro­gram. If you use the same seed, the se­quence of the gen­er­ated ran­dom num­bers will al­ways be the same!

Fig­ure 3: the Python 3 code of the ran­domPass.py script. Python 3 can do won­ders us­ing just a few lines of code!

Fig­ure 2: the kind of out­put ran­domPass.c gen­er­ates, as well as the com­mand used for com­pil­ing it.

Fig­ure 4: the Go code of the ran­domPass.go pro­gram. Go of­fers the ad­van­tages of C with­out the tricky parts of C.

Fig­ure 5: the kind of out­put the dic­tPass. py Python 3 script gen­er­ates – the re­sult­ing pass­words are pretty in­ge­nious for such a small pro­gram.

Newspapers in English

Newspapers from Australia

© PressReader. All rights reserved.