yacked2

[Java] Crack Vigenere Cipher

Apr 13th, 2014
365
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.39 KB | None | 0 0
  1. /*
  2.     Yacked2 13.4.2014
  3. */
  4. import java.math.BigDecimal;
  5. import java.math.RoundingMode;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. import java.util.Map.Entry;
  9. import java.util.Scanner;
  10. import java.util.TreeMap;
  11.  
  12. public class KeyLength {
  13.  
  14.     public static void main(String[] args)
  15.     {
  16.         //s scannerjem vsesemo kodirano besedilo v program
  17.         Scanner sc = new Scanner(System.in);
  18.         String kodirano = sc.next();
  19.        
  20.         //FindKey vrne dolžino ključa med 4 in 20
  21.         int kljuc = FindKey(kodirano);
  22.        
  23.         //pogostost posameznih črk v angleski abecedi
  24.         double[] jezik = new double[] {8.167,1.492,2.782,4.253,12.702,2.228,2.015, 6.094,6.966,0.153, 0.772,4.025,2.406,6.749, 7.507,1.929, 0.095,5.987,6.327,9.056,2.758, 0.978,2.360,0.150,1.974,0.074};
  25.        
  26.         //angleška abeceda
  27.         String abeceda = "abcdefghijklmnopqrstuvwxyz";
  28.        
  29.         //pogostost v kodiranem nizu
  30.         double[][] pogostost = pogostost(kodirano, kljuc);
  31.        
  32.         //v resitev shranimo crke kjuca
  33.         char[] resitev = new char[kljuc];
  34.        
  35.         //sprehodimo se cez cel kjuc
  36.         for(int i=0; i < kljuc;i++)
  37.         {
  38.             //poiscemo vsa odstopanja znotraj vrstice
  39.             double[] vseZaVrsto = new double[26];
  40.            
  41.             //v vrstici je 26 možnih pozicij
  42.             for(int n=0; n < 26; n++)
  43.             {
  44.                 //sestevamo absolutno odstopanje vseh črk
  45.                 double napaka=0;
  46.                
  47.                 //računanje napake za vsak zamik
  48.                 for(int k = 0; k < 26;k++)
  49.                 {
  50.                     double local = Math.abs( jezik[k] - pogostost[i][(k+n) % 26]);
  51.                     napaka += local;
  52.                 }
  53.                 //skupna napaka v vrsti za zamik n
  54.                 vseZaVrsto[n] = napaka;
  55.             }
  56.            
  57.             //poiscemo najmanjso napako v vrsti
  58.             int naj = 0;
  59.        
  60.             for(int b=1; b<26;b++)
  61.             {
  62.                 if(vseZaVrsto[b] < vseZaVrsto[naj])
  63.                 {
  64.                     naj = b;   
  65.                 }
  66.             }
  67.             //crka na polozaju najmanjsege napake je del resitve
  68.             resitev[i] = abeceda.charAt(naj);
  69.         }
  70.        
  71.         //izpišemo rešitev
  72.         System.out.print("RESITEV: ");
  73.         for(char crka: resitev)
  74.         {
  75.             System.out.print(crka);
  76.         }
  77.        
  78.         //zapremo scanner
  79.          sc.close();
  80.     }
  81.  
  82.     private static int FindKey(String kodirano) //poiscemo dolzino kjuca
  83.     {
  84.         kodirano = kodirano.toLowerCase();
  85.         //kodirano besedilo je shranjeno v kodirano in je v malih crkah
  86.        
  87.         //v arraylist bomo shranjevali dele kodiranega besedila, ki se večkrat ponovijo
  88.         ArrayList<String> SubStrrring = new ArrayList<String>();
  89.        
  90.         //poiščemo podvojevanje in ga shranimo v arraylist
  91.         for(int i=0; i < kodirano.length()-3;i++)
  92.         {
  93.             //del mora biti sestavljen vsaj iz treh crk
  94.             String ponovitev = kodirano.substring(i, i+3);
  95.        
  96.             //ce se del v besedilu ponovi več kot enkrat vrne true
  97.             boolean ponavljanje = Check(ponovitev,kodirano);
  98.            
  99.             if(ponavljanje)
  100.             {
  101.                 int n=1;
  102.                 //ugotovimo ali je del vecji kot tri crke
  103.                 while(ponavljanje)
  104.                 {
  105.                     if(i+3+n < kodirano.length())
  106.                     {
  107.                         String novaPonovitev = kodirano.substring(i,i+3+n);
  108.                         boolean NovoPonavljanje = Check(novaPonovitev,kodirano);
  109.                        
  110.                         if(NovoPonavljanje)
  111.                         {
  112.                             ponovitev = novaPonovitev;
  113.                             n++;
  114.                         }
  115.                         else
  116.                         {
  117.                             break;
  118.                         }
  119.                        
  120.                     }
  121.                     else
  122.                     {
  123.                         break;
  124.                     }
  125.                 }
  126.                 //ce tega dela se ni v arrylistu ga dodamo
  127.                 if(!(SubStrrring.contains(ponovitev)))
  128.                 {
  129.                     SubStrrring.add(ponovitev);
  130.                 }
  131.             }
  132.         }
  133.         //Sedaj so podvojevanje shranjene v SubStrrringu
  134.        
  135.         //ugotoviti moramo kakšne so razdalje med temi ponovljenimi deli
  136.         ArrayList<Integer> razdalje = new ArrayList<Integer>();
  137.        
  138.         //sprehodimo se čez vse ponovitve
  139.         for(int n=0; n<SubStrrring.size();n++)
  140.         {
  141.             //v dump bomo shranjevali začetne indexe ponovitev
  142.             ArrayList<Integer> dump = new ArrayList<Integer>();
  143.            
  144.             //del ki se ponavlja
  145.             String word = SubStrrring.get(n);
  146.            
  147.             for (int i = -1; (i = kodirano.indexOf(word, i + 1)) != -1; )
  148.             {
  149.                 //razdalja je index +1 in jo dodamo v arraylist
  150.                 int k=i+1;
  151.                 dump.add(k);
  152.             }
  153.             //izracunamo razliko in jo dodamo v zunanji arraylist
  154.             int razlika = Math.abs(dump.get(1) - dump.get(0));
  155.             razdalje.add(razlika);
  156.         }
  157.        
  158.         //sedaj izračunamo deljitelje razdalij
  159.         ArrayList<Integer> deljitelji = new ArrayList<Integer>();
  160.        
  161.         //za vsako razdaljo...
  162.         for(int stevilo : razdalje)
  163.         {
  164.              int integer = stevilo;
  165.              //če je ostanek deljenja 0 potem count deli stevilo, dodamo ga v arraylist
  166.              for(int count = 2; count <= integer; count++)
  167.              {
  168.                  if(integer%count == 0)
  169.                  {
  170.                      deljitelji.add(count);
  171.                  }
  172.              }
  173.         }
  174.        
  175.         //prestejemo vse deljitelje
  176.          HashMap<Integer,Integer> map = new HashMap<Integer, Integer>();
  177.          
  178.          //sprehodimo se čez vse deljitelje
  179.          for(int i=0; i<deljitelji.size() ;i++)
  180.          {  
  181.              //dosedanjemu stevilu pristejemo se enega
  182.              Integer count = map.get(deljitelji.get(i));        
  183.              map.put(deljitelji.get(i), count==null?1:count+1);
  184.          }
  185.          
  186.          //sedaj hashmap preslikamo v treemap da ga lahko uredimo
  187.          TreeMap<Integer, Integer> Tree = new TreeMap<Integer, Integer>();
  188.        
  189.          for(Entry<Integer, Integer> entry : map.entrySet())
  190.          {
  191.              int MapKey = entry.getKey();
  192.              int MapValue = entry.getValue();
  193.              Tree.put(MapKey, MapValue);
  194.          }
  195.          
  196.          //poiscemo najbolj verjetne kljuce
  197.          int maxK = -1;
  198.          int maxV = -1;
  199.          
  200.          //System.out.println("Verjetnost moznih kjucev:");
  201.          
  202.          //gremo cez cel treeset
  203.          for (Entry<Integer, Integer> entry : Tree.entrySet())
  204.          {
  205.              //če je kjuc med 4 in 20 ter je njegova ponovitev 10x ali več
  206.              if(entry.getKey() >= 4 && entry.getKey() <=20 && entry.getValue() >= 10)
  207.              {
  208.                  //izracun najbolj verjetne moznosti
  209.                  if(entry.getValue() > maxV)
  210.                  {
  211.                      maxV = entry.getValue();
  212.                      maxK = entry.getKey();
  213.                  }
  214.                  //System.out.println("Kjuc dolzine " + entry.getKey() + ": " + entry.getValue());
  215.              }
  216.              
  217.          }
  218.          //System.out.println("Najvecja verjetnost za dolzino kjuca je " + maxK);
  219.          return maxK;
  220.     }
  221.  
  222.     private static boolean Check(String ponovitev, String kodirano)
  223.     {
  224.         int lastIndex = 0;
  225.         int count =0;
  226.        
  227.         while(lastIndex != -1){
  228.  
  229.                lastIndex = kodirano.indexOf(ponovitev,lastIndex);
  230.  
  231.                if( lastIndex != -1){
  232.                      count ++;
  233.                      lastIndex+=ponovitev.length();
  234.               }
  235.         }
  236.         if(count > 1)
  237.         {
  238.             return true;
  239.         }
  240.         else
  241.         {
  242.             return false;
  243.         }  
  244.     }
  245.  
  246.     public static double[][] pogostost (String kodirano, int kljuc)
  247.     {
  248.         kodirano = kodirano.toLowerCase();
  249.        
  250.         //kodirano besedilo razdelimo na kjuc-delov
  251.         String[] razdeljeno = new String[kljuc];
  252.         for(int i=0; i<kodirano.length();i++)
  253.         {
  254.             int k = i % kljuc;
  255.            
  256.             if( i < kljuc)
  257.             {
  258.                 razdeljeno[k] = ""+kodirano.charAt(i);
  259.             }
  260.             else
  261.             {
  262.                 razdeljeno[k] += kodirano.charAt(i);
  263.             }
  264.         }
  265.        
  266.         //izracun pogostosti crk v posameznem kjuc-nizu
  267.         HashMap<Integer,TreeMap<Character,Integer>> analiza = new HashMap<Integer,TreeMap<Character,Integer>>();
  268.        
  269.         //za vsak niz
  270.         for(int i=0; i < razdeljeno.length;i++)
  271.         {
  272.             TreeMap<Character,Integer> crke = new TreeMap<Character,Integer>();
  273.            
  274.             for(int n=0; n < razdeljeno[i].length();n++)
  275.             {
  276.                 char c = razdeljeno[i].charAt(n);
  277.                 int vrednost;
  278.                
  279.                 if(crke.containsKey(c))
  280.                 {
  281.                     vrednost = crke.get(c);
  282.                 }
  283.                 else
  284.                 {
  285.                     vrednost = 0;
  286.                 }
  287.                 vrednost++;
  288.                
  289.                 crke.put(c,vrednost);
  290.             }
  291.             analiza.put(i, crke);
  292.         }
  293.         //System.out.println(analiza.toString());
  294.        
  295.         //izracun pogostosti v %
  296.         /////////////////////////////////////////////////////////////////////////
  297.         HashMap<Integer,TreeMap<Character,Double>> procenti = new HashMap<Integer,TreeMap<Character,Double>>();
  298.        
  299.        
  300.          for (Entry<Integer,TreeMap<Character,Integer>> entry : analiza.entrySet())
  301.          {
  302.              int n= entry.getKey(); //katera vrsta v kljucu smo
  303.              
  304.              TreeMap<Character,Integer> crke = entry.getValue(); //shranjene crke, pogostost
  305.              
  306.              int vseCrke= 0;
  307.              
  308.              for(Entry<Character, Integer> c : crke.entrySet())
  309.              {
  310.                  
  311.                  vseCrke += c.getValue();
  312.              }
  313.              
  314.              TreeMap<Character,Double> zaVrsto = new TreeMap<Character,Double>(); //tukaj noter bomo shranjevali % za lokalne črke
  315.              
  316.              //int VseCrke = crke.size();
  317.              
  318.              for(Entry<Character, Integer> c : crke.entrySet())
  319.              {
  320.                  
  321.                  double result = (double) c.getValue() / vseCrke;
  322.                  result = result * 100;
  323.                  
  324.                  BigDecimal bd = new BigDecimal(result).setScale(3, RoundingMode.HALF_EVEN);
  325.                  result = bd.doubleValue();
  326.                
  327.                  zaVrsto.put(c.getKey(), result);
  328.              }
  329.              procenti.put(n, zaVrsto);
  330.              
  331.          }
  332.         //System.out.println(procenti.toString());
  333.        
  334.         //pogostost v ang jeziku
  335.         //double[] jezik = new double[] {8.167,1.492,2.782,4.253,12.702,2.228,2.015, 6.094,6.966,0.153, 0.772,4.025,2.406,6.749, 7.507,1.929, 0.095,5.987,6.327,9.056,2.758, 0.978,2.360,0.150,1.974,0.074};
  336.         String abeceda = "abcdefghijklmnopqrstuvwxyz";
  337.  
  338.         //naredimo 2d array z odstoti
  339.         double[][] pog = new double[kljuc][26];
  340.        
  341.         for (Entry<Integer, TreeMap<Character, Double>> entry : procenti.entrySet())
  342.         {
  343.             int vrsta = entry.getKey();
  344.            
  345.             TreeMap<Character,Double> odstotki = entry.getValue();
  346.            
  347.             for(int i=0; i < abeceda.length();i++)
  348.             {
  349.                 Character crka = Character.valueOf(abeceda.charAt(i));
  350.                 double vrednost;
  351.                
  352.                 if(odstotki.containsKey(crka))
  353.                 {
  354.  
  355.                     vrednost = odstotki.get(crka);
  356.                 }
  357.                 else
  358.                 {
  359.                     vrednost =0;
  360.                 }
  361.                 pog[vrsta][i] = vrednost;
  362.             }
  363.         }
  364.        
  365.         //vrnemo 2d array z odstoti pogostosti črk
  366.         return pog;
  367.        
  368.     }
  369. }
Add Comment
Please, Sign In to add comment