8


3

整数IDの難読化手法

整数IDを難読化する簡単で可逆的な方法を探しています。 理想的には、結果として得られる難読化の長さは最大で8文字であり、非連続である必要があります。つまり、「1」の難読化は「2」などの難読化のようには見えません。

これは決して安全であることを意図したものではないため、これは大きな懸念事項ではありません。 また、難読化する整数は大きくありません(1〜10,000)が、衝突も必要ありません。

誰かがこの基準に合う何かのためのアイデアを持っていますか?

10 Answer


11


整数が約10,000個しかない場合、最も簡単で確実な方法は、おそらく整数とランダムに生成された文字列の間のマッピングテーブルでしょう。 各整数に対応するランダムな識別子を事前に生成するか、必要に応じてそれらを埋めます。

この方法により、衝突が発生しないことを保証できます。また、文字列は整数自体から導出されないため、暗号化を解除する必要がないため、暗号化について心配する必要はありません。

データベーステーブルまたはメモリに実装できます(例: 必要に応じて、双方向辞書)。


6


これは7か月前に尋ねられたので、あなたは今までに解決策を見つけたでしょうが、私が遭遇した解決策は、Skip32 / Skipjack暗号+ base32エンコードの組み合わせです。 perlの例(私が知っているので):

use Crypt::Skip32::Base32Crockford;
my $key    = pack( 'H20', "112233445566778899AA" ); # Always 10 bytes!
my $cipher = Crypt::Skip32::Base32Crockford->new($key);
my $b32    = $cipher->encrypt_number_b32_crockford(3493209676); # 1PT4W80
my $number = $cipher->decrypt_number_b32_crockford('1PT4W80'); # 3493209676

ac#の実装については知りませんが、perlの1つはhttp://search.cpan.org/perldoc?Crypt::Skip32::Base32Crockfordで、ルビーの2つの構成要素はhttps:// githubです。 com / levinalex / base32およびhttps://github.com/patdeegan/integer-obfuscator。 これら2つの間で、必要な言語に移植できるはずです。


5


ピアソンハッシュからアイデアを導き出しました。これは、32ビット整数だけでなく、任意の入力に対しても機能します。 これがグレッグの答えとまったく同じであるかどうかはわかりませんが、彼が何を意味するのか理解できませんでした。 しかし、私が知っていることは、メモリ要件がここで一定であることです。 入力がいくら大きくても、これは依然として信頼できる難読化/暗号化のトリックです。

レコードの場合、このメソッドはハッシュではなく、衝突はありません。 これは、バイト文字列を難読化する完全に適切な方法です。

これが機能するために必要なのは、0から255までの範囲のランダムな順列である秘密キー「_encryptionTable」です。 これを使用してバイトをシャッフルします。 リバースを非常に困難にするために、XORを使用してバイト文字列を少し混ぜます。

public byte[] Encrypt(byte[] plaintext)
{
    if (plaintext == null)
    {
        throw new ArgumentNullException("plaintext");
    }
    byte[] ciphertext = new byte[plaintext.Length];
    int c = 0;
    for (int i = 0; i < plaintext.Length; i++)
    {
        c = _encryptionTable[plaintext[i] ^ c];
        ciphertext[i] = (byte)c;
    }
    return ciphertext;
}

その後、BitConverterを使用して値とバイト配列の間を移動したり、ベース64または32に変換してテキスト表現を取得したりできます。 Base 32エンコードは、それが重要な場合、URLフレンドリーです。 復号化は、 `_encryptionTable`の逆数を計算することで操作を逆にするのと同じくらい簡単です。

    public byte[] Decrypt(byte[] ciphertext)
    {
        if (ciphertext == null)
        {
            throw new ArgumentNullException("ciphertext");
        }
        byte[] plaintext = new byte[ciphertext.Length];
        int c = 0;
        for (int i = 0; i < ciphertext.Length; i++)
        {
            plaintext[i] = (byte)(_decryptionTable[ciphertext[i]] ^ c);
            c = ciphertext[i];
        }
        return plaintext;
    }

