Simply encrypt a string in C
Asked Answered
A

7

7

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.

Azilian answered 1/10, 2011 at 20:2 Comment(2)
XOR every byte with an arbitraty value to encrypt, do the same do decryptIntermediacy
For the sake of poor souls who will visit this question in search of a simple way to encrypt a string and try to copy and paste some code from the answers randomly I'll speak this out loud. Encoding is not encryption. Obscurity is not encryption. Some of the answers in this question are not encryption at all. Caution please.By
S
19

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.

Stable answered 19/7, 2017 at 16:46 Comment(1)
In case someone actually writes this code like this not understanding the security problems it has: Please, please store the password outside your executable. Otherwise someone can simply decompile it and easily find out. Probably you'd have to use some non-reversable way like a hash to generate a string from your password.Subspecies
M
9

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.

Mize answered 1/10, 2011 at 20:14 Comment(0)
H
6
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.

Hajji answered 1/10, 2011 at 20:7 Comment(5)
It's just for an online scoreboard. Once the score is received via query string it forwards away from it almost instantly. The query string is only seen for less than a second. I just wanted to deter the average user who wants to add a fake score or something. It's terrible but it fits the job I thinkAzilian
It doesn't matter for how many seconds the string is seen. It doesn't matter that 99% of the people won't get it. It only takes 1 user to screw up your scoreboard, doesn't it?Mize
Do what you want. I'm happy to help, and you've been warned. Carry on.Hajji
duly noted, I can always improve it later. The game is only alpha quality right now anyways and mostly I just want something going to get the scoreboard code working. How powerful is the XOR method?Azilian
Not excessively secure, but infintely better than rotating by 15. Just make sure to XOR every character with a different number or it will be as insecure as the simple rotation.Mize
F
5

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.

Fasciate answered 1/10, 2011 at 20:5 Comment(0)
B
2

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.

Brana answered 19/7, 2017 at 18:28 Comment(0)
A
0

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;
}
Allegra answered 22/8, 2018 at 21:37 Comment(0)
V
-2

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.

Virtuous answered 1/10, 2011 at 20:14 Comment(3)
I did a lot of research and think you're right. I got something going but then some things screwed up the url. Is there any resources around with some simplistic c base64 functions?Azilian
google.com/search?q=base64+implementation+c. The implementations I saw are pretty simple to understand.Virtuous
The problem with obfuscation-masquerading-as-encryption is that it gives a false sense of security. One day someone will rely on this being 'secure' and will run something important over it.Reformation

© 2022 - 2024 — McMap. All rights reserved.