2014-10-12 4 views
0

Привет, кто читает это!Vigenere Cipher java UTF-8

Мне нужно реализовать шифр Vigenere на Java. У меня есть .txt документ, который я буду читать, кодировать и декодировать. Вот оно:

ASCII  abcde xyz 
German äöü ÄÖÜ ß 
Polish ąęźżńł 
Russian абвгдеж эюя 
CJK  你好 

Моя проблема заключается в том, что я не знаю, как правильно перенести символы, согласно this table латинских букв имеют коды от 0061 до 007A. Немецкие, которые мне нужны: 00C0 - 00FF, польский: 0100-017F, русский 0430-044F, и я не заинтриговал китайский.

Как я могу указать unshiftChar и shiftChar, чтобы сделать это подставкой? Теперь мой вход выглядит следующим образом:

The original text from file is: 
ASCII  abcde xyz 
German äöü ÄÖÜ ß 
Polish ąęźżńł 
Russian абвгдеж эюя 
CJK  你好 

String that will be encoded is: 
asciiabcdexyzgermanäöüäöüßpolishąęźżńłrussianабвгдежэюяcjk你好 

The encrypted string is: 
äckkwdfaqmzjökcbucäbdslhwfssjvåjoxfbsltfvwgnvboegbrnboeghxöb 

The decrypted phrase is: 
asciiab¥dexyzg￧rmanäö￷äöuupo○ibmjcå￷äldhtc￲iwmtdå￶awmtddpw 

Вот код Java:

public class VigenereCipher 
    { 
    public static void main(String[] args) throws IOException 
    { 
     String key = "Unicode"; 

     File file = new File("G:\\unicode.txt"); 

     FileInputStream fis = new FileInputStream(file); 
     byte[] fileBArray = new byte[fis.available()]; 
     fis.read(fileBArray); 

     String text = new String(fileBArray, "UTF-8"); 

     //String text = "Some simple text to check the decoding algorythm"; 
     System.out.println("The original text from file is: \n" + text); 
     String enc = encrypt(text, key); 
     System.out.println(enc + "\n"); 
     System.out.println("The decrypted phrase is: "); 
     System.out.println(decrypt(enc, key)); 
    } 

    // Encrypts a string 
    public static String encrypt(String message, String key) 
    { 
     message = StringToLowerCaseWithAllSymbols(message); 
     System.out.println("String that will be encoded is: \n" + message); 
     char messageChar, keyChar; 
     String encryptedMessage = ""; 
     for (int i = 0; i < message.length(); i++) 
     { 
      messageChar = shiftChar(message.charAt(i)); 
      keyChar = shiftChar(key.charAt(i % key.length())); 
      messageChar = (char) ((keyChar + messageChar) % 29); 
      messageChar = unshiftChar(messageChar); 
      encryptedMessage += messageChar; 
     } 
     System.out.println("\nThe encrypted string is: "); 
     return encryptedMessage; 
    } 

    // Decrypts a string 
    public static String decrypt(String cipher,String key) 
    { 
      char cipherChar, keyChar; 
      cipher = StringToLowerCaseWithAllSymbols(cipher); 
      String decryptedMessage = ""; 
      cipher = cipher.toLowerCase(); 
      for (int i = 0; i < cipher.length(); i++) 
      { 
       cipherChar = shiftChar(cipher.charAt(i)); 
       keyChar = shiftChar(key.charAt(i % key.length())); 
       cipherChar = (char) ((29 + cipherChar - keyChar) % 29); 
       cipherChar = unshiftChar(cipherChar); 
       decryptedMessage += cipherChar; 
      } 
      return decryptedMessage; 
    } 

    // Prunes all characters not in the alphabet {A-Öa-ö} from a string and changes it to all lower  case. 
    public static String StringToLowerCaseWithAllSymbols(String s) 
    { 
      //s = s.replaceAll("[^A-Za-zåäöÅÄÖ]", ""); 
      // 's' contains all the symbols from my text 
      s = s.replaceAll("[^A-Za-zäöüÄÖÜßąęźżńłабвгдежэюя你好]", ""); 
      return s.toLowerCase(); 
     } 

    // Assigns characters a,b,c...å,ä,ö the values 1,2,3...,26,28,29. 
    private static char shiftChar(char c) 
    { 
      if (96 < c && c < 123) 
      { 
       c -= 97; 
      } 
      else if (c == 229) 
      { 
       c = 26; 
      } 
      else if (c == 228) 
      { 
       c = 27; 
      } 
      else if (c == 246) 
      { 
       c = 28; 
      } 
      return c; 
     } 

    // Undoes the assignment in shiftChar and gives the characters back their UTF-8 values. 
    private static char unshiftChar(char c) 
    { 
      if (0 <= c && c <= 25) 
      { 
       c += 97; 
      } 
      else if (c == 26) 
      { 
       c = 229; 
      } 
      else if (c == 27) 
      { 
       c = 228; 
      } 
      else if (c == 28) 
      { 
       c = 246; 
      } 
      return c; 
     } 
} 

ответ

1

Прежде всего, вы не хотите, чтобы перейти: Вы хотите вращать. Предположим, мы работаем с английским алфавитом. Если «A» + 2 - «C», что такое «Z» + 2? Когда вы используете шифр Vigenere, вы хотите «Z» + 2 == «B».

Я бы не использовал Unicode в программе шифрования Vigenere: я бы использовал свою собственную кодировку, в которой первая буква алфавита представлена ​​нулем, вторая буква представлена ​​одним и так далее. Итак, для моего английского примера, код ('A') ==> 0, код ('B') ==>, ... code ('Z') ==> 26.

Тогда моя функция вращения выглядит следующим образом:

int rotate(Alphabet alphabet, int code, int amount) { 
    return (code + amount) % alphabet.getLength(); 
} 

Итак:

rotate(english, code('A'), 2) ==> (0 + 2)%26 == 2, (the code for 'C'), and 
rotate(english, code('Z'), 2) ==> (25 + 2)%26 == 1, (the code for 'B'). 
+0

Хорошо, я вижу .. А если у меня есть английский, русский и т.д. символов, мне нужно создать алфавит для всех из них? – TomatoLion

+0

@ Kate21, вот как бы я это сделал. Я бы, вероятно, создал интерфейс «Alphabet» с методами для преобразования между пользовательской кодировкой и Unicode, а затем я бы сделал один класс, который «реализует алфавит» для каждого языка. –