У кого-нибудь есть хорошая реализация потокового шифра, написанная на чистом портативном C? На данный момент меня не очень беспокоит надежность шифра, потому что он нужен только для проверки концепции, но важна скорость. Я подумал о том, чтобы просто Xor'ировать с константой, если я не могу найти приличный потоковый шифр.
Симметричный потоковый шифр C
Ответы (7)
РЕДАКТИРОВАТЬ (2018 г.): используйте NaCl или libsodium или TweetNaCl если вы ищете меньший размер кода. Они обеспечивают надежное шифрование и должны быть намного быстрее, чем RC4.
RC4 — это очень простой для реализации алгоритм.
Ознакомьтесь с реализацией Sterling Camden или реализация Адама Бэка.
См. проект ECRYPT eStream. Это серьезные хардкорные криптографические алгоритмы, оцененные экспертами по безопасности. Насколько я знаю, все алгоритмы-кандидаты должны были включать реализацию на чистом C (не C++).
edit: Самое замечательное в этом веб-сайте то, что он подробно рассказывает о различных алгоритмах, включая их известные слабости, и включает контрольные показатели эффективности.
Для чистого POC-приложения можно быстро поставить ROT13 на место. http://en.wikipedia.org/wiki/ROT13
Тем не менее, я очень не решаюсь сделать предложение, поскольку слишком часто простой код POC, который должен быть заменен позже, никогда не бывает...
Я получил Blowfish без особых проблем. Он утверждает, что работает быстрее, чем DES.
Вот чрезвычайно простая реализация потокового шифра на языке 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;
}
Вы смотрели на OpenSSL? Он имеет безопасную реализацию множества криптографических алгоритмов и примитивов. Вам не нужно использовать его с чем-либо, связанным с сетью. Тем не менее, он не очень хорошо документирован или прост в освоении. Если вы очень заботитесь о безопасности (например, если вы храните личные пользовательские данные, такие как кредитные карты), вам определенно следует использовать OpenSSL или какую-либо другую безопасную реализацию вместо создания собственной.
Вы можете обратиться к приведенному ниже коду для понимания цели. Код использует генератор псевдослучайных чисел для генерации ключа и написан исключительно на 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
Расшифрованные данные в строке:
пратекджоши