简单地用C加密一个字符串

发布于 2024-12-07 11:05:21 字数 259 浏览 0 评论 0原文

我正在尝试在打开网址时对我正在制作的游戏上的查询字符串进行加密。它不必很复杂,事实上,因为我正在使用游戏引擎,所以它需要尽可能简单。如果我的等级太低,它往往会大惊小怪。

我已经创建了查询字符串,我只需要获取它的每个字符并从该字符中减去 15 即可对其进行轻微加密。我只是想做一个简单的加密来阻止大多数用户。

我希望能给出一个代码示例,但我在 C 方面不太有经验,我什至不知道从哪里开始。 游戏引擎的 api 通常让一切对我来说都很简单。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

何其悲哀 2024-12-14 11:05:21

这些答案都没有真正构成任何形式的合理加密。

您真正想要做的是使用某种形式的身份验证加密和某种形式的安全密钥派生算法。我个人的推荐是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! */
}

此代码首先生成两个密钥对(通常,这会分别发生在 bob 和 alice 的机器上,并且他们会向对方发送他们的公钥,同时保留他们的秘密密钥(嗯,秘密)。

然后,生成随机数,并且调用 crypto_box_easy(...) 加密从 alice 到 bob 的消息(使用 bob 的公钥进行加密,并使用 alice 的秘密)进行签名的密钥)。

然后(可能通过网络发送消息之后),bob 使用对 crypto_box_open_easy(...) 的调用来解密消息(使用他自己的密钥进行解密,并使用 alice 的公钥来解密)验证签名)。如果消息验证由于某种原因失败(有人试图篡改消息),则由非零返回代码指示。

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.

孤独岁月 2024-12-14 11:05:21

你的“加密”不会欺骗任何人。

网上有众所周知的安全加密算法的良好实现。

例如: Twofish

编辑:

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 的长度以满足您的需求。

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.

温柔戏命师 2024-12-14 11:05:21
void doTerribleEncryptionMethod(char * arr, int arrSize)
{
    int i;
    for(i = 0; i < arrSize; i++)
    {
      arr[i] -= 15;
    }
}

注意函数名称。你想做的事情很愚蠢,而且毫无价值。

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.

最后的乘客 2024-12-14 11:05:21

您可以使用一个非常简单的函数来完成此操作:

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

还有一个您可能感兴趣的简单加密算法,它称为 异或密码

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.

半步萧音过轻尘 2024-12-14 11:05:21

SonOfRa 已经提出了正确的答案

但是,如果您打算使用一些可怕的东西来模糊字符串而不实际加密它,GNU C 库提供了die.net/man/3/memfrob" rel="nofollow noreferrer">memfrob(3) 已编写且易于逆转。

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.

一人独醉 2024-12-14 11:05:21

如果你愿意,你可以对字节进行异或
通过迭代数组并使用 ^=
这解密和加密

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

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;
}
仅一夜美梦 2024-12-14 11:05:21

您可以使用带有自定义字母表的 base64 变体,或者只是打乱顺序的字母表。它并不真正安全,但就您的情况而言可能就足够了。该算法被广泛使用,因此您可以轻松找到可以提供自定义字母表的实现。

额外的一点是,无论您在查询字符串中输入什么,如果您正确选择字母表,编码形式都将包含有效的 URL 字符。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文