Linux Format

The LXF puzzle!....................

In our first LXF puzzle Mihalis Tsoukalos shows how to generate complex passwords in a range of languages and challenges you to do a better job.

-

In our first (of many?) LXF puzzles, Mihalis Tsoukalos shows how to generate complex passwords in a range of languages and challenges you to do a better job.

By the end of this article you’ll know how to generate difficult-to-guess passwords in various programmin­g languages. However, the main purpose of this tutorial is to get you involved into the process, make you think and perhaps even come up with a better solution than the ones presented here.

Some programmin­g languages might offer modules and packages that automatica­lly generate good passwords. However, the problem is that they leave little space for learning, customisat­ion and experiment­ation, which takes away the fun from the whole programmin­g process.

A forthcomin­g issue of Linux Format might include the code and the list of people who did well with the presented challenge. Watch this space...

Thinking, is hard

Computers work with numbers; therefore computers are unable to generate letters or words directly. You’ll have to find a way to create random numbers and convert them to words that contain both letters and numbers.

First of all we need to decide whether we’re going to generate passwords with Unicode characters or not. The answer is pretty easy: using ASCII characters can help you create pretty secure passwords so you won’t need to add Unicode characters to them.

So, the real problem here is how to go from a random number to an ASCII character in C as well as in Python 3, Perl and Go. If you’re using a different programmin­g language you’ll have to find the technique your programmin­g language uses for converting an integer to an ASCII character.

The easiest way to lower a big integer number and make it fall within a given range, which will help you to convert it to an ASCII character, is with the help of the modulo (aka modulus) operation, which finds the remainder of the division between two integers. If you divide a number by 10, then the remainder will be an integer between 0 and 9. Because the number of valid ASCII characters is around 130, you’ll need to divide the generated random number with 130, but you can also choose a lower number. However, if your programmin­g language can generate random numbers within a given range, you might not need to use the modulo operation.

So random!

The first step into solving the original problem is being able to create random numbers. So, this section will present a small C program that reads the seed and the number of random numbers that will generated from the command line, before printing them on your screen.

The name of the program will be random.c – it contains the following C code:

#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { if (argc != 3) { printf("Wrong number of arguments. Exiting...\n"); return -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"); return 0;

As you can see, the C program is relatively small. However, the generation of random numbers in most scripting languages takes less than five lines of code.

You first read the two command line arguments of the program and you call the srand() function in order to set the seed for your random number generator. Next, you just call the rand() function as many times as the random numbers you want to produce.

If you use the same seed all the time, you’ll create the same output all the time. This makes the entire process not random and therefore easy to be hacked: $ ./random 123 4 128959393 1692901013 436085873 748533630 $ ./random 123 3 128959393 1692901013 436085873 $ ./random 123 5 128959393 1692901013 436085873 748533630 776550279

As you can see, the first number of all sequences of random numbers is always the same when you’re using the same seed, which also makes all consecutiv­e numbers identical. So, is random.c a relatively good random generator? The answer is yes, as long as you don’t use the same seed all the time. This teaches us that sometimes small details make all the difference and that we should be very careful. However, there are better alternativ­es around for setting the value of the seed, which is one of the subjects of the next section. Figure1 shows the output from numerous executions of the random.c program.

Even more random

The C code of this section will be saved as randomPass.c – the general idea is based on the code of random.c, which is used for generating random numbers. However, this time the seed for the random number generator isn’t given as a command line argument, which is a very common practice.

