Vigenere Cipher encryption/decryption 使用数组

Vignere Cipher encryption/decryption using arrays

我需要先使用维吉尼亚密码加密然后解密消息。它应该是这样工作的

example message:                                 "c  a  t  s  _  d  o  g  s"
keyword "rats":                                   r  a  t  s  r  a  t  s  r
order of the letter in the message (start at a=0):2  0  19 18 () 3  14 6  18
order of the letter in the keyword:               17 0  19 18 17 0  19 18 17
sum of the two orders:                            19 0  38 36 17 3  39 24 35
new letter for the message*                       t  a  m  k     d  h  y  j
encrypted message = "tamk uoyk"

注意:如果sum > 26那么我们从sum中减去26得到一个循环字母表。示例:

z + b = 25 + 1 = 26; 26 - 26 = 0 --> a

我写了获取关键字数值的方法,还有两个“加”或“减”单个字母的方法和两个执行凯撒的方法encoding/decoding(简单地移动整个通过字母表右侧的 int 或左侧解密的消息)。

我真正需要帮助的部分是如何创建一个 for 循环,该循环将关键字重复适当的次数(以与消息具有相同的长度)并继续使用 obtainKeys 方法来获取重复键的数值。

这是我的整个程序;我挣扎的部分在最后 (Q2f)

import java.util.Arrays;
public class Cypher {
    public static void main(String[] args) {
        System.out.println(charRightShift('z', 3));
        System.out.println(charLeftShift('z', 3));

        String test = caesarEncode("cats and dogs", 5);
        System.out.println(test);
        System.out.println(caesarDecode(test, 5));
        obtainKeys("abcxyz");
        System.out.println(vigenereEncode("elephants", "rats"));
    }

    //Q2a-b
    //Generalized method for char shifts
    public static char charShift(char c, int n) {
        //value of n should be between 0 and 25
        if (Math.abs(n) < 0 || 25 < Math.abs(n)) {
            //returning the ascii value of '0' which
            //is nul & adding error message
            int zero = 0;
            c = (char) zero;
            throw new IllegalArgumentException("n has to be 0<=|n|<=25");
        }
        //character c should be a lower case latin letter
        //if not, we simply return c, the original character,
        //skipping this else if
        else if (c >= 'a' && c <= 'z') {
            c = (char) (c + n);
            if (c > 'z') {
                c = (char) (c - 26);
            } else if (c < 'a') {
                c = (char) (c + 26);
            }
        }
        return c;
    }

    //method that shifts the value of the character to the right
    public static char charRightShift(char c, int n) {
        c = charShift(c, n);
        return c;
    }

    //method that shifts the value of the character to the left
    public static char charLeftShift(char c, int n) {
        n = -n;
        c = charShift(c, n);
        return c;
    }

    //Q2c
    //method that shifts the message to the right by int 'key' characters
    public static String caesarEncode(String message, int key) {
        //transform string into char array
        char[] messageEncrypt = message.toCharArray();
        //for each char, we shift it by 'key' ints,
        //using charRightShift method
        for (int i = 0; i < messageEncrypt.length; i++) {
            char c = messageEncrypt[i];
            c = charRightShift(c, key);
            messageEncrypt[i] = c;
        }
        return new String(messageEncrypt);
    }

    //Q2d
    //method that shifts the message to the left by int 'key' characters
    public static String caesarDecode(String message, int key) {
        //transform string into char array
        char[] messageDecrypt = message.toCharArray();
        //for each char, we shift it by 'key' ints using charLeftShift
        for (int i = 0; i < messageDecrypt.length; i++) {
            char c = messageDecrypt[i];
            c = charLeftShift(c, key);
            messageDecrypt[i] = c;
        }
        return new String(messageDecrypt);
    }

    //Q2e
    //method to obtain the int array storing the numerical value of the String
    public static int[] obtainKeys(String s) {
        //creating int array where we're going to
        //store the numerical value of the String
        int[] keys = new int[s.length()];
        int j;
        //for each ascii value of the char in string s, we substract 97 to
        //get the lower case english alphabet character corresponding to it
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            j = c - 97;
            //now store every int in the int array
            keys[i] = j;
        }
        String keysString = Arrays.toString(keys);
        return keys;
    }

    //Q2f
    public static String vigenereEncode(String message, String keyword) {
        //for loop check if there are any 'illegal' characters in the keyword
        char[] kword = keyword.toCharArray();
        for (int i = 0; i < kword.length; i++) {
            char c = kword[i];
            if (c < 'a' || c > 'z') {
                throw new IllegalArgumentException(
                        "The keyword must only contain characters " +
                                "from the lower case English alphabet.");
            }
        }
        int[] numMessage = obtainKeys(message);
        int[] numKeyword = obtainKeys(keyword);
        for (int i = 0; i < message.length(); i++) {
            for (int j = 0; j < keyword.length(); i++) {
                //NOT SURE IF I NEED A NESTED LOOP HERE
                //WHAT TO DO HERE?
            }
        }
        return messageVigenere;
    }
}

您可以使用模数逻辑找到需要哪个字母,而不是重复关键字直到它达到消息的长度。对于消息中的任何位置 n,关键字字母为 keyword[n % keyword.length()].

您可以使用 mod 操作 %

char[] messageArray = message.toCharArray();
char[] encryptedMessage = new char[messageArray.length];
int[] numKeyword = obtainKeys(keyword);
int keywordLength = numKeyword.length;

for(int i=0; i<message.length(); i++){
    int shiftAmount = numKeyword[i % keywordLength];
    char c = messageArray[i];
    c = charRightShift(c,shiftAmount);
    encryptedMessage[i] = c;
}