Base64 形式の文字列を暗号化するアルゴリズム

Base64 形式の文字列を
暗号化するアルゴリズムを思いついたため
今回は紹介しようと思います。

役に立つかは不明ですが
面白いアルゴリズムだとは思いますので
知見を得るというよりは
このアルゴリズムを楽しむ事を目的として
閲覧して頂けると嬉しいです。

***

暗号化・複合化するコード

```csharp:暗号化・複合化するコード
public class MyEncrypter {
        public static string MyEncrypt(string rootBase64String)
        {
            string thinking = CreateMyKey();

            StringBuilder create = new();

            create.Append(rootBase64String[0]);

            for (int i = 1; i < rootBase64String.Length; i++)
            {
                if (rootBase64String[i] == '=')
                {
                    create.Append("=");
                    continue;
                }
                int index = thinking.IndexOf("" + create[i - 1]) + thinking.IndexOf("" + rootBase64String[i]);
                if (thinking.Length - 1 < index)
                {
                    index -= thinking.Length;
                }
                create.Append(thinking[index]);
            }

            return create.ToString();
        }

        public static string MyDecrypt(string encryptedBase64String)
        {
            string thinking = CreateMyKey();

            StringBuilder create = new();

            create.Append(encryptedBase64String[0]);

            for (int i = 1; i < encryptedBase64String.Length; i++)
            {
                if (encryptedBase64String[i] == '=')
                {
                    create.Append("=");
                    continue;
                }

                int index = thinking.IndexOf("" + encryptedBase64String[i]) - thinking.IndexOf("" + encryptedBase64String[i - 1]);

                if (index < 0)
                {
                    index += thinking.Length;
                }

                create.Append(thinking[index]);
            }

            return create.ToString();
        }

        //Base64 の文字を 64 文字・重複無しで並べた文字列を返します。
        private static string CreateMyKey()
        {
            System.Text.StringBuilder thinking = new("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");

            int nowCulc = 13241;

            for (int i = 0; i < 20000; i++)
            {
                int target1 = Math.Abs(nowCulc % 64);
                nowCulc *= 63;
                nowCulc += 15731;
                int target2 = Math.Abs(nowCulc % 64);
                nowCulc *= 59;
                nowCulc += 34721;
                char oneTime = thinking[target1];
                thinking[target1] = thinking[target2];
                thinking[target2] = oneTime;
            }

            return thinking.ToString();
        }
}
```

MyEncrypter.MyEncrypt(rootBase64String);

で暗号化します。

MyEncrypter.MyDecrypt(encryptedBase64String);

で暗号化した文字列を複合化します。

```csharp:使用例
string rootString = "o3Dgc+d";
string encriptString = MyEncrypter.MyEncrypt(rootString);
string resultString = MyEncrypter.MyDecrypt(encriptString);
bool isTheSame  = rootString == resultString; // true
```

と言った使い方です。

最初の 1 文字は同じで
2 文字目以降を
前の文字との差分で保存しています。

thinking 変数は Base64 の文字を
重複なく 64 文字入れて下さい。
順序はバラバラの方が
セキュリティが高いです。

thinking 変数が
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
と仮定すると

B の次が E ならば
CDE と 3 文字進んでるため
thinking[3] を保存しています。

b の次が h ならば
cdefgh と 6 文字進んでいるため
thinking[6] を保存しています。

MyEncrypt メソッドと
MyDecrypt メソッドの
thinking 変数は
同じ内容にする必要があります。

thinking 変数の内容は
AES のキーと同じように
隠すようにして下さい。

上記の例で言うと
int nowCulc = 13241;
の 13241 を隠すイメージです。

nowCulc += 15731;
等の数値部分も隠せると
もっと良いです。

任意の文字列を key にする場合は
下記のようなコードを
作成する必要があると思います。

下記のコードは
ハッシュコードの生成アルゴリズムに
自信がないため
確実に正常に動作するか分かりません。

文字列を一意の int に
100% 変換できる自信が無いのです。

具体的には文字コードなどの影響で
nowCulc *= (int)one;
の部分がぶれる気がしています。

下記のコードは参考程度に捉えて下さい。

```csharp:暗号化・複合化するコード
// こちらは CreateMyKey メソッドが正常に動作するか不明のため、参考程度に捉えて下さい。
public class MyEncrypter2 {
        public static string MyEncrypt(string rootBase64String, string key)
        {
            string thinking = CreateMyKey(key);

            StringBuilder create = new();

            create.Append(rootBase64String[0]);

            for (int i = 1; i < rootBase64String.Length; i++)
            {
                int index = thinking.IndexOf("" + create[i - 1]) + thinking.IndexOf("" + rootBase64String[i]);
                if (thinking.Length - 1 < index)
                {
                    index -= thinking.Length;
                }
                create.Append(thinking[index]);
            }

            return create.ToString();
        }

        public static string MyDecrypt(string encryptedBase64String, string key)
        {
            string thinking = CreateMyKey(key);

            StringBuilder create = new();

            create.Append(encryptedBase64String[0]);

            for (int i = 1; i < encryptedBase64String.Length; i++)
            {
                if (encryptedBase64String[i] == '=')
                {
                    continue;
                }

                int index = thinking.IndexOf("" + encryptedBase64String[i]) - thinking.IndexOf("" + encryptedBase64String[i - 1]);

                if (index < 0)
                {
                    index += thinking.Length;
                }

                create.Append(thinking[index]);
            }

            return create.ToString();
        }

        private static string CreateMyKey(string key)
        {
            System.Text.StringBuilder thinking = new("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");

            int nowCulc = 1;
            
            foreach (char one in key)
            {
                nowCulc *= (int)one;
                nowCulc += 17321;
            }

            for (int i = 0; i < 20000; i++)
            {
                int target1 = Math.Abs(nowCulc % 64);
                nowCulc *= 63;
                nowCulc += 15731;
                int target2 = Math.Abs(nowCulc % 64);
                nowCulc *= 61;
                nowCulc += 34721;
                char oneTime = thinking[target1];
                thinking[target1] = thinking[target2];
                thinking[target2] = oneTime;
            }

            return thinking.ToString();
        }
}
```

***

以上 Base64 形式の文字列を
同じ Base64 に暗号化する
アルゴリズムを紹介しました。

byte 配列は
Convert.ToBase64String メソッドで
Base64 に変換できるため
使える機会自体はあると思っています。

数値を Base64 として見るならば
数値も Base64 に暗号化できると言えます。その場合は
[数値を Base64 に圧縮するアルゴリズム](https://qiita.com/uni928/items/3773606705f12908e7b0) で
圧縮してから暗号化する方法もあります。

このアルゴリズムは
[このサイト](https://uni928.github.io/Base64Encrypter/) で試す事ができます。
よろしければ試してみて下さい。

コードを読んで
面白いと感じて頂いたならば
非常に嬉しいです。

皆さんがこの記事を楽しめますように。
閲覧ありがとうございました。