また、32ビット整数で作業していて、0以上の数値のみに注意を払うと、難読化された数値を推測しにくくなる場合、他の楽しいこともできます。

また、秘密の単語を使用して擬似番号ジェネレータをシードし、それを使用して初期順列を設定します。 だからこそ、私はすべてのものを作成するために使用した秘密の言葉を知ることで、単純に価値を得ることができます。

var mt = new MersenneTwister(secretKey.ToUpperInvariant());
var mr = new byte[256];
for (int i = 0; i < 256; i++)
{
    mr[i] = (byte)i;
}
var encryptionTable = mt.NextPermutation(mr);
var decryptionTable = new byte[256];
for (int i = 0; i < 256; i++)
{
    decryptionTable[encryptionTable[i]] = (byte)i;
}
this._encryptionTable = encryptionTable;
this._decryptionTable = decryptionTable;

これはやや安全です。ここでの最大の欠点は、暗号化(XOR 0)がXORのアイデンティティであり、値を変更しないことです( a ^ 0 == a)。 したがって、最初の暗号化されたバイトは、そのバイトのランダムな位置を表します。 この問題を回避するには、PRNG(シードで初期化した後)にランダムバイトを要求するだけで、秘密キーに基づいて、定数ではない「c」の初期値を選択できます。 この方法では、入力と出力を監視できない限り、大規模なサンプルを使用しても暗号化を解読することは非常に困難です。


4


XORは、整数を難読化する便利で高速な方法です。

1 xor 1234 = 1235
2 xor 1234 = 1232
3 xor 1234 = 1233
100 xor 1234 = 1206
120 xor 1234 = 1194

それは高速で、同じ番号で再びxor-ingを実行すると元の値が返されます! 唯一の問題は、「攻撃者」が数字のいずれかを知っている場合、xorマスクを簡単に把握できることです…​ 結果を既知のオリジナルとxor-ingすることにより!

たとえば、そのリストの4番目の数字が難読化された「100」であるため、I(「攻撃者」)。 だから私はやる:

100 xor 1206 = 1234
  1. そして今、私はXORマスクを手に入れました。 数字です。 幸いなことに、その問題に対する些細な解決策があります。 XORマスクをアルゴリズム的に変更します。 たとえば、配列内の1000個の整数を難読化する必要がある場合は、XORマスク「1234」で開始し、arrrayの各数値に対して4でMASKをインクリメントします。


2


他の人々が興味を持っている場合、誰かが数年前に32ビットのブロック暗号を適応させました。これはこのタスクに特に役立ちます。

上記のPerlおよびRubyポートも利用可能です。

8文字以下の結果が必要な場合は、16進数またはbase64表現を使用できます。


1


2017年5月更新

私が開発したライブラリを自由に使用(または変更)してください。

_ インストールパッケージKent.Cryptography.Obfuscation _

これは、127などの非負のIDを_8文字の文字列_に変換します。 xVrAndNb、および戻る(生成されるたびにシーケンスをランダム化するためのいくつかの利用可能なオプション付き)。

使用例

var obfuscator = new Obfuscator();
string maskedID = obfuscator.Obfuscate(15);

完全なドキュメント:https://github.com/kendtimothy/Cryptography[Github]。

'' '' '

古い答え

古い答えに多様性を加えるだけです。 おそらく誰かがそれを必要とするでしょう。 これは、私がしばらく前に作成した難読化クラスです。

次の方法で使用できます。

Obfuscation obfuscation = new Obfuscation();
string maskedValue = obfuscation.Obfuscate(5);
int? value = obfuscation.DeObfuscate(maskedValue);

乾杯、うまくいけばそれが役に立つかもしれません。


1


ほとんどの言語のライブラリでそれを処理するための素晴らしいプロジェクト:http://hashids.org/


0


