Home > Technical Tutorials > Encryption using C

Encryption using C

Introduction

This tutorial explains how to use C libraries to encrypt text. For the purpose of the tutorial, we will check if the password of a given user is a dictionary word or not.

Please note a few things before reading this tutorial:

  1. Most of the information in this tutorial can be found on the man page of crypt. The man page of crypt in Fedora Core 5 and most of the man pages of crypt online are outdated and do not contain as much information as the latest one. You can find the latest man page on http://www.kernel.org/doc/man-pages/online/pages/man3/crypt.3.html.
  2. The Linux passwords are generally stored in the file /etc/shadow. The normal users do not have the permission to read / edit this file, so you need run the code as a super user. Each line of /etc/shadow looks like the line below:
    testuser:$1$testdata$TQKecT.xRF1s5CMDTE1k./:14154:0:99999:7:::

    In /etc/shadow, each field is separated by a :. Also, here we are interested in the first two fields which are explained later.

  3. There is a list of dictionary words in Linux that can generally found in /etc/share/dict/words.

Basic Encryption

To begin with, lets see how to encryption works. GNU provides crypt function that enables us to encrypt text based on the algorithm we choose and the key we provide. The encrypted password is the second field in each line of /etc/shadow. If you see it too has three fields each separated by a $. They are as follows:

  1. A number that represents the encryption algorithm used. These are as follows:
    • 1 – MD5
    • 2a – Bluefish (This is not available on GNU libraries but some Linux systems may provide it).
    • 5 – SHA256
    • 6 – SHA512.

    Each of these is explained later.

  2. The second part represents the salt. (The salt is used to change the algorithm, i.e., changing the salt will change the encryption).
  3. The third part represents the encrypted password. The length of this part depends on the encryption algorithm used:
    • MD5 – 22 Characters
    • SHA256 – 43 Characters
    • SHA512 – 86 Characters

The prototype of the crypt function is:

    char *crypt(const char *key, const char *salt);

This function can be found in the header file unistd.h and outputs the complete second field of the /etc/shadow. So, here is a program that encrypts a string using MD5 and prints its encryption. Other encryption techniques are available only if the version of glibc installed on your system is greater than 2.7. To check the glibc version you can run the following command

    echo `ls /lib/libc-*` | cut -f2 -d"-" | cut -f1,2 -d"."

So the program is as follows:

#include <stdio.h>
#include <unistd.h>
int main() {
     printf("%s\n",crypt("test","$1$testdata$"));
}

The second argument, i.e., the salt gives the encryption algorithm as well as the salt. Also the last $ sign is also optional.

Main Program

Now here we see how to check if the encrypted password of a given user is a dictionary word or not. For that we read the file containing dictionary word one word at a time and check if its encryption matches with the given user’s password or not.

Our program takes the user name as the command line argument and thus should run as:

[root@localhost ~]# ./a.out testuser

So to begin, first we include the libraries. We also include the string library that helps us to parse the shadow file.

#include <stdio.h>
#include <unistd.h>
#include <string.h>

The first step is to check if there are sufficient number of command line arguments present or not. So, it is as follows:

int main(int argc, char **argv) {
    if(argc != 2) {
        fprintf(stderr,"usuage: %s
                        <username>\n",argv[0]);
        exit(1);
    }

Next we check if the given user is present user is present in the /etc/shadow file or not. For this we are going to use the strtok function to parse this file. strtok function takes a string and splits it based on the delimiters that are provied. If multiple delimiters are provided, it will split based on each of them. On the first call we provide both the string and the delimiters. On subsequent calls, the string is not provied and a NULL is passed instead. Also, if we want to remember a particular field, we need to copy that part as strtok actually overwrites the next part of the string at the same memory location. Also, the original string also needs to be stored, if required, as it too gets destroyed in the process. Also, we store the encrypted password, if the user is found. The code for this part is:

    FILE *fp = fopen("/etc/shadow","r");
    /* Variable to scan a line */
    char *str = (char *)malloc(sizeof(char) * 10000);
    int found = 0;

    /* Two variables to store encrypted password */
    char *passwd = (char *)malloc(sizeof(char) * 1024);
    char *storepasswd = (char *)malloc(sizeof(char) * 1024);

    /* Variable to store username */
    char *username = (char *)malloc(sizeof(char) * 1024);
    while(fgets(str,10000) != NULL)) {
        strcpy(username,strtok(str,":"));
        if(strcmp(argv[1],username) == 0) {
            strcpy(passwd,strtok(NULL,":"));
            strcpy(storepasswd,passwd);
            found=1;
        }
    }
    if(found != 0) {
        fprintf(stderr,"Username: %s not found\n",argv[1]);
    }

Next thing we do will be next thing will be to extract the salt from the passwd string, open the list of words, encrypt each word and check if it is the password or not. For that we first store the whole password string in a variable, then pass it to strtok and split it on the basis of $ and store just the salt as in the following lines:

    strcpy(salt,"$");
    strcat(salt,strtok(passwd,"$")); // Gets the algorithm
    strcat(salt,"$");
    strcat(salt,strtok(NULL,"$")); // Gets the salt
    strcat(salt,"$"); // This is optional

Once you extract the salt, you can get the encrypted password using the following command:

    strcpy(getpasswd,crypt(word,salt));

This stores the password in getpasswd and we can compare it with the stored password.

    if(strcmp(getpasswd,storepasswd) == 0)
    {
        printf("Password is: %s\n",word);
    }

Only thing that remains is to run a loop on words from the dictionary. The remaining code is left to the reader to implement. Please send your comments if you find some difficulty or I have made some mistake somewhere.

Advertisement
Categories: Technical Tutorials
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.