因此,我为我设计的加密密码(基于SPN密码,但做了一些修改)编写了Java程序(在下面附加了代码)。无论如何,当我运行程序时,代码立即停止,并且收到java.lang.ThreadDeath错误。我什至尝试在主方法的开头(如第一行)添加一条打印语句(因此这是我的程序处理的第一件事),但是我没有运气,Java在我的打印语句甚至无法运行之前就停止了运行
这是我的代码:
package SSPN;
import java.io.*;
import java.util.*;
public class Main throws IOException{
public static final int NUM_ROUNDS = 1;
public static final File f = new File("sBoxes.txt");
//Need better comments!!
//For each character, prints out a binary string of length 7. Does zero - padding!
public static String[] plaintextToCharacterBinarySequence(String plaintext)
{
//Getting int values
int[] charRepresentations = new int[plaintext.length()];
for (int i = 0; i < charRepresentations.length; i++)
{
char ch = plaintext.charAt(i);
int asciiValue = (int)ch;
charRepresentations[i] = asciiValue;
}
String[] binValues = new String[charRepresentations.length];
System.out.print("Binary values are: ");
for (int i = 0; i < binValues.length; i++)
{
String str = Integer.toBinaryString(charRepresentations[i]);
StringBuilder sb = new StringBuilder(str);
if (str.length() !=7)
{
int DIFF = 7 - str.length(); //As it is an Ascii Value, must be less than length 7
for (int j = 7; j > (7 - DIFF); j--)
{
sb.insert(0,"0");
}
}
str = sb.toString();
binValues[i] = str;
System.out.print(binValues[i] + " ");
}
System.out.println();
return binValues;
}
public static String binarySequenceToString(String[] sequence)
{
StringBuilder sb = new StringBuilder();
for (int i =0; i < sequence.length; i++)
{
int val = Integer.parseInt(sequence[i], 2);
char ch = (char) val;
sb.append(ch);
}
return sb.toString();
}
/*We define an instance of the affine cipher (for extra security), with a = length of message,b = ascii value of 1st character.
m = 128. Then, we convert the output to (zero-padded) 7-bit binary number, and store the result as the output of a hash
table (where the input binary number is the key)*/
public static HashMap<String, String> defineandStoreSBoxes(File f, int lengthOfMessage, int firstAsciiValue) throws FileNotFoundException, IOException
{
BufferedReader br = new BufferedReader(new FileReader(f));
HashMap<String, String> hm = new HashMap <String, String>();
String currentSBox;
while ((currentSBox = br.readLine()) != null)
{
int base10Val = Integer.parseInt(currentSBox, 2);
int encryptedOutput = lengthOfMessage * base10Val + firstAsciiValue; //(LIMITATION: Without modding by 128, encryptedOutput Cannot exceed Integer.MAX_VALUE)
String binOutput = Integer.toBinaryString(encryptedOutput);
StringBuilder sb = new StringBuilder(binOutput);
if (binOutput.length() !=7)
{
int DIFF = 7 - binOutput.length(); //As it is an Ascii Value, must be less than length 7
for (int j = 7; j > (7 - DIFF); j--)
{
sb.insert(0,"0");
}
}
binOutput = sb.toString();
hm.put(currentSBox, binOutput);
}
br.close();
return hm;
}
//This method performs bitwise XOR on each block of the plaintext and the bits of the round key (which are the same size)
public static String[] xorSubkey(String[] currentText, String roundKey )
{
for (int i =0; i < roundKey.length(); i++)
{
StringBuilder sb = new StringBuilder();
String binStr = currentText[i];
for (int j =0; j < 7; j++)
{
int chCurrent = Character.getNumericValue(binStr.charAt(j)); //Either 0 or 1
int chKey = Character.getNumericValue(roundKey.charAt((1 * 7)+ j));
if (chCurrent == chKey)
{
sb.append("0");
}
else
{
sb.append("1");
}
}
currentText[i] = sb.toString();
}
return currentText;
}
public static String[] sBoxSubstitution(String[] currentText, HashMap <String,String> hm)
{
for (int i =0; i < currentText.length; i++)
{
String val = hm.get(currentText[i]);
currentText[i] = val;
}
return currentText;
}
public static String[] linTransform(String[] currentText)
{
int shift = currentText.length % 7;
for (int i =0; i < currentText.length; i++)
{
StringBuilder sb = new StringBuilder(currentText[i]);
String sub = currentText[i].substring(shift, 7);
sb.insert(0, sub);
sb.delete(currentText[i].length(), currentText[i].length() + (7 - shift));
currentText[i] = sb.toString();
}
return currentText;
}
public static String[] encrypt(String plaintext, String[] roundKeys) throws IOException
{
String[] binaryText = plaintextToCharacterBinarySequence(plaintext);
HashMap<String, String> hm = defineandStoreSBoxes(f, plaintext.length(), (int) plaintext.charAt(0));
String[] xoredSequence, substitutedSequence,transformedSequence = null;
//The first Num_Rounds -1 Rounds
for (int i =0; i < NUM_ROUNDS -1; i++)
{
xoredSequence = xorSubkey(binaryText, roundKeys[i]);
substitutedSequence = sBoxSubstitution(xoredSequence, hm);
transformedSequence = linTransform(substitutedSequence);
}
// the final round
xoredSequence = xorSubkey(transformedSequence, roundKeys[roundKeys.length - 2]); //Make sure this isnt null
substitutedSequence = sBoxSubstitution(xoredSequence, hm);
//Final xor Subkeying
String[] ciphertext = xorSubkey(substitutedSequence, roundKeys[roundKeys.length - 1]); //Make sure this isnt null
return ciphertext;
}
//DECRYPTING
public static String[] decrypt(String textToDecrypt, String[] roundKeys) throws IOException
{
String[] bitCiphertext = plaintextToCharacterBinarySequence(textToDecrypt);
HashMap<String, String> hm= defineandStoreSBoxes(f,textToDecrypt.length(), (int)textToDecrypt.charAt(0) ); //Make sure this is reversed
String[] xoredSequence, substitutedSequence,transformedSequence = null;
//Decrypting final ciphertext
String[] finalXOR = xorSubkey(bitCiphertext, roundKeys[roundKeys.length - 1]);
// Final round
substitutedSequence = reverseSBox(finalXOR, hm);
xoredSequence = xorSubkey(substitutedSequence, roundKeys[roundKeys.length - 2]);
//Reversing the loop order
for (int i = NUM_ROUNDS -1; i >= 0; i--)
{
transformedSequence = reverseLinTransform(substitutedSequence);
substitutedSequence = reverseSBox(transformedSequence, hm);
xoredSequence = xorSubkey(substitutedSequence, roundKeys[i]);
}
String[] plaintext = xoredSequence;
return plaintext;
}
public static String[] reverseSBox(String[] value, HashMap <String, String> hm)
{
for (int i =0; i < value.length; i++)
{
for (Map.Entry<String, String> entry : hm.entrySet())
{
if (value[i].equals(entry.getValue())) //Because s-boxes are bijective
{
value[i] = entry.getKey();
}
}
}
return value;
}
public static String[] reverseLinTransform(String[] value)
{
int shift = 7 - (value.length %7);
for (int i =0; i < value.length; i++)
{
StringBuilder sb = new StringBuilder(value[i]);
String sub = value[i].substring(shift, 7);
sb.insert(0, sub);
sb.delete(value[i].length(), value[i].length() + (7 - shift));
value[i] = sb.toString();
}
return value;
}
public static boolean isGoodRoundKey(String key, int plainTextLength)
{
if (plainTextLength == key.length() && key.length() % 7 ==0 && isBinary(key) ==true)
{
return true;
}
else
{
return false;
}
}
public static boolean isBinary(String number)
{
for (int i =0; i < number.length(); i++)
{
char c = number.charAt(i);
if (c != '0' && c != '1')
{
return false;
}
}
return true;
}
public static void main(String[] args) throws IOException
{
System.out.println("Inside main");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //Buffered reader will read in plaintext, and round keys
System.out.print("Enter the text that you would like to encrypt: ");
String plaintext = br.readLine();
int numChars = plaintext.length();//The total number of characters that make up this string
String[] roundKeys = new String[NUM_ROUNDS + 1];//Each box will have 7 bits
System.out.println("The cipher will encrypt for "+ NUM_ROUNDS + "rounds, so you will need to enter some round keys. ");
System.out.println("Each round key must be a sequence of zeroes and ones, and must be exactly seven times the length of the plaintext string");
//Storing all the round keys in the array!
for (int i =0; i <= NUM_ROUNDS; i++)
{
if (i ==0)
{
System.out.print("Enter the round key for the 1st round: ");
}
else if (i ==1)
{
System.out.print("Enter the round key for the 2nd round: ");
}
else if (i ==2)
{
System.out.print("Enter the round key for the 3rd round: ");
}
else if (i == NUM_ROUNDS)
{
System.out.print("Enter the round key that will be XORed at the very end of all the rounds ");
}
else
{
System.out.print("Enter the round key for the " + i+1 + "th round: ");
}
roundKeys[i] = br.readLine();
System.out.println();
/*Check to make sure the round key that is passed in is valid. If it is not, an error message will be printed to the user,
prompting them to enter a valid round key. This will loop indefinitely until a valid round key is entered.
*/
if (isGoodRoundKey(roundKeys[i],plaintext.length() ) !=true)
{
boolean isValid = false;
while(isValid == false)
{
System.out.println("ERROR: the key you entered is not a valid key for this cipher.");
System.out.println("Please enter another key: ");
String new_key = br.readLine();
if (isGoodRoundKey(new_key, plaintext.length()) ==true)
{
roundKeys[i] = new_key;
isValid = true;
}
}
}
}
br.close();
String[] bitCiphertext = encrypt(plaintext, roundKeys);
String ciphertext = binarySequenceToString(bitCiphertext);
System.out.println("The encryption of " + plaintext + " is: "+ ciphertext);
String[] discoveredBitPlaintext = decrypt(ciphertext, roundKeys);
String discoveredPlaintext = binarySequenceToString(bitCiphertext);
System.out.println("The encryption of " + ciphertext + " is: " + discoveredPlaintext);//Reverse order of round Keys
}
}