C Symmetric Stream Cipher
Asked Answered
A

7

6

Does anyone have a good implementation of a stream cipher written in pure portable C? I am not terribly concerned with the strength of the cipher at this point in time because it is only for a proof of concept, but speed would be important. I've thought about just Xor'ing with a constant if I cannot find a decent stream cipher.

Apostrophize answered 22/12, 2008 at 19:27 Comment(0)
P
6

EDIT (2018): use NaCl or libsodium, or TweetNaCl if you're looking for a smaller code footprint. They provide strong encryption and should be much faster than RC4.

RC4 is a very simple algorithm to implement.

Check out Sterling Camden's implementation or Adam Back's implementation.

Pyromorphite answered 22/12, 2008 at 20:25 Comment(0)
D
4

See the ECRYPT eStream project. These are serious hardcore cryptographic algorithms judged by security experts. As far as I know all the candidate algorithms were required to include an implementation in pure C (not C++).

edit: The great thing about that website is it goes into a lot of depth about the different algorithms, including their known weaknesses, and includes performance benchmarks as well.

Daube answered 22/12, 2008 at 22:55 Comment(2)
They don't seem to be available yet, unless I just can't find the link.Apostrophize
The links are there but are nonstandard (no underlining) -- they are the items in the tables. (mouse over and you should see the cursor change for a link)Daube
C
2

For a pure POC application, you can quickly throw ROT13 into place. http://en.wikipedia.org/wiki/ROT13

However, I'm very hesitant in making the suggestion since too frequently simple POC code that's meant to be replaced later never is...

Coronary answered 22/12, 2008 at 19:44 Comment(2)
Yeah, I was hoping for something a little bit cryptographically stronger than Rot13 and I'm dealing with binary data not an ASCII byte stream.Apostrophize
3ROT128? :-) Sorry, couldn't help it. :-)Coronary
T
1

I got Blowfish going without much trouble. It claims to be faster than DES.

Toluidine answered 22/12, 2008 at 19:41 Comment(2)
Blowfish is a block cipher, not a stream cipher.Apostrophize
from wikipedia's en.wikipedia.org/wiki/Block_cipher : Stream ciphers can be built using block ciphers. OFB-mode and CTR mode are block modes that turn a block cipher into a stream cipher.Daube
D
1

Here is an extremely basic implementation of a stream cipher in C. It is not, by any means meant to be secure. It simply illustrates how to perform the basic steps required.

The real magic needs to be done in the CycleKey function, which generates new key values as each chunk of data is passed through the encryption stream.

This example encrypts one char at a time. You would have to extend the concept to larger chunks of data for the encryption to be anywhere near secure. Once again, I have done this simply to illustrate the basic steps.

Good luck with the project!

#include <stdio.h>

char staticKey;

void CycleKey(char data)
{
    /* this is where the real magic should occur */
    /* this code does *not* do a good job of it. */

    staticKey += data;

    if (staticKey & 0x80)
    {
        staticKey ^= 0xD8;
    }
    else
    {
        staticKey += 0x8B;
    }
}

void ResetCipher(const char * key)
{
    staticKey = 0;

    while (*key)
    {
        CycleKey(*key);
        key++;
    }
}

void Encrypt(const char * plaintext, char * encrypted)
{
    while (*plaintext)
    {
        *encrypted = *plaintext + staticKey;

        CycleKey(*encrypted);

        encrypted++;
        plaintext++;
    }

    *encrypted = '\0';
}

void Decrypt(char * plaintext, const char * encrypted)
{
    while (*encrypted)
    {
        *plaintext = *encrypted - staticKey;

        CycleKey(*encrypted);

        plaintext++;
        encrypted++;
    }

    *plaintext = '\0';
}

int main(void)
{
    char * key = "123";
    char * message = "Hello, World!";
    char encrypted[20];
    char decrypted[20];

    ResetCipher(key);
    Encrypt(message, encrypted);

    ResetCipher(key);
    Decrypt(decrypted, encrypted);

    printf("output: %s\n", decrypted);

    return 0;
}
Demonstrable answered 22/12, 2008 at 20:27 Comment(0)
S
0

Have you looked at OpenSSL? It has a secure implementation of a lot of cryptographic algorithms and primitives. You don't have to use it with anything network related. However, it's not really well documented or easy to learn. If you care a lot about security (for instance, if you are storing private user data such as credit cards) you should definitely use OpenSSL or some other secure implementation instead of rolling your own.

Skillless answered 22/12, 2008 at 19:34 Comment(1)
RC4 in OpenSSL may work. I was kind of hoping to just have an implementation of the cipher in a stand alone C file rather than a whole library to import though.Apostrophize
T
0

You can refer to the below code for understanding purpose. The code uses pseudo random number generator to generate key and purely written in C.

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

/* Function declarations */
int getSize(char *array);
int hashCode(const char *str, int size);
void convertIntToBinaryArray(int num, int *arr, int *index);
void encryptStreamCipher(int key[], int data[], int encypted_data[],int data_size);
void decryptStreamCipher(int key[], int enc_data[], int data_size);
void convertCharToBinary(char c,int *binary_arr,int *index);
void convertStringToBinary(char *str,int *binary_arr, int *size);
void convertBinaryToString(int *data,char *array_string,int *index);
char convertBinaryToChar(char *str);
void displayIntArray(int *array, int size);
void displayCharArray(char *array, int size);
#define MAX_SIZE 10000


