2

C# で文字列を暗号化しようとしています。

static public string Encrypt(char[] a)
{
    for (int i = 0; i < a.Length; i++)
    {
        a[i] -= (char)(i + 1);
        if (a[i] < '!')
        {
            a[i] += (char)(i + 20);
        }
    }
    return new string(a);
}

さて、この文字列を入れると:

"Qui habite dans un ananas sous la mer?".

暗号化は次のようになります。

`Psf3c[[ak[3XT`d3d\3MYKWIZ3XSXU3L@?JAMR`

@ の後に認識できない文字があります。どうやってそこにたどり着いたのか、理由もわかりません。

復号化しようとすると(この方法を使用して:)

static public string Decrypt(char[] a)
{
    for (int i = 0; i < a.Length; i++)
    {
        a[i] += (char)(i + 1);
        if ((a[i] - 20) - i <= '!')
        {
           a[i] -= (char)(i + 20);
        }
    }
    return new string(a);
}

これは(間違った)出力です:

Qui habete dans un ananas sous laamerx.

暗号化ルーチンが Unicode 文字にアクセスできるようにするにはどうすればよいですか?

4

3 に答える 3

5

印刷できない文字が表示される理由は、次の行です。

a[i] -= (char)(i + 1);

何が起こっているかというと、内部のスペースla merは文字列の 34 番目の位置であり、スペースの同等の整数値は 0x20 = 32 です。これは、減算(i+1)すると -2 になることを意味します。しかし、結果を に格納しています。charこれは符号なしの型であるため、実際には 0xFFFE = 65534 になります。その後、テストa[i] < '!'すると false になりますa[i]

代わりに、(このアルゴリズムを本当に実装したい場合) すべきことは、結果を符号付きの型に格納し、実行しているように操作して、最後に char に変換することです。

    int value = (int)a[i] - (i + 1);
    if (value < (int)'!')
    {
        value += i + 20;
    }
    a[i] = (char)value;

(強調のための追加の型キャスト。)

必要ないかもしれませんが、メソッドでも同じパターンを使用することをお勧めしDecryptます。一般に、一時変数で機能するコードについて推論する方が、その場で編集するよりもはるかに簡単です。

于 2015-06-10T00:46:13.460 に答える
1

一般に、最新の暗号化では、文字には注意を払いません (何もない場合もあります。画像や音声ファイルを暗号化している場合もあります)。バイトには注意を払います。

同じアプローチを取ることができます。特定のエンコーディング (UTF-8 が適しています) でテキストからバイトのストリームを取得し、それに対して暗号化を行います。

暗号化されたバイトが出力になります。書き留めることができるものが必要な場合は、base-64 を使用してテキスト表現を生成できます。

それは難しい部分であり、実際の使用では、確立された十分にテストされた暗号化スキームを使用するため、暗号化はまだあまり良くありませんが、非のような違法な Unicode シーケンスを生成しない実行可能なアプローチがあります。 -文字または不一致のサロゲート。

于 2015-06-10T03:23:38.550 に答える