C对称流密码

6

有没有人在纯可移植C语言中实现了一个好的流密码?我目前并不特别关注密码的强度,因为这只是一个概念验证,但速度很重要。如果找不到一个合适的流密码,我考虑使用常数进行Xor操作。

7个回答

6

4

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

编辑:该网站的好处是它深入探讨了不同算法,包括它们已知的弱点,并且还包括性能基准测试


除非我找不到链接,否则它们似乎还没有可用。 - Steven Behnke
链接已经存在,但是它们不太标准(没有下划线)——它们是表格中的项目。(将鼠标悬停在上面,您应该会看到光标变成链接) - Jason S

2

对于一种纯粹的POC应用程序,您可以快速使用ROT13。 http://en.wikipedia.org/wiki/ROT13

然而,我非常犹豫地提出建议,因为经常会发现旨在稍后替换的简单POC代码从未被替换...


是的,我希望得到比Rot13更强的加密方式,而且我正在处理二进制数据而不是ASCII字节流。 - Steven Behnke
1
3ROT128? :-) 对不起,我忍不住了。 :-) - Brian Knoblauch

1

我很容易就让Blowfish运行起来了。它声称比DES更快。


Blowfish是一个块密码算法,而不是流密码算法。 - Steven Behnke
流密码可以使用块密码构建。OFB模式和CTR模式是将块密码转换为流密码的块模式。 - Jason S

1
这里是在C语言中实现流密码(stream cipher)的极其基本的例子。它绝不是用来保密的,只是表明了如何执行基本步骤。
真正的魔法需要在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;
}

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

输入用于加密数据的密钥:

password

密钥的二进制表示:

101010100101110000101101000101

加密后的数据:

11011010001011100100110001100000011001010110010101101011011010100110111101110011011 0100001101001

解密后的二进制数据:

01110000011100100110000101110100011001010110010101101011011010100110111101110011011 0100001101001

解密后的字符串数据:

prateekjoshi


0

你看过OpenSSL吗?它有很多密码算法和基元的安全实现。你不必将其与任何网络相关的东西一起使用。然而,它的文档不是很好,也不容易学习。如果你非常关心安全(例如,如果你正在存储私人用户数据,如信用卡),你应该绝对使用OpenSSL或其他安全实现,而不是自己编写。


RC4在OpenSSL中可能有效。我有点希望只是有一个独立的C文件实现密码而不是整个需要导入的库。 - Steven Behnke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接