There are many ways to choose the seed, including using the current time or a combinatio­n of the current time with a network id, as well as the use of a UNIX device such as /dev/random that’s able to generate random numbers without the need for writing any code. Additional­ly, this time the output of the program will be ASCII characters instead of numbers, which is the output we’re after. The important code of randomPass.c is as follows: char c = FROM + rand() % TOTAL + 1; printf("%c”, c); As you can see from the previous code, C has the easiest method for converting an integer into an ASCII character because it treats ASCII characters as integer numbers and vice versa – although you should be aware that this kind of flexibilit­y is behind many nasty bugs.

However, it’s also interestin­g to know how randomPass.c gets the seed for the random number generator using the /dev/random device: int getSeed = open("/dev/random”, O_RDONLY); unsigned short mySeed; uint16_t myRead = read(getSeed, &mySeed, sizeof(mySeed));

You just read /dev/random as if it was a file. Figure2 shows the output of numerous executions of the

randomPass.c program, which takes just one argument that’s the length of the generated random password.

So, after having a working version in C, it makes sense to implement programs in other programmin­g languages. There are various reasons for doing so, including the joy of learning and in order to be able to compare the various implementa­tions and find the advantages and disadvanta­ge of each programmin­g language. So, next we’re going to develop a Python 3 program, a Perl program and a program in Go. All of them will generate random passwords using the same principles that helped us develop the C program.

Randomness in Python 3

This section will present a Python 3 program that’s based on the technique used in randomPass.c. The name of the Python 3 script will be randomPass.py and its important code is as follows: for i in range(0, count): while True: randomNumb­er = random.randrange(MIN, MAX) char = str(chr(randomNumb­er)) if char.isspace() == False:

break print(char, end='') This code doesn’t use the modulo operator because the randrange() function of the random module generates random numbers that fall within the desired range. The upshot is that this makes things faster, because the script needs to execute less commands.

Additional­ly, Python 3 has a very handy function named isspace() that enables you to find out whether a character is a space character or not, and exclude it from the output. Finally, the Python 3 random module automatica­lly creates a seed for you.

Executing randomPass.py will generate the following kind of output: $ ./randomPass.py 20 eK1M;w#'F@Iudpm&W/G> $ ./randomPass.py 20 M8w[o/JROb&A_'"K)Bc>

Figure3 shows the Python 3 code of randomPass.py. Generally speaking, scripting languages require less code than programmin­g languages such as C to solve the same problem. However, the executable files of compiled programmin­g languages tend to be faster than scripts. If you have the time, it would also be useful to try to measure the performanc­e of each program presented in this tutorial. The best way to do so is by modifying the code of each program in order to generate 100,000 random passwords and use the time(1) utility to measure the time it took each one of them to execute. Always try to learn as much as you can when you’re experiment­ing.

Perl random passwords

Perl is another good candidate for generating random passwords based on random numbers, so this section will present a Perl program named randomPass.pl that enables you to produce random passwords. The randomPass.pl script is relatively small, yet it does the job pretty well and only takes one command line argument, which is the length of the generated password.

The most important code of randomPass.pl is this: print chr($OFFSET + int(rand($MAX)));

All the job is done by the chr() function, which takes an integer as input and returns a character. After converting the random number to an ASCII character, you just have to print it on your screen.

Executing randomPass.pl will generate the following kind of output: $ ./randomPass.pl 20 [wPyWpJ6iUZ#%!F{:p45 $ ./randomPass.pl 10 ,H,4I>|G)a

Doing your job using small scripts in any scripting programmin­g language is not a bad idea, because it saves you time and effort.

Secure old Go

Go is a modern programmin­g language that you can use for creating random passwords. The Go program discussed here is called randomPass.go. The most important part of the program is as follows: for i= 0; i < LENGTH; i++ { anInt := int(random(MIN, MAX)) newChar := string(startChar[0] + byte(anInt)) if newChar == " " { i=i-i continue } fmt.Print(newChar) As you can see, Go has a strange way of dealing with ASCII characters. Learning such things when writing simple applicatio­ns for fun is a huge benefit for every programmer – this will definitely make your life easier you when you want to develop bigger applicatio­ns in Go in the future.

Executing randomPass.go will generate the following kind of random passwords:

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

Figure4 shows the entire Go code of the randomPass.go program, which you can compare with the other implementa­tions.

Dictionary file

After working through these examples, it’s not a bad idea to start playing more and maybe trying to implement some crazy ideas. Therefore, this section will take a slightly different approach and use the dictionary file that comes with a Linux machine as the starting point of the generated passwords.

If the dictionary file isn’t there, you might need to install it on your Linux machine using your favourite package manager. The good thing is that the presented program takes the dictionary file, which is a plain text file, as a command line argument so you’ll also be able to use your own text files with your desired list of words.

This section will use Python 3 for the implementa­tion of passwords, because the language enables you to tackle many tasks without the need to write too much code. The name of the Python 3 script will be dictPass.py and the first thing it will do is count the number of words found in the dictionary file. Then, it will select a random word based on a random number that it will generate.

After selecting the word, it’ll need to make sure that its length is more than the desired numbers of characters you want on your password. If the password is smaller, it will generate another random number and choose another word from the dictionary until the generated password is equal or larger than the desired length. Because the current password will be based on dictionary words, the program will try to alter it by randomly replacing some of its letters with numbers, uppercase letters and other symbols. After that, the password will be displayed on the screen, ready to be used.

All the previous steps will be shown in the output of the dictPass.py script to make things clearer for you.

The core functional­ity of dictPass.py is implemente­d in the following Python 3 code: lineNumber = randint(1, length) randomLine = file.getline(lineNumber) randomLine = randomLine.rstrip() print(":”, randomLine) password = password + randomLine The previous Python 3 code constructs the first version of the password by choosing a word from the dictionary file. The only disadvanta­ge of dictPass.py is that it reads the dictionary file many times, which might slow down the process. Executing dictPass.py will generate the following type of output: $ ./dictPass.py 10 /usr/share/dict/american-english voLu<43.1aCh)s

As you can see, the dictPass.py script generates pretty good passwords – the power of dictPass.py doesn’t come from the use of Python 3 but from the clever and unusual way it generates the passwords. Figure5 shows more executions of the dictPass.py program, which is a very good indication of how far your imaginatio­n can take you.

Do you find the generated passwords good enough? Can you make the program any better? Can you think of a better technique to create more difficult passwords? Can you come up with a simpler technique to create better random strings? Implement it as a program and send it to us, and you might get published.

Is this tutorial the end of random password generation? Of course not. This is just the beginning of your journey to creating better and more secure passwords for you, your friends, your company and your family.

 ??  ?? Figure 4: the Go code of the randomPass.go program. Go offers the advantages of C without the tricky parts of C.
Figure 4: the Go code of the randomPass.go program. Go offers the advantages of C without the tricky parts of C.
 ??  ?? Figure 3: the Python 3 code of the randomPass.py script. Python 3 can do wonders using just a few lines of code!
Figure 3: the Python 3 code of the randomPass.py script. Python 3 can do wonders using just a few lines of code!
 ??  ?? Figure 2: the kind of output randomPass.c generates, as well as the command used for compiling it.
Figure 2: the kind of output randomPass.c generates, as well as the command used for compiling it.
 ??  ??
 ??  ?? Figure 1: the output of the random.c program. If you use the same seed, the sequence of the generated random numbers will always be the same!
Figure 1: the output of the random.c program. If you use the same seed, the sequence of the generated random numbers will always be the same!
 ??  ??
 ??  ?? Figure 5: the kind of output the dictPass. py Python 3 script generates – the resulting passwords are pretty ingenious for such a small program.
Figure 5: the kind of output the dictPass. py Python 3 script generates – the resulting passwords are pretty ingenious for such a small program.

Newspapers in English

Newspapers from Australia