web-dev-qa-db-ja.com

Cで文字列を暗号化するだけです

URLを開くときに作成しているゲームでクエリ文字列を暗号化しようとしています。複雑にする必要はありません。実際、私はゲームエンジンで作業しているので、できるだけ単純にする必要があります。レベルが低くなりすぎると大騒ぎする傾向があります。

クエリ文字列はすでに作成しているので、各文字を取得し、文字から15を引いて、軽く暗号化する必要があります。ほとんどのユーザーを思いとどまらせる単純な暗号化を作成したいだけです。

コード例を挙げられればいいのですが、Cの経験があまりなく、どこから始めればよいのかさえわかりません。ゲームエンジンのAPIを使用すると、通常、すべてが簡単になります。

7
Isaiah

これらの答えはどれも、実際にはいかなる形式の合理的な暗号化も構成していません。

実際に実行したいのは、何らかの形式の認証付き暗号化と、ある形式の安全な鍵導出アルゴリズムを使用することです。私の個人的な推奨事項は 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 */
}
_

これで、key-arrayには、上記のコードサンプルでの使用に適したキーが含まれています。ランダムキーを生成するためのrandombytes_buf(key, sizeof key)の代わりに、ユーザー定義のパスワードから派生したキーを生成し、それを暗号化に使用します。

3は3つのタイプの中で「最も複雑」です。これは、2つのパーティが通信している場合に使用するものです。各当事者は、公開鍵と秘密鍵を含む「鍵ペア」を生成します。これらのキーペアを使用すると、相互にデータを暗号化(および署名)するために使用できる「共有キー」について合意できます。

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

このコードは最初に両方のキーペアを生成します(通常、これはボブとアリスのマシンで別々に発生し、publicキーを保持しながら、お互いに送信します秘密鍵、まあ、秘密)。

次に、ランダムなナンスが生成され、crypto_box_easy(...)の呼び出しにより、メッセージがアリスからbobに暗号化されます(bobの公開鍵を使用して暗号化し、署名を作成するためのアリスの秘密鍵)。

次に(ネットワーク経由でメッセージを送信する可能性がある後)、crypto_box_open_easy(...)の呼び出しをbobが使用してメッセージを復号化します(自分の秘密鍵を使用して復号化し、アリスの公開鍵を使用して署名を検証します)。メッセージの検証が何らかの理由で失敗した場合(誰かがメッセージを改ざんしようとした場合)、これはゼロ以外の戻りコードで示されます。

18
sonOfRa

あなたの「暗号化」はだれもだましません。

オンラインで利用できる、よく知られた安全な暗号化アルゴリズムの優れた実装があります。

例: 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の長さを増やします。

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

関数名に注意してください。あなたがしたいことはばかげていて、かなり価値がありません。

6
San Jacinto

あなたは非常に単純な関数でそれを行うことができます:

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

興味があるかもしれない単純な暗号化アルゴリズムもあります。それは XOR暗号 と呼ばれます。

5
BlackBear

SonOfRaはすでに正しい答えを提案しています

しかし、実際に暗号化せずに文字列を不明瞭にするためにひどいものを使用するつもりなら、GNU Cライブラリは memfrob(3) を提供します。これはすでに作成されており、簡単に元に戻すことができます。

1
sarnold

必要に応じて、バイトを排他的論理和することができます
配列を反復処理し、^ =を使用することにより、これは復号化および暗号化されます

#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
Screwballer