Просто зашифруйте строку в C - PullRequest
7 голосов
/ 02 октября 2011

Я пытаюсь зашифровать строку запроса в игре, которую я создаю при открытии URL.Это не должно быть сложным, на самом деле, поскольку я работаю с игровым движком, оно должно быть максимально простым.Это имеет тенденцию суетиться, если я получаю слишком низкий уровень.

Я уже создал строку запроса, мне просто нужно взять каждый символ из него и вычесть 15 из символа, чтобы слегка зашифровать его.Я просто хочу сделать простое шифрование, которое будет сдерживать большинство пользователей.

Я хотел бы привести пример кода, но я не слишком опытен в C, и я даже не уверенс чего начать. API игрового движка обычно делает все простым для меня.

Ответы [ 7 ]

17 голосов
/ 19 июля 2017

Ни один из этих ответов на самом деле не представляет собой какую-либо форму разумного шифрования.

Что вы на самом деле хотите сделать, так это использовать некоторую форму аутентифицированного шифрования и некоторую форму алгоритма создания безопасного ключа.Моя личная рекомендация libsodium .Он обеспечивает очень хорошие значения по умолчанию и API, который относительно сложно ошибиться.

Есть несколько различных способов сделать это:

  1. Шифрование секретным ключом со случайным ключом Шифрование с проверкой подлинности
  2. Шифрование секретным ключом с помощью ключа, полученного из ключевой фразы Получение ключа
  3. Гибридное шифрование с соглашением о ключах. Шифрование с открытым ключом

Все эти возможности интегрированы в libsodium и реализуются с относительной легкостью.

Следующие примеры кода взяты непосредственно из документация libsodium .

для 1:

#define MESSAGE ((const unsigned char *) "test")
#define MESSAGE_LEN 4
#define CIPHERTEXT_LEN (crypto_secretbox_MACBYTES + MESSAGE_LEN)

unsigned char nonce[crypto_secretbox_NONCEBYTES];
unsigned char key[crypto_secretbox_KEYBYTES];
unsigned char ciphertext[CIPHERTEXT_LEN];

/* Generate a secure random key and nonce */
randombytes_buf(nonce, sizeof nonce);
randombytes_buf(key, sizeof key);
/* Encrypt the message with the given nonce and key, putting the result in ciphertext */
crypto_secretbox_easy(ciphertext, MESSAGE, MESSAGE_LEN, nonce, key);

unsigned char decrypted[MESSAGE_LEN];
if (crypto_secretbox_open_easy(decrypted, ciphertext, CIPHERTEXT_LEN, nonce, key) != 0) {
    /* If we get here, the Message was a forgery. This means someone (or the network) somehow tried to tamper with the message*/
}

для 2: (извлечение ключа из пароля)

#define PASSWORD "Correct Horse Battery Staple"
#define KEY_LEN crypto_secretbox_KEYBYTES

unsigned char salt[crypto_pwhash_SALTBYTES];
unsigned char key[KEY_LEN];

/* Choose a random salt */
randombytes_buf(salt, sizeof salt);

if (crypto_pwhash
    (key, sizeof key, PASSWORD, strlen(PASSWORD), salt,
     crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE,
     crypto_pwhash_ALG_DEFAULT) != 0) {
    /* out of memory */
}

Теперь массив ключейсодержит ключ, который подходит для использования в приведенном выше примере кода.Вместо randombytes_buf(key, sizeof key) для генерации случайного ключа мы сгенерировали ключ, полученный из пользовательского пароля, и используем его для шифрования.

3 - «самый сложный» из 3 типов.Это то, что вы используете, если две стороны общаются.Каждая из сторон генерирует «пару ключей», которая содержит открытый и секретный ключи.С этими парами ключей они могут вместе договориться о «общем ключе», который они могут использовать для шифрования (и подписывания) данных друг для друга:

#define MESSAGE (const unsigned char *) "test"
#define MESSAGE_LEN 4
#define CIPHERTEXT_LEN (crypto_box_MACBYTES + MESSAGE_LEN)

