Simple Parallel Crypto

We need a utility that will perform a simple XOR crypto transform. They key will be given as a set of bytes in an external file and the number of bytes in the key will dictate the “chunk size”. The plain text data will
be given on stdin and the utility must break it into chunk-size sections and XOR it against the key and write the cypher text it to stdout.
After each chunk is processed the key is rotated left by one bit to make a new key. This means that the key will repeat every N chunks, where N is the number of bits in the key. The plain text may not be a multiple
of the chunk size in length. The plain text may also be very large, far exceeding the available memory+swap space in the system.

In addition to just performing the algorithm, the utility needs to scale so that multiple chunks of plain text can be efficiently processed in parallel on multi-core/multi-CPU machines. As such, a number of threads
must be created to process chunks of data concurrently. Regardless of the number of threads, the output cypher text must remain the same. Any errors/status must come out on stderr.

Required Command Line Options:
-k <filename> Specify the key file
-n # Number of threads to create

Example:
The keyfile contains two bytes: 0xF0 0xF0
The plain text file has the bytes: 0x01 0x02 0x03 0x04 0x11 0x12 0x13 0x14

encrypt -k keyfile -n 1 < plain > cypher

The cypher text has the bytes: 0xF1 0xF2 0xE2 0xE5 0xD2 0xD1 0x94 0x93

Implementation Details/Notes:

The utility can be written in C/C++. If C/C++, it should build and run on a POSIX system
(like Linux or Mac OS X).

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <pthread.h>

typedef unsigned char uchar;

/**
 *  I use a pointer to this struct
 *  as a parameter for basic thread routine
 */
struct chunkData
{
    uchar* inData;
    uchar* outData;
    int    chunkSize;
};

/**
 *  rotates key left by one bit
 *	 parameter(s):
 *		[in] nBytes  - key buffer length
 *      [in:out] key - ptr to key buffer
 *	returns:
 *		0 if no errors
 */
void rotateKeyLeftByOneBit(int nBytes, uchar* key)
{
    int index = nBytes; 
    uchar rBit = 0x80 &amp; key[0];
    uchar frontBit = 0;

    while (--index &gt;= 0)
    {
        // save front bit
        frontBit = 0x80 &amp; key[index];
        // shift 
        key[index] &lt;&lt;= 1;
        // set last bit
        if (rBit != 0)
        {
            key[index] |= 0x01;
        }
        // save 
        rBit = frontBit;
    }
}

/**
 *   Read key from the given file 
 *	 parameter(s):
 *		[in]     fileName - filename with key
 *      [out]    len - key buffer length
 *	returns:
 *		pointer to key buffer if no errors otherwise 0
 */
uchar* getKey(char* fileName, int* len)
{
    uchar* pKey = 0;
    int numBytes = 0;
    int nFileLen = 0;

    FILE* hFile = fopen(fileName,"rb");
    if (hFile == NULL)
    {
        return pKey;
    }
	// Get file length
    fseek(hFile, 0L, SEEK_END);  
    nFileLen = ftell(hFile);     
    rewind(hFile);               
    // allocate memory to contain the whole file:
    pKey = malloc(nFileLen);
    if (pKey != 0)
    {
        // read the key into the buffer:
        numBytes = fread (pKey,1,nFileLen,hFile);
        if (numBytes != nFileLen)
        {
            free (pKey);
            pKey = 0;
        }
        else
        {
            *len = nFileLen; 
        }    
    }    
    else    
    {
        fclose(hFile);
        return pKey;
    }
    fclose(hFile);

    return pKey;
}

/**
 *   Basic thread routine which in fact performs a simple encription
 *   parameter:
 *      [in]     ptr - pointer to chunkData struct
 */
void *encryptData(void* ptr)
{
    int j;
    struct chunkData* p = (struct chunkData* ) ptr;

    for(j=0;j &lt; p-&gt;chunkSize;j++)
    {
        *(p-&gt;outData+j) = *(p-&gt;inData+j) ^ *(p-&gt;outData+j);
    }
}

/**
 *   Creates thread(s) and waits until child thread(s) completed
 *   parameter(s):
 *      [in]        number of threads
 *      [in:out]    pParam pointer to 
 *  returns:
 *      0 - if there is no error
 */
int parallelCripto(int nThreads,struct chunkData* pParam)
{
    int rc = 0;
    int i;

    pthread_t* pThreads = (pthread_t *) calloc(nThreads, sizeof(pthread_t));
    if (pThreads == 0)
    {
        fprintf(stderr,"Memory allocation error\n");
        return 1;
    }

    for(i = 0; i &lt; nThreads; i++)
    {
        if(pthread_create(&amp;pThreads[i], NULL, encryptData, (void *) (pParam+i)) != 0)
        {
            rc = 1;
            fprintf(stderr,"pthread_create error");  
            break;
        }
    }

    if (rc == 0)
    {
        for(i = 0; i &lt; nThreads; i++)
        {
            pthread_join(pThreads[i], NULL); 
        }
    }
Raise your hips http://raindogscine.com/tag/anina/ getting viagra prescription off the ground until your knees, hips, and shoulders appear on a straight line. Not only does it helps you with your on sale here order cheap viagra problem. It usually occurs in adults under 35 and is more common in older men, yet it can affect  cheapest viagra no prescription anyone from the age group of 30-40. So you see generic viagra http://raindogscine.com/?attachment_id=159 it is quite an excellent find.     free(pThreads);

    return rc;
}