int main(int argc, char **argv) {
    char array_string[MAX_SIZE];
    char ascii_key[MAX_SIZE];
    int data[MAX_SIZE];
    int key[MAX_SIZE];
    int encypted_data[MAX_SIZE];
    int seed;
    int key_int;
    int key_size = 0;
    int index;
    int data_size = 0;
    /* 1. Enter the data to encrypt (Do not use space in between)*/
    fprintf(stdout, "Enter data to encrypt: \n");
    fscanf(stdin, "%s", array_string);

    /* 2. Convert the string to binary data */
    convertStringToBinary(array_string,data,&data_size);
    printf("Data in binary: \n");
    displayIntArray(data,data_size);

    /* 3. Read the key string from user */
    fprintf(stdout, "Enter key to encrypt data with: \n");
    fscanf(stdin, "%s", ascii_key);

    /* 4.Get hash code from the key */
    key_size = getSize(ascii_key);
    seed = hashCode(ascii_key, key_size);

    /* 5. Set the key as seed to random number generator to create a key of random bits */
    srand(seed);
    key_int = rand();

    /* 6. Convert key to binary int array */
    convertIntToBinaryArray(key_int, key, &index);
    printf("Key in binary: \n");
    displayIntArray(key,index);

    /* 7. Encrypt : (Binary data) XOR (Binary key) */
    encryptStreamCipher(key, data, encypted_data, data_size);

    /* 8. Display encrypted data */
    printf("encrypted Data: \n");
    displayIntArray(encypted_data,data_size);

    /* 9.Now, Decrypt data and verify initial data */
    decryptStreamCipher(key, encypted_data, data_size);
    printf("Decrypted binary data: \n");
    displayIntArray(encypted_data,data_size);

    /* 10. Convert decrypted data in binary to string */
    memset(array_string,0,sizeof(array_string));
    convertBinaryToString(encypted_data,array_string,&data_size);

    /* 11.Display the original message in string */
    printf("Decrypted Data in String: \n");
    displayCharArray(array_string,data_size);

    return 0;
}

int getSize(char *array) {
    int size = 0;
    int i = 0;
    while ((i != MAX_SIZE) && (array[i] != '\0')) {
        i++;
        size++;
    }
    return size;
}

int hashCode(const char *str, int size) {
    int hash = 0;
    for (int i = 0; i < size; i++) {
        hash = 31 * hash + str[i];
    }
    return hash;
}

void convertIntToBinaryArray(int num, int *arr, int *index) {
    if (num == 0 || *index >= MAX_SIZE)
        return;
    convertIntToBinaryArray(num / 2, arr, index);
    if (num % 2 == 0)
        arr[(*index)++] = 0;
    else
        arr[(*index)++] = 1;

}

void encryptStreamCipher(int key[], int data[], int encypted_data[],
        int data_size) {
    for (int i = 0; i < data_size; i++) {
        encypted_data[i] = data[i] ^ key[i];
    }
}

void decryptStreamCipher(int key[], int enc_data[], int data_size) {
    for (int i = 0; i < data_size; i++) {
        enc_data[i] = enc_data[i] ^ key[i];
    }
}

void convertStringToBinary(char *str,int *binary_arr,int *index) {
    *index=0;
    for (int i = 0; i<strlen(str); i++) {
        convertCharToBinary(str[i],binary_arr,index);
    }
}

void convertCharToBinary(char c,int *binary_arr,int *index) {
    for (int i = 7; i >= 0; --i) {
        binary_arr[*index]=((c & (1 << i)) ? 1 : 0);
        (*index)++;
    }
}

void convertBinaryToString(int *data,char *array_string,int *index){
    int data_size=*index;
    char char_array[data_size];
    *index=0;

    for(int i=0;i<data_size;i++){
        char_array[i]=(data[i] == 1?'1':'0');
    }

    for(int i=0;i<data_size;i=i+8){
        char sub_str[8];
        memcpy(sub_str,char_array+i,8);
        array_string[(*index)++]=convertBinaryToChar(sub_str);
    }
}

char convertBinaryToChar(char *str){
    char c=strtol(str,0,2);
    return c;
}

void displayIntArray(int *array, int size)
{
    for (int i = 0; i < size; i++) {
        printf("%d",array[i]);
    }
    printf("\n");
}

void displayCharArray(char *array, int size)
{
    for (int i = 0; i < size; i++) {
        printf("%c",array[i]);
    }
    printf("\n");
}

Output:

Enter data to encrypt: prateekjoshi

Data in binary:

01110000011100100110000101110100011001010110010101101011011010100110111101110011011 0100001101001

Enter key to encrypt data with:

password

Key in binary:

101010100101110000101101000101

encrypted Data:

11011010001011100100110001100000011001010110010101101011011010100110111101110011011 0100001101001

Decrypted binary data:

01110000011100100110000101110100011001010110010101101011011010100110111101110011011 0100001101001

Decrypted Data in String:

prateekjoshi

Thicket answered 16/9, 2017 at 12:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.