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 & key[0];
uchar frontBit = 0;
while (--index >= 0)
{
// save front bit
frontBit = 0x80 & key[index];
// shift
key[index] <<= 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 < p->chunkSize;j++)
{
*(p->outData+j) = *(p->inData+j) ^ *(p->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 < nThreads; i++)
{
if(pthread_create(&pThreads[i], NULL, encryptData, (void *) (pParam+i)) != 0)
{
rc = 1;
fprintf(stderr,"pthread_create error");
break;
}
}
if (rc == 0)
{
for(i = 0; i < 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 > 0 )
{
argCheck++;
}
}
break;
default:
break;
}
}
if ( argCheck != 2 )
{
fprintf(stderr,"%s\n", "Usage: palmtest -k <key_filename> -n <Number_of_threads_to_create>");
exit(1);
}
// get key from the given file
pKey = getKey(fileName,&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 < chunkSize)
{
while(readSize < 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 < 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 < chunkSize;j++)
{
// output
printf ("%02X",pParam->outData[j] );
}
}
else
{
// create multi-threaded processing
if (parallelCripto(curThread,pParam) == 0)
{
for(j=0;j < curThread;j++)
{
int i = 0;
for(;i < chunkSize;i++)
{
// output
printf ("%02X",pParam[j].outData[i] );
}
}
}
}
free(pParam);
curThread = 0;
}
}
}
printf ("\n");
free(pOutText);
free(pText);
free(pKey);
return 0;
}</span>