C对称流密码

时间:2008-12-22 19:27:59

标签: c encryption stream-cipher

有没有人能够很好地实现用纯便携式C编写的流密码?在这个时间点,我并不十分关心密码的强度,因为它只是用于概念验证,但速度很重要。如果我找不到合适的流密码,我一直在考虑使用常数Xor'ing。

7 个答案:

答案 0 :(得分:6)

编辑(2018):如果您正在寻找更小的代码占用空间,请使用NaCllibsodiumTweetNaCl。它们提供强大的加密,应该比RC4快得多。

RC4是一种非常简单的算法。

结帐Sterling Camden's implementationAdam Back's implementation

答案 1 :(得分:4)

请参阅ECRYPT eStream项目。这些是由安全专家评判的严肃的硬核加密算法。据我所知,所有候选算法都需要在纯C(而不是C ++)中包含一个实现。

编辑:该网站的优点在于它深入探讨了不同的算法,包括其已知的弱点,并且还包括performance benchmarks

答案 2 :(得分:2)

对于纯POC应用程序,您可以快速将ROT13投入到位。 http://en.wikipedia.org/wiki/ROT13

然而,我对提出这个建议非常犹豫,因为过于频繁的简单POC代码以后永远不会被替换......

答案 3 :(得分:1)

Blowfish没有遇到太多麻烦。它声称比DES快。

答案 4 :(得分:1)

这是C中流密码的一个非常基本的实现。,无论如何都是安全的。它只是说明了如何执行所需的基本步骤。

真正的魔法需要在CycleKey函数中完成,它会在每个数据块通过加密流时生成新的键值。

此示例一次加密一个char。您必须将概念扩展到更大的数据块,以便加密到接近安全的地方。我再次这样做只是为了说明基本步骤。

祝你好运!

#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;
}

答案 5 :(得分:0)

你看过OpenSSL吗?它具有许多加密算法和原语的安全实现。您不必将其与网络相关的任何内容一起使用。但是,它并没有很好的记录或易于学习。如果您非常关心安全性(例如,如果您要存储私人用户数据,如信用卡),您绝对应该使用OpenSSL或其他一些安全实施,而不是自己动手。

答案 6 :(得分:0)

出于理解目的,您可以参考以下代码。该代码使用伪随机数生成器生成密钥,纯粹用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");
}

<强>输出:

输入要加密的数据: prateekjoshi

二进制数据:

01110000011100100110000101110100011001010110010101101011011010100110111101110011011 0100001101001

输入密钥以使用以下方式加密数据:

密码

键入二进制文件:

101010100101110000101101000101

加密数据:

11011010001011100100110001100000011001010110010101101011011010100110111101110011011 0100001101001

解密的二进制数据:

01110000011100100110000101110100011001010110010101101011011010100110111101110011011 0100001101001

字符串中的解密数据:

prateekjoshi