数字のビットパターンで遊ぶことができます-例えば、ビットを回転させたり交換したりします。 これにより、たとえば26ビットの数と、人間の観察者にはすぐにはわからない26ビットの別の数の間を移動することができます。 決して「安全」ではありませんが。


-1


これは古い投稿であることに気づきましたが、整数IDを難読化するためのテクニックを投稿すると役立つと思いました

短所:8文字以上を使用します。3300万未満のid値にのみ適しています

長所:難読化を解除するためのキーを必要とせず、URL / Cookieフレンドリーで、毎回異なる値を生成するため、壊れにくく、衝突が発生しません。上記の投稿はアドレスではなく、人々があなたのサイトを「スクレイプ」しようとしています。 id = 123で終わるURLが表示される場合、id = 124などを試すことができます…​ 追加のデータを取得するために、XORの例の一部が適切でない可能性が高い理由です)

公的に公開されている難読化手法を使用するべきではないと思うので、これを少し調整することをお勧めします(私はこれを自分用に行いました)。

ハッピーコーディング!

    public static string ObfuscateId(int id)
    {
        try
        {
            string rtn;
            int sid = id + 279;
            int xm = sid * 3;
            int xl = xm.ToString().Length + 10;
            string sc = xl.ToString().Substring(1, 1);
            string fc = xl.ToString().Substring(0, 1);
            string csum = sid.ToString().Substring(sid.ToString().Length - 3);
            rtn = Guid.NewGuid().ToString().Replace("-", "").ToLower();
            rtn = sc + rtn.Substring(2, 26) + fc;
            rtn = rtn.Remove(4, 3).Insert(4, csum);
            rtn = rtn.Remove(xl, (xl - 10)).Insert(xl, xm.ToString());
            rtn = rtn.Replace('1', 'g');
            rtn = rtn.Replace('2', 'h');
            rtn = rtn.Replace('3', 'i');
            rtn = rtn.Replace('4', 'w');
            rtn = rtn.Replace('5', 'y');
            rtn = rtn.Replace('6', 'u');
            rtn = rtn.Replace('7', 'z');
            rtn = rtn.Replace('8', 'l');
            rtn = rtn.Replace('9', 'v');
            rtn = rtn.Replace('0', 'n');
            rtn = rtn.Replace('c', 'j');
            rtn = rtn.Replace('d', 'p');
            rtn = rtn.Replace('f', 'q');

            return rtn.ToUpper();
        }
        catch
        {
            return "ERROR BAD ID";
        }
    }

    public static int DeObfuscateId(string obtxt)
    {
        try
        {
            string rtn;
            int id;

            rtn = obtxt.ToLower();
            rtn = rtn.Replace('g', '1');
            rtn = rtn.Replace('h', '2');
            rtn = rtn.Replace('i', '3');
            rtn = rtn.Replace('w', '4');
            rtn = rtn.Replace('y', '5');
            rtn = rtn.Replace('u', '6');
            rtn = rtn.Replace('z', '7');
            rtn = rtn.Replace('l', '8');
            rtn = rtn.Replace('v', '9');
            rtn = rtn.Replace('n', '0');
            rtn = rtn.Replace('j', 'c');
            rtn = rtn.Replace('p', 'd');
            rtn = rtn.Replace('q', 'f');

            string sc = rtn.Substring(0, 1);
            string fc = rtn.Substring(rtn.Length - 1);
            int xl = int.Parse(fc + sc);
            int mv = int.Parse(rtn.Substring(xl, (xl - 10)));
            int sid = mv / 3;
            id = sid - 279;
            string csum = sid.ToString().Substring(sid.ToString().Length - 3);
            string xsum = rtn.Substring(4, 3);

            if (csum!=xsum)
            {
                return -99999;
            }

            return id;
        }
        catch
        {
            return -99999;
        }
    }

}


-2


整数のバイト表現のMD5 / SHA1ハッシュを取得するだけです。 衝突しないことが保証されています。