/**
 *	Main entry point
 */
int main(int argc, char* argv[])
{
    int		chunkSize = 0;
//    int		keyIndex  = 0;
    int		optChar; 
    int		argCheck = 0;
    int		nThreads = 1;
    int     curThread = 0;
    int     isDone = 1;
    char	fileName[256] = {0};
    uchar*	pKey = 0; 
    uchar*	pText = 0;
    uchar*  pOutText = 0;
    struct chunkData* pParam = 0;

    // parse arguments
    while ((optChar = getopt(argc, argv, "k:n:")) != -1)
    {
        switch (optChar)
        {
            case 'k':
                if (optarg)
                {
                    strcpy(fileName,optarg);
                    argCheck++;
                }
                break;
            case 'n':
                if (optarg)
                {
                    nThreads = atoi(optarg);
                    if ( nThreads &gt; 0 )
                    {    
                        argCheck++;
                    }
                }
                break;
            default:
                break;
        }
    }

    if ( argCheck != 2 )
    {   
        fprintf(stderr,"%s\n", "Usage: palmtest -k &lt;key_filename&gt; -n &lt;Number_of_threads_to_create&gt;");
        exit(1);
    }

    // get key from the given file
    pKey = getKey(fileName,&amp;chunkSize);
    if (pKey == 0 || chunkSize == 0)
    {    
        fprintf(stderr,"Cannot read a key.\n");
        exit(2);
    }
	// check stdin
    if (stdin == NULL)
    {
		free(pKey);
		fprintf(stderr,"STDIN is closed.\n");
        exit(1);
    }
    // allocate memory for input text and output encrypted data
	pText = (char*) malloc(chunkSize*nThreads);
    if (pText == NULL)
    {
		free(pKey);
		fprintf(stderr,"Memory allocation error\n");
        exit(1);
    }

    pOutText = (char*) malloc(chunkSize*nThreads);
    if (pOutText == NULL)
    {
        free(pText);
        free(pKey);
        fprintf(stderr,"Memory allocation error\n");
        exit(1);
    }

    curThread = 0;
	// read data from stdin
	while(isDone)
    {
        // set buffer offset for data section
        int bufOffset = curThread*chunkSize; 
		int readSize = fread(pText+bufOffset, 1, chunkSize, stdin);

        if (readSize == 0)
		{
			isDone = 0;
		}
        else
        {
            if (readSize &lt; chunkSize)
            {
                while(readSize &lt; chunkSize)
                {
                    // add gap to input buffer
                    *(pText+bufOffset+readSize) = ' ';
                    readSize++;
                }
                isDone = 0;
            }
            curThread++;
        }

        // check if it is time doing crypto
        if (isDone == 0 || curThread == nThreads) 
        {
            if ( curThread != 0 )
            {    
                int j;
                pParam = (struct chunkData* ) calloc(curThread, sizeof(struct chunkData));
                if (pParam == 0)
                {
                    fprintf(stderr,"Memory allocation error\n");
                    break;
                }
                // fill the input structures
                for(j=0;j &lt; curThread;j++)
                {
                    pParam[j].inData = pText+j*chunkSize;
                    pParam[j].outData = pOutText+j*chunkSize;
                    pParam[j].chunkSize = chunkSize;
                    memcpy(pOutText+j*chunkSize, pKey, chunkSize);
                    rotateKeyLeftByOneBit(chunkSize, pKey);
                }
                // no need to call parallelCripto 
                if ( curThread == 1 )
                { 
                    (encryptData)((void* )pParam);
                    for(j=0;j &lt; chunkSize;j++)
                    {    
                        // output 
                        printf ("%02X",pParam-&gt;outData[j] );
                    }
                }
                else
                {
                    // create multi-threaded processing 
                    if (parallelCripto(curThread,pParam) == 0)
                    {    
                        for(j=0;j &lt; curThread;j++)
                        {
                            int i = 0;
                            for(;i &lt; chunkSize;i++)
                            {    
                                // output 
                                printf ("%02X",pParam[j].outData[i] );
                            }
                        }
                    }
                }
                free(pParam);
                curThread = 0;
            }
        }
	}

    printf ("\n");

    free(pOutText);
    free(pText);
    free(pKey);
    return 0;
}</span>