开发者

Simply encrypt a string in C

I'm trying to encrypt a query string on a game I'm making when opening a url. It doesn't have to be complicated, in fact since I'm working from a game engine 开发者_开发百科it needs to be as simple as possible. It tends to fuss if I get too low level.

I've already created the query string, I just need to take each char of it and subtract 15 from the char to lightly encrypt it. I'm just wanting to make a simple encryption that will deter most users.

I wish I could give a code example but I'm not too experienced in C, and I'm not even sure where to begin. The game engine's api usually makes everything simple for me.


None of these answers really constitute any form of reasonable encryption.

What you actually want to do, is use some form of authenticated encryption, and some form of secure key derivation algorithm. My personal recommendation is libsodium. It provides very good defaults, and an API that is relatively hard to get wrong.

There's several different ways to do this:

  1. Secret key encryption with a random key Authenticated Encryption
  2. Secret key encryption with a key derived from a passphrase Key Derivation
  3. Hybrid encryption with Key Agreement. Public Key Encryption

All of these possibilities are integrated into libsodium and implementable with relative ease.

The following code examples are taken directly from the libsodium documentation.

For 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*/
}

For 2: (Deriving a key from a password)

#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 */
}

Now, the key-array contains a key that is suitable for the use in the code sample above. Instead of randombytes_buf(key, sizeof key) for generating a random key, we generated a key derived from a user-defined password, and use that for encryption.

3 is the "most complicated" of the 3 types. It is what you use if you have two parties communicating. Each of the parties generates a "keypair", which contains a public and a secret key. With those keypairs, they can together agree on a "shared key" that they can use for encrypting (and signing) data for each other:

#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! */
}

This code first generates both keypairs (typically, this would happen on bob's and alice's machine separately, and they would send each other their public key, while keeping their secret key, well, secret).

Then, a random nonce is generated, and the call to crypto_box_easy(...) encrypts a message from alice to bob (using bob's public key to encrypt, and alice's secret key to make a signature).

Then (after potentially sending the message over the network), the call to crypto_box_open_easy(...) is used by bob to decrypt the message (using his own secret key to decrypt, and alice's public key to verify the signature). If the verification of the message failed for some reason (someone tried to tamper with it), this is indicated by the non-zero return code.


Your "encryption" won't fool anybody.

There are good implementatons of well-known and secure encryption algorithms available online.

For example: Twofish

Edit:

Example implementation of 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];
}

Assumes that the array containing the query string is 8 or less bytes long. Increase the length of secret to meet your needs.


void doTerribleEncryptionMethod(char * arr, int arrSize)
{
    int i;
    for(i = 0; i < arrSize; i++)
    {
      arr[i] -= 15;
    }
}

Notice the function name. What you want to do is silly, and pretty worthless.


You can do it with a very simple function:

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

There's also a simple encryption algorithm you may be interested in, it's called XOR cipher.


SonOfRa already proposed the right answer.

But if you're intent on using something terrible to obscure a string without actually encrypting it, the GNU C library provides a memfrob(3) that is already-written and easily reversible.


if you want to, you can just xor the bytes
by iterating through the array and using ^= this decrypts and encrypts

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


You can use a variant of base64 with a custom alphabet, or just a shuffled alphabet. It's not really secure, but in your case it is probably sufficient. The algorithm is widely used, so it will be easy for you to find an implementation where you can provide a custom alphabet.

The bonus point is, that whatever you put into the query string, the encoded form will consist of valid URL characters, if you choose the alphabet appropriately.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