見出し画像

④エニグマ暗号機のローター結線解読プロジェクト(コードを変更するも...)

プログラムの意味は分かるものの、まだ偶然性に頼っている。
もう少し、自分で群論を勉強してみますか。
以下はサンプルとして残しておくが、再チャレンジだ。


2文字ずつの置換を優先的に生成するようにアルゴリズムを修正することを検討できますか。 その結果をPrintできますか

質問プロンプト

もちろんです。2文字ずつの置換(つまり、2-サイクル)を優先的に生成するようにアルゴリズムを修正することは、非常に良いアイデアです。これにより、より現実的な暗号システムのモデルに近づくことができます。

回答
(* Define helper functions *)
cycleStructure[perm_] := Sort[Length /@ (Cycles[perm])];

(* Function to generate random permutation with prioritized 2-character cycles *)
randomPermWithPrioritized2Cycles[n_, prob2Cycle_:0.7] := Module[
  {perm = Range[n], unused = Range[n], cycle},
  While[Length[unused] > 1,
    If[RandomReal[] < prob2Cycle || Length[unused] == 2,
      cycle = RandomSample[unused, 2],
      cycle = RandomSample[unused, RandomInteger[{2, Min[4, Length[unused]]}]]
    ];
    perm[[cycle]] = RotateLeft[perm[[cycle]]];
    unused = Complement[unused, cycle];
  ];
  perm
]

(* Function to apply permutation *)
applyPerm[perm_, x_] := perm[[x]]

(* Function to calculate match score *)
matchScore[a_, b_, plaintext_, ciphertext_] := Module[
  {m = Length[plaintext], scores},
  scores = Table[
    Count[
      Table[
        applyPerm[a, applyPerm[RotateLeft[b, r], plaintext[[i]]]] == ciphertext[[i]],
        {i, 1, m}
      ],
      True
    ]/m,
    {r, 0, 25}
  ];
  Max[scores]
]

(* Main cryptanalysis function *)
cryptanalysis[plaintext_, ciphertext_, sampleSize_:1000, matchThreshold_:0.5] := Module[
  {n = 26, bestA, bestB, bestScore = 0, currentScore, allResults = {}},
  
  (* Iterative sampling and scoring *)
  Do[
    Module[{a = randomPermWithPrioritized2Cycles[n],
            b = randomPermWithPrioritized2Cycles[n]},
      currentScore = matchScore[a, b, plaintext, ciphertext];
      AppendTo[allResults, <|"A" -> a, "B" -> b, "Score" -> currentScore|>];
      If[currentScore > bestScore,
        bestScore = currentScore;
        bestA = a;
        bestB = b;
      ];
    ],
    {sampleSize}
  ];
  
  (* Sort results *)
  allResults = SortBy[allResults, -#["Score"] &];
  
  (* Return results *)
  <|
    "BestA" -> bestA,
    "BestB" -> bestB,
    "BestMatchScore" -> bestScore,
    "AllResults" -> allResults
  |>
]

(* Example usage *)
plaintext = {1, 2, 3, 4, 5, 6};
ciphertext = {15, 22, 3, 18, 9, 7};
result = cryptanalysis[plaintext, ciphertext, 1000, 0.3];

(* Print results *)
Print["Best match score: ", result["BestMatchScore"]];
Print["Best A permutation: ", result["BestA"]];
Print["Best B permutation: ", result["BestB"]];
Print["Best A cycle structure: ", cycleStructure[result["BestA"]]];
Print["Best B cycle structure: ", cycleStructure[result["BestB"]]];
Print["\nTop 5 results:"];
Do[
  With[{r = result["AllResults"][[i]]},
    Print["Rank ", i, ":"];
    Print["  Score: ", r["Score"]];
    Print["  A cycle structure: ", cycleStructure[r["A"]]];
    Print["  B cycle structure: ", cycleStructure[r["B"]]];
  ],
  {i, 1, Min[5, Length[result["AllResults"]]]}
]

このプログラムは、前のバージョンから以下の点で改善されています:
2文字置換の優先:
randomPermWithPrioritized2Cycles 関数を導入し、2文字の置換を優先的に生成します。
デフォルトで70%の確率で2文字置換を生成し、残りは2〜4文字の置換をランダムに生成します。
結果の保存と順位付け:
全ての生成された置換ペアとそのスコアを保存します。
結果をスコアの降順でソートし、上位の結果を表示できるようにしました。
詳細な結果の表示:
最良の結果だけでなく、上位5件の結果を表示するようにしました。
各結果について、スコアと置換の巡回置換構造を表示します。

使用方法:plaintext と ciphertext を実際のデータに置き換えます。
必要に応じて sampleSize と matchThreshold を調整します。
プログラムを実行し、結果を分析します。

回答

このプログラムは、以下の情報を表示します:最良のマッチスコア
最良のA置換とB置換
最良のAとBの巡回置換構造
上位5件の結果(スコア、Aの巡回置換構造、Bの巡回置換構造)

注意点:2文字置換を優先することで、特定のタイプの暗号に対してより効果的に機能する可能性がありますが、他のタイプの暗号に対しては効果が低下する可能性もあります。
このアプローチは依然としてヒューリスティックであり、完全な解を保証するものではありません。
サンプルサイズを大きくすることで、より良い結果が得られる可能性がありますが、計算時間も増加します。

このプログラムを使用する際の推奨事項:まず小さなサンプルサイズ(例:1000)で実行し、結果を確認します。
結果が満足できるものでない場合、サンプルサイズを徐々に増やしていきます。
複数回実行して結果を比較し、一貫性を確認します。
可能であれば、複数の平文-暗号文ペアを使用してクロスチェックを行います。

この新しいバージョンにより、2文字置換を優先した暗号解析が可能になり、また結果の詳細な分析もしやすくなりました。実際の暗号解析では、これらの結果を出発点として、さらなる分析や最適化が必要になる場合があります。

回答

この記事が気に入ったらサポートをしてみませんか?