unsigned char alice_publickey[crypto_box_PUBLICKEYBYTES];
unsigned char alice_secretkey[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(alice_publickey, alice_secretkey);

unsigned char bob_publickey[crypto_box_PUBLICKEYBYTES];
unsigned char bob_secretkey[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(bob_publickey, bob_secretkey);

unsigned char nonce[crypto_box_NONCEBYTES];
unsigned char ciphertext[CIPHERTEXT_LEN];
randombytes_buf(nonce, sizeof nonce);
if (crypto_box_easy(ciphertext, MESSAGE, MESSAGE_LEN, nonce,
                    bob_publickey, alice_secretkey) != 0) {
    /* error */
}

unsigned char decrypted[MESSAGE_LEN];
if (crypto_box_open_easy(decrypted, ciphertext, CIPHERTEXT_LEN, nonce,
                         alice_publickey, bob_secretkey) != 0) {
    /* message for Bob pretending to be from Alice has been forged! */
}

Этот код сначала генерирует обе пары ключей (обычно это происходитна машине Боба и Алисы по отдельности, и они посылали друг другу свой открытый ключ, сохраняя при этом свой секретный ключ, ну, в общем, секрет).

Затем генерируется случайный одноразовый номер, ивызов crypto_box_easy(...) шифрует сообщение от Алисы к Бобу (используя открытый ключ Боба для шифрования и секретный ключ Алисы для создания подписи).

Затем (после возможной отправки сообщения черезсеть), вызов crypto_box_open_easy(...) используется Бобом для расшифровки сообщения (используя его собственный секретный ключ для расшифровки и открытый ключ Алисы для проверки подписи).Если проверка сообщения по какой-то причине не удалась (кто-то пытался ее подделать), это указывается ненулевым кодом возврата.

9 голосов
/ 02 октября 2011

Ваше "шифрование" никого не обманет.

В сети есть хорошие реализации известных и безопасных алгоритмов шифрования.

Например: Twofish

Edit:

Пример реализации XOR:

void encrypt(char *array, int array_size)
{
    int i;
    char secret[8] = { 22, 53, 44, 71, 66, 177, 253, 122 };
    for(i = 0; i < array_size; i++)
        array[i] ^= secret[i];
}

Предполагается, что массив, содержащий строку запроса, имеет длину 8 или менее байтов. Увеличьте длину secret, чтобы удовлетворить ваши потребности.

6 голосов
/ 02 октября 2011
void doTerribleEncryptionMethod(char * arr, int arrSize)
{
    int i;
    for(i = 0; i < arrSize; i++)
    {
      arr[i] -= 15;
    }
}

Обратите внимание на название функции. То, что вы хотите сделать, глупо и довольно бесполезно.

5 голосов
/ 02 октября 2011

Вы можете сделать это с очень простой функцией:

void encrypt(char *s)
{
    int i, l = strlen(s);
    for(i = 0; i < l; i++)
        s[i] -= 15;
}

Существует также простой алгоритм шифрования, который может вас заинтересовать, он называется XOR cipher .

1 голос
/ 19 июля 2017

SonOfRa уже предложил правильный ответ .

Но если вы намереваетесь использовать что-то ужасное, чтобы скрыть строку без фактического шифрования это, библиотека GNU C предоставляет memfrob(3), который уже написан и легко обратим.

0 голосов
/ 23 августа 2018

если хотите, вы можете просто перезаписать байты
, перебирая массив и используя ^ =, который расшифровывает и шифрует

#include <string.h>
char* xorit(char* str, int key){ // any number for key except 
  for(int i=0; i<strlen(str);i++){
      str[i] ^= key; 
  }
  return str;
}
0 голосов
/ 02 октября 2011

Вы можете использовать вариант base64 с пользовательским алфавитом или просто перетасованным алфавитом. Это не совсем безопасно, но в вашем случае этого вполне достаточно. Алгоритм широко используется, поэтому вам будет легко найти реализацию, в которой вы можете предоставить собственный алфавит.

Бонус в том, что независимо от того, что вы введете в строку запроса, закодированная форма будет состоять из действительных символов URL, если вы правильно выберете алфавит.

...