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;
}
我需要先使用维吉尼亚密码加密然后解密消息。它应该是这样工作的
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;
}