可逆的なシャッフルアルゴリズムキーを使用
質問
方法を教えてくださいコードの可逆的なシャッフルアルゴリズムをC#ソースコードを使用するキーやシャッフルで元に戻すことができるのですか。
たとえば、文字列:"こんにちは世界"をしたいのでシャッフルのように降っきを逆にシャッフルの文字列に戻る"こんにちはます。
解決
見 フィッシャー-イェイツシャッフル しなければならないというニーズpermuteの文字列に基づくキーとなります。飼料のキーとして、シーズPRNG、この乱数の使用を選択することができます
どのように逆転しですか?フィッシャー-イェイツの作品の入れ替える対の要素の集まりです。う逆転の過程での発送と同じキーを同じPRNG、その後のフィッシャー-イェイツのアルゴリズム している場合 またシャッフリング配列のサイズの文字列になります。うまいものだけを記録し、指数の要素がこの交換が完了するように設定します。
お客さま人数小児-幼児に行われ、この実行を通じてリストのスワップ取引 逆に, を応用して、シャッフル文字列になります。その結果、元の文字列になります。
したがって、たとえば、うまシャッフル文字列"こんにちは"のスワップ(まだ使PRNGここでは、巻きダイス、その点につPRNGができ、同じ系列の番号と同じ種子):
(4,0): "hello" -> "oellh"
(3,3): "oellh" -> "oellh"
(2,1): "oellh" -> "olelh"
(1,0): "olelh" -> "loelh"
なので、シャッフルの文字列は、"loelh".
にdeshuffle、生と同じシリーズ"ランダムに"数字,0,3,1,0です。そして、スワップを逆順:
(1,0): "loelh" -> "olelh"
(2,1): "olelh" -> "oellh"
(3,3): "oellh" -> "oellh"
(4,0): "oellh" -> "hello"
あなた方の成功を意味する。
下振れのこのコースを利用する場合は、その多くのメモリーのdeshuffle:配列のインデックスなどオリジナルの配列のchar.そのために本当に巨大な配列するために選択PRNGはとにかく、シーケンス生成機能)できる段差のいずれかに転送又は逆なの店舗のすべての出力に出力します。はこのハッシュに基づく暗号法論的には安全PRNGsがLFSRsは可逆的である。
ちなみに、なぜださい。
他のヒント
こちらは簡単な実施に必要な場合はログインしてくださ):
public static class ShuffleExtensions
{
public static int[] GetShuffleExchanges(int size, int key)
{
int[] exchanges = new int[size - 1];
var rand = new Random(key);
for (int i = size - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
exchanges[size - 1 - i] = n;
}
return exchanges;
}
public static string Shuffle(this string toShuffle, int key)
{
int size = toShuffle.Length;
char[] chars = toShuffle.ToArray();
var exchanges = GetShuffleExchanges(size, key);
for (int i = size - 1; i > 0; i--)
{
int n = exchanges[size - 1 - i];
char tmp = chars[i];
chars[i] = chars[n];
chars[n] = tmp;
}
return new string(chars);
}
public static string DeShuffle(this string shuffled, int key)
{
int size = shuffled.Length;
char[] chars = shuffled.ToArray();
var exchanges = GetShuffleExchanges(size, key);
for (int i = 1; i < size; i++)
{
int n = exchanges[size - i - 1];
char tmp = chars[i];
chars[i] = chars[n];
chars[n] = tmp;
}
return new string(chars);
}
}
使用量:
var originalString = "Hello world";
var shuffled = originalString.Shuffle(123);
var deShuffled = shuffled.DeShuffle(123);
// shuffled = "lelooH rwld";
// deShuffled = "Hello world";
のキーでなければな整数値を使用する場合、それらの文字列としてパスワードを呼び出すだGetHashCode()かれています。
var shuffled = originalString.Shuffle(myStringKey.GetHashCode());
編集:
今まさに、フィッシャー–イェイツシャッフルアルゴリズムの実装です。コJeffのための このコード
すでに以下の質問で答えなのです。暗号化/復号化文字列です。当期純
Javaの質問にもリダイレクトはここ、ここは暗号強度のjava実装:
import java.security.*;
import java.util.*;
/** Cryptographic strength reversible random shuffle. To be truly secure, the passKey arguments should be 20 chars or more and (obviously) not guessable. */
public class SecureShuffle
{
public static int[] getShuffleExchanges(int size, String passKey)
{
int[] exchanges = new int[size - 1];
SecureRandom rand = new SecureRandom(passKey.getBytes());
for (int i = size - 1; i > 0; i--)
{
int n = rand.nextInt(i + 1);
exchanges[size - 1 - i] = n;
}
return exchanges;
}
public static void shuffle(byte[] toShuffle, String passKey)
{
int size = toShuffle.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = size - 1; i > 0; i--)
{
int n = exchanges[size - 1 - i];
byte tmp = toShuffle[i];
toShuffle[i] = toShuffle[n];
toShuffle[n] = tmp;
}
}
public static void deshuffle(byte[] shuffled, String passKey)
{
int size = shuffled.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = 1; i < size; i++)
{
int n = exchanges[size - i - 1];
byte tmp = shuffled[i];
shuffled[i] = shuffled[n];
shuffled[n] = tmp;
}
}
public static void shuffle(char[] toShuffle, String passKey)
{
int size = toShuffle.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = size - 1; i > 0; i--)
{
int n = exchanges[size - 1 - i];
char tmp = toShuffle[i];
toShuffle[i] = toShuffle[n];
toShuffle[n] = tmp;
}
}
public static void deshuffle(char[] shuffled, String passKey)
{
int size = shuffled.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = 1; i < size; i++)
{
int n = exchanges[size - i - 1];
char tmp = shuffled[i];
shuffled[i] = shuffled[n];
shuffled[n] = tmp;
}
}
public static void shuffle(int[] toShuffle, String passKey)
{
int size = toShuffle.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = size - 1; i > 0; i--)
{
int n = exchanges[size - 1 - i];
int tmp = toShuffle[i];
toShuffle[i] = toShuffle[n];
toShuffle[n] = tmp;
}
}
public static void deshuffle(int[] shuffled, String passKey)
{
int size = shuffled.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = 1; i < size; i++)
{
int n = exchanges[size - i - 1];
int tmp = shuffled[i];
shuffled[i] = shuffled[n];
shuffled[n] = tmp;
}
}
public static void shuffle(long[] toShuffle, String passKey)
{
int size = toShuffle.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = size - 1; i > 0; i--)
{
int n = exchanges[size - 1 - i];
long tmp = toShuffle[i];
toShuffle[i] = toShuffle[n];
toShuffle[n] = tmp;
}
}
public static void deshuffle(long[] shuffled, String passKey)
{
int size = shuffled.length;
int[] exchanges = getShuffleExchanges(size, passKey);
for (int i = 1; i < size; i++)
{
int n = exchanges[size - i - 1];
long tmp = shuffled[i];
shuffled[i] = shuffled[n];
shuffled[n] = tmp;
}
}
public static void main(String[] args)
{
String passphrase = "passphrase";
String text = "The rain in Spain stays mainly on the plain";
char[] chars = text.toCharArray();
shuffle(chars, passphrase);
System.out.println(new String(chars));
deshuffle(chars, passphrase);
System.out.println(new String(chars));
byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};
shuffle(bytes, passphrase);
System.out.println(Arrays.toString(bytes));
deshuffle(bytes, passphrase);
System.out.println(Arrays.toString(bytes));
}
}