Java: Decrypting Caesar Cipher with Unknown Positions - java

Descriptions: I am suppose to come up with a program that will break encrypted messages that used a Caesar Cipher algorithm. Sounds easy enough the problem is you have to figure out what position was used to make the encrypted message in order to decrypt the coded message.
So I have a method called public void train(String trainingFileName) that reads in a file with a lot of text in it to determine the frequency of each lowercase alphabetical English character (a - z) that are stored in a double array []. That method works great so it's not necessary to look at unless you want to, but I do use a good majority of that code in the method that I'm having trouble on which is my public int decrypt(String cipherTextFileName, String outputFileName) method.
The code works beautifully when the Caesar Cipher is set to 3 positions, but anything else it gives me a lot of problems.
I have a do-while loop in my public int decrypt(String cipherTextFileName, String outputFileName) method that will decrypt the coded message starting with 0 positions and then using the "distance" formula that I'm using (NOTE: I cannot use any other formula) to find the minimum distance between the knownFrequencies and the observedFreq in my encrypted message. Right now I have my do-while loop set to where if the distance is less than 0.6 then stop the loop. In theory when I have the correct number of positions in the Caesar Cipher the distance should be below that value.
Problem: Program works great when numberOfPositions is 3, but when I use an encrypted message that is not using 3 positions in the Caesar Cipher the distance never falls below 1 and while in debug mode when I set the numberOfPositions to what it should be to decrypt the message, the message is still encrypted.
Question: How can I implement this method better so I am not testing my distance on a "hard" value to stop the do-while loop? I tried using Math.min(), but that doesn't work. Why can't I decode a message with the positions of the Caesar Cipher other than 3.
I will show you my code now. If you want to test it on your system. You will need 3 text files. One file has to be long with a bunch of words in it... at least 1000. That file will be read in the train method. You need a file with an encrypted message and another file for the program to write the decrypted message.
Here is an encrypted message first using 3 positions of the Caesar Cipher and then 5 positions.
Wkh surjudp zdv krvwhg eb dfwru Slhufh Eurvqdq dqg kdg frpphqwdub iurp pdqb Kroobzrrg dfwruv dqg iloppdnhuv Prylh txrwdwlrqv wkdw ylhzhuv xvh lq wkhlu rzq olyhv dqg vlwxdwlrqv
Ymj uwtlwfr bfx mtxyji gd fhytw Unjwhj Gwtxsfs fsi mfi htrrjsyfwd kwtr rfsd Mtqqdbtti fhytwx fsi knqrrfpjwx Rtanj vztyfyntsx ymfy anjbjwx zxj ns ymjnw tbs qnajx fsi xnyzfyntsx
When decrypted it should say:
The program was hosted by actor Pierce Brosnan and had commentary from many Hollywood actors and filmmakers Movie quotations that viewers use in their own lives and situations
Alright here is the class I wrote (you will need all the imports) and I would like to thank anyone who helps in advance:
public class CodeBreaker {
public final int NUMBER_OF_LETTERS = 26;
private double[] knownFrequencies = new double[NUMBER_OF_LETTERS];
public double[] getKnownFrequencies() {
return knownFrequencies;
}
public void setKnownFrequencies(double[] knownFrequencies) {
this.knownFrequencies = knownFrequencies;
}
/**
* Method reads in a file with a lot of text in it and
* then use that to figure out the frequencies of each character
*
* #param trainingFileName
*/
public void train(String trainingFileName) {
try {
Scanner fileIO = new Scanner(new File(trainingFileName));
int total = 0;
String temp = "";
while (fileIO.hasNext()) {
//reading into file and storing it into a string called temp
temp += fileIO.next().toLowerCase().replaceAll("[ -,!?';:.]+", "");
//converting temp string into a char array
}
char[] c = temp.toCharArray();
total += c.length; // how many characters are in text
int k = (int) 'a'; // int value of lowercase letter 'a'
int[] counter = new int[NUMBER_OF_LETTERS];
for (int j = 0; j < total; j++) {
for (int i = k - k; i < knownFrequencies.length; i++) {
char[] d = new char[knownFrequencies.length];
d[i] = (char) (k + i);
if (c[j] == d[i]) {//checking to see if char in text equals char in d array
counter[i]++;
knownFrequencies[i] = (double) counter[i] / total;
}
}
}
fileIO.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.err.println(e);
System.exit(0);
}
}
/**
* Main decryption method used to take coded text from a file, figure out the positions in the CaesarCipher
* and then decode it onto another file.
*
* #param cipherTextFileName
* #param outputFileName
* #return
*/
public int decrypt(String cipherTextFileName, String outputFileName) {
Scanner fileIO;
int numberOfPositions = 0;
double distance = 0.000000;
try {
fileIO = new Scanner(new File(cipherTextFileName));
PrintWriter writer = new PrintWriter(new File(outputFileName));
String temp = "";
while (fileIO.hasNext()) {
//reading into file and storing it into a string called temp
temp += fileIO.next().toLowerCase().replaceAll(" ", "");
}
fileIO.close();
do {
distance = 0.0;
int total = 0;
double[] observedFreq = new double[NUMBER_OF_LETTERS];
temp = decrypt(temp, numberOfPositions);
char[] c = temp.toCharArray(); //store decrypted chars into an array
total += c.length; // how many characters are in text
int k = (int) 'a'; // int value of lowercase letter 'a'
int[] counter = new int[NUMBER_OF_LETTERS]; //use to count the number of characters in text
for (int j = 0; j < total; j++) {
for (int i = k - k; i < observedFreq.length; i++) {
char[] d = new char[observedFreq.length];
d[i] = (char) (k + i);
if (c[j] == d[i]) { //checking to see if char in text equals char in d array
counter[i]++;
observedFreq[i] = (double) counter[i] / total;
}
}
}
//Formula for finding distance that will determine the numberOfPositions in CaesarCipher
for (int j = 0; j < knownFrequencies.length; j++) {
distance += Math.abs(knownFrequencies[j] - observedFreq[j]); //This is the part of the code I am having trouble with
}
numberOfPositions = numberOfPositions + 1;
} while (distance > 0.6); //This is the part of the code I am having trouble with
Scanner fileIO2 = new Scanner(new File(cipherTextFileName));
while (fileIO2.hasNextLine()) {
//reading into file and storing it into a string called temp
temp = fileIO2.nextLine();
writer.println(decrypt(temp, numberOfPositions));
}
writer.close();
fileIO2.close();
System.out.println(distance);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.err.println(e);
System.exit(0);
}
return numberOfPositions;
}
/**
* CaesarCipher decrypt and encrypt methods
*
* #param ciphertext
* #param numberOfPositions
* #return
*/
public String decrypt(String ciphertext, int numberOfPositions) {
// TODO Auto-generated method stub
return encrypt(ciphertext, -numberOfPositions);
}
public String encrypt(String msg, int offset) {
offset = offset % 26 + 26;
StringBuilder encoded = new StringBuilder();
for (char i : msg.toCharArray()) {
if (Character.isLowerCase(i)) {
int j = (i - 'a' + offset) % 26;
encoded.append((char) (j + 'a'));
} else if (Character.isUpperCase(i)) {
int h = (i - 'A' + offset) % 26;
encoded.append((char) (h + 'A'));
} else {
encoded.append(i);
}
}
return encoded.toString();
}
// barebones main method to test your code
public static void main(String[] args) {
// args[0] contains the filename of the training file
// args[1] contains the filename of the cipher text file
// args[2] contains the filename of the output file
CodeBreaker cb = new CodeBreaker();
cb.train(args[0]);
System.out.println(cb.decrypt(args[1], args[2]));
}
}

The standard method of decoding a Caesar cypher is called, "running down the alphabet". Essentially a brute force solution; you try all the possibilities. Since there are only 26 possible keys, it is not that difficult.
Taking your example:
WKH SURJUDP ZDV KRVWHG ...
wkh surjudp zdv krvwhg ...
xli tvskveq aew lswxih ...
ymj uwtlwfr bfx mtxyji ...
znk vxumxgs cgy nuyzkj ...
aol wyvnyht dhz ovzalk ...
bpm xzwoziu eia pwabml ...
cqn yaxpajv fjb qxbcnm ...
dro zbyqbkw gkc rycdon ...
esp aczrclx hld szdepo ...
ftq bdasdmy ime taefqp ...
gur cebtenz jnf ubfgrq ...
hvs dfcufoa kog vcghsr ...
iwt egdvgpb lph wdhits ...
jxu fhewhqc mqi xeijut ...
kyv gifxird nrj yfjkvu ...
lzw hjgyjse osk zgklwv ...
max ikhzktf ptl ahlmxw ...
nby jlialug qum bimnyx ...
ocz kmjbmvh rvn cjnozy ...
pda lnkcnwi swo dkopaz ...
qeb moldoxj txp elpqba ...
rfc npmepyk uyq fmqrcb ...
sgd oqnfqzl vzr gnrsdc ...
the program was hosted ...
uif qsphsbn xbt iptufe ...
vjg rtqitco ycu jquvgf ...
wkh surjudp zdv krvwhg ...
It is simple enough for a human to find the correct line with only 26 to pick from. For a computer it is more difficult. Your idea of counting letter frequencies is good. You might also mark down letter pairs like "qx" and mark up pairs like "th". Calculate the score for all 26 possible results and pick the highest scoring result. As long as you have tuned your scoring method well, then you have a good chance of finding the right solution.

Taking the suggestion from rossum, and realizing that my initial class was a total mess that nobody could understand. I rewrote the class using bunch of methods this time instead of clumping everything into one or two methods, and now the class works perfectly. I am up for any suggestions to make the code more efficient. To me it seems a little redundant so any suggestion for improvement are welcome. This was for a class assignment which the due date has passed, so this code is going to be for reference.
public class CodeBreaker {
//Setting up instance variables and setter/getter methods
public final int NUMBER_OF_LETTERS = 26;
private int numberOfPositions = 0;
private double[] knownFrequencies = new double[NUMBER_OF_LETTERS];
private double[] observedFreq = new double[NUMBER_OF_LETTERS];
public double[] getKnownFrequencies() {
return knownFrequencies;
}
public void setKnownFrequencies(double[] knownFrequencies) {
this.knownFrequencies = knownFrequencies;
}
//This method reads text from a long file, breaks it down into individual characters, and stores it in the knownFrequencies array
public void train(String trainingFileName) {
String tempString = "";
double totalChars = 0.0;
try {
#SuppressWarnings("resource")
Scanner FileIO = new Scanner(new File(trainingFileName)).useDelimiter("[ *-,!?.]+"); //reading text from a file using
//the delimiter so we get all of the contents
while(FileIO.hasNext()){
tempString += FileIO.next().toLowerCase();//storing contents into a string, all lower case
}
FileIO.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.err.println(e);
System.exit(0);
}
//Figuring out total number of English letters(a-z) used to determine the frequencies
for(int j = 0; j < tempString.length(); j++){
char ch = tempString.charAt(j);
if(Character.isAlphabetic(ch)){
totalChars++;
}
}
//Initializing the knownFrequencies array with each individual letter count a-z
for (int k = 0; k <= tempString.length()-1; k++){
char ch = tempString.charAt(k);
double chValue = (double) ch;
if (Character.isAlphabetic(ch)) {
if(chValue >= 97 && chValue <= 122){
knownFrequencies[ch - 'a']++;
}
}
}
//Divide the individual letter counts by the total to get a decimal number
//for the frequency and store that into the knownFrequencies array.
for (int i = 0; i < knownFrequencies.length; i++) {
if(knownFrequencies[i] > 0){
knownFrequencies[i] = knownFrequencies[i]/totalChars;
}
}
}
//This method does practically the same thing in the train method except it doesn't read from a file, and it compiles all of the
//cipher text characters to find the frequencies that will be used later to determine the key
public void setObservedFreq(String tempString)//String parameter takes in the cipher text
{
//Finding total number of lower case English letters (a-z)
double totalChars = 0.0;
for(int j = 0; j < tempString.length(); j++){
char ch = tempString.charAt(j);
if(Character.isAlphabetic(ch)){
totalChars++;
}
}
//Initializing observedFreq with the number of letters in the string.
for (int k = 0; k <= tempString.length()-1; k++){
char ch = tempString.charAt(k);
double chValue = (double) ch;
if (Character.isAlphabetic(ch)) {
if(chValue >= 97 && chValue <= 122){
observedFreq[ch - 'a']++;
}
}
}
//Re-initializing with a decimal frequency.
for (int i = 0; i < NUMBER_OF_LETTERS; i++) {
if(observedFreq[i] > 0){
observedFreq[i] = observedFreq[i]/totalChars;
}
}
}
//This method subtracts the absolute value of the observedFreq from the knownFrequencies, sum all those together and store it
//in a variable that will be return in the method. The smallest distance value means the cipher text has been decoded.
public double findDistance(){
double distance = 0.0;
for(int x = 0; x < NUMBER_OF_LETTERS; x++){
distance += Math.abs(knownFrequencies[x] - observedFreq[x]);
}
return(distance);
}
//This method finds a int value that will be used as the key to decipher the cipherText
public int findNumberOfPositions(String cipherText){
int smallestIndex = 0;
double [] indexArray = new double [NUMBER_OF_LETTERS];
//We are going through all possible shifts (up to 25) to see and storing those distances into the indexArray.
for(int i = 0; i < NUMBER_OF_LETTERS; i ++){
setObservedFreq(decrypt(cipherText,i));
indexArray[i] = findDistance();
}
//Determine which index in the array has the smallest distance
double currentValue = indexArray[0];
for (int j=0; j < NUMBER_OF_LETTERS; j++) {
if (indexArray[j] < currentValue)
{
currentValue = indexArray[j];
smallestIndex = j;
}
}
return smallestIndex; //The index is returned and will be used for the key when the message is decrypted
}
//Read in a file that contains cipher text decrypt it using the key that was found in the findNumberOfPositions method
//then write the plain text into a output file.
public int decrypt(String cipherTextFileName, String outputFileName) {
String tempString = "";
try {
#SuppressWarnings("resource")
Scanner FileIO = new Scanner(new File(cipherTextFileName)).useDelimiter("[ *-,!?.]+");
while(FileIO.hasNext()){
tempString += FileIO.next().toLowerCase();//read into a file and store lower case text it into tempString
}
FileIO.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.err.println(e);
System.exit(0);
}
numberOfPositions = findNumberOfPositions(tempString); //call our findNumberOfPositions method to find the key
try {
Scanner scan = new Scanner(new File(cipherTextFileName));
PrintWriter writer = new PrintWriter(new File(outputFileName));
while(scan.hasNextLine()){
writer.println(decrypt(scan.nextLine(), numberOfPositions)); //key is then used to decrypt the message and gets
//printed into another file.
}
writer.close();
scan.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.err.println(e);
System.exit(0);
}
return numberOfPositions;
}
//Caesar Cipher encrypt and decrypt methods
public String decrypt(String ciphertext, int numberOfPositions) {
// TODO Auto-generated method stub
return encrypt(ciphertext, -numberOfPositions);
}
public String encrypt(String msg, int offset){
offset = offset % 26 + 26;
StringBuilder encoded = new StringBuilder();
for (char i : msg.toCharArray()) {
if (Character.isLowerCase(i)) {
int j = (i - 'a' + offset) % 26;
encoded.append((char) (j + 'a'));
}
else if(Character.isUpperCase(i)){
int h = (i - 'A' + offset) % 26;
encoded.append((char) (h + 'A'));
}
else {
encoded.append(i);
}
}
return encoded.toString();
}
public static void main(String[] args) {
// args[0] contains the filename of the training file
// args[1] contains the filename of the cipher text file
// args[2] contains the filename of the output file
CodeBreaker cb = new CodeBreaker();
cb.train(args[0]);
cb.decrypt(args[1], args[2]);
}
}

Related

Can't compare 2 strings if a letter in first string exists in second string - java

However I had an assignment of programming in java related to a text i already have under (text).
the function is supposed to as below
getEncryptedText(int shift)
return a string representation of ciphertext given that the text to be manipulated is the plaintext using Caesar Cipher.
The number of rotation is depend on the shift value;
positive shift value represent the right rotation while negative shift value represent left
rotation. However, unlike explain in Wikipedia, this method used following string as
plain:
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Other characters than above will be treated as it is (i.e. will not been encrypted)
*Further reading: https://en.wikipedia.org/wiki/Caesar_cipher
So this is the class method I have made so far and wanted to know how can i keep the text chars which aren't included in the plaintext i have such as "!,#,#,$,%... and so on". So far i tried everything but couldn't make it but the rest seems fine!
public String getEncryptedText(int shift) {
String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
String cipherText = "";
for (int i = 0; i < text.length(); i++){
{
int charPosition = ALPHABET.indexOf(text.charAt(i));
if(text.charAt(i) == ' ') {
cipherText += " ";
}
else
{
int keyVal = (shift + charPosition) % 62;
char replaceVal = ALPHABET.charAt(keyVal);
cipherText += replaceVal;
}
}
}
return cipherText;
}
Consider modifying your if statement and using the StringBuilder class:
class Main {
public static void main(String[] args) {
CesarCypherHelper cesarCypherHelper = new CesarCypherHelper();
System.out.println(cesarCypherHelper.getEncryptedText("Hello World!", 2));
System.out.println(cesarCypherHelper.getEncryptedText("Hello World!", 64));
}
}
class CesarCypherHelper {
public String getEncryptedText(String text, int shift) {
String ALPHABET =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder encryptedText = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
int charPosition = ALPHABET.indexOf(ch);
if (charPosition == -1) {
encryptedText.append(ch);
} else {
int keyVal = (shift + charPosition) % ALPHABET.length();
encryptedText.append(ALPHABET.charAt(keyVal));
}
}
return encryptedText.toString();
}
}
Output:
Jgnnq Yqtnf!
Jgnnq Yqtnf!

Java Encrypting/Decrypting Assignment: Offsetting Characters

I'm stuck on some code for a class of mine. My professor encourages asking questions on forums such as this, especially since it gives him less questions :), so I figured I'd ask all of you for help.
The purpose of my assignment is to encrypt and decrypt and input string by shifting, or offseting, the characters over how of many times the user tells it to. My code is below.
For some reason, I got an error when I decrypt my encrypted text, and the error only occurs with numbers of 6 or more when run my code, so if used professor's example and encrypted "subterfuge" to offset 6 characters to make "yahzkxlamk" and then try to decrypt the text to offset 6 characters again to make "subterfuge", it gives me an error. The error is
java.lang.StringIndexOutOfBoundsException: String index out of range: -6
When I run the code with the same input string, "subterfuge", but with an offset of 5 or less, it works. The error is said to occur at the 65th line of the below code where it says
sb.append(alphabet.charAt(offset));
at the end of my Decrypt() method in the last else statement.
import javax.swing.*;
public class Encryptor {
private String plainText;
private int shift;
public String cipherText;
public Encryptor() {
plainText = null;
shift = 0;
}
public static void main(String[] args) {
//encryption block
Encryptor e = new Encryptor();
String strCipherText = e.Encrypt();
System.out.println("encrypted text");
System.out.println(strCipherText);
//decrypt block
Encryptor d = new Encryptor();
//cipher text becomes the input text to the Decrypt method
d.cipherText = strCipherText;
String strPlainText = d.Decrypt();
System.out.println("decrypted text");
System.out.println(strPlainText);
System.exit(0);
}//end of main method
public String Decrypt()
{
plainText = cipherText;
shift = Integer.parseInt(JOptionPane.showInputDialog("enter offset"));
int offset=0;
int newOffset=0;
String alphabet ="abcdefghijklmnopqrstuvwxyz";
StringBuffer sb = new StringBuffer();
int index = plainText.length();
for(int i=0;i<index;i++)
{
String temp = "" + plainText.charAt(i);
offset = alphabet.indexOf(temp);
offset -= shift;
if(offset > 25)
{
newOffset = offset % 26;
sb.append(alphabet.charAt(newOffset));
}
else
{
sb.append(alphabet.charAt(offset));
}
}//end of for loop
return sb.toString();// return encrypted string
}
public String Encrypt()
{
plainText = ((String)JOptionPane.showInputDialog("enter words " + "to encrypt")).toLowerCase().trim();
shift = Integer.parseInt(JOptionPane.showInputDialog("enter offset"));
int offset=0;
int newOffset=0;
String alphabet = "abcdefghijklmnopqrstuvwxyz";
StringBuffer sb = new StringBuffer();
int index = plainText.length();
for(int i=0;i<index;i++)
{
String temp = "" + plainText.charAt(i);
offset = alphabet.indexOf(temp);
offset += shift;
if(offset > 25)
{
newOffset = offset % 26;
sb.append(alphabet.charAt(newOffset));
}
else
{
sb.append(alphabet.charAt(offset));
}
}//end of for loop
return sb.toString();// return encrypted string
}
}
Here is your problem:
offset = alphabet.indexOf(temp);
offset -= shift;
if(offset > 25)
{
newOffset = offset % 26;
sb.append(alphabet.charAt(newOffset));
}
else
{
sb.append(alphabet.charAt(offset));//< New offset is less than 0
}
What you want is a positive-only mod function. So just add do this after you do your modular division:
while(newOffset < 0)
newOffset += 26;
What I tend to do is just make a function for this:
/* Positive modular division. */
public static int pmod(int num, int mod)
{
num %= mod;
if(num < 0) num += mod;
return num;
}

Attempting to write a Vigenere Cipher java code with user input

I am attempting to, in java, write a program that will encode a string like a vigenere cipher. An example run would be
java Encrypt -e lemon < in.txt > out.txt
in.txt should read ATTACKATDAWN, and out.txt should read LXFOPVEFRNHR, and if an insufficient # of args are used it should print the usage statement; However, when I run the encryption method on this, it returns "??¡????¡??£?", and if i run the decryption method on THAT, it returns "?? ???? ????", and if I put in less than the required two args, it returns
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at Encrypt.main(Encrypt.java:22)
here is my code
import java.util.Scanner;
public class Encrypt
{
public static void main(String[] args)
{
Scanner scan = new Scanner (System.in);
String msg = scan.nextLine();
String key = args[1];
if (args.length < 2)
{
System.out.println("Encryption program by ----");
System.out.println("Usage: java Encrypt [-e, -d] < inputFile > outputFile");
System.exit(0);
}
else if (args[0].equals ("-e"))
{
String emsg = encrypt(args[1], msg);
System.out.println(emsg);
}
else if (args[0].equals ("-d"))
{
String dmsg = decrypt(args[1], msg);
System.out.println(dmsg);
}
}
public static void usage(String[] args)
{
if (args.length < 2)
{
System.out.println("Encryption program by --------");
System.out.println("Usage: java Encrypt [-e, -d] < inputFile > outputFile");
System.exit(0);
}
}
public static String encrypt(String key, String msg)
{
String emsg = "";
for (int i = 0; i < msg.length(); i++)
{
int m = msg.charAt(i);
int k = key.charAt(i % key.length());
int e = (m + (k - 32));
char s = (char) e;
if (e > 126)
e = (e - (127 - 32));
emsg += s;
}
return emsg;
}
public static String decrypt(String key, String msg)
{
String dmsg = "";
for (int i = 0; i < msg.length(); i++)
{
int m = msg.charAt(i);
int k = key.charAt(i%key.length());
int e = (m - (k - 32));
char s = (char) e;
if (e > 126)
e = (e - (127 - 32));
dmsg += s;
}
return dmsg;
}
}
I honestly dont know what I am doing wrong; ANY assistance would be very welcome!
You get an ArrayIndexOutOfBoundsException because you access the second element of the array:
String key = args[1];
before you've tested the length of args. Get rid of this line entirely, since you don't refer to key anywhere else in your application. (A good IDE should have told you this already).
For your encryption code, I think you'll find this quite challenging unless you limit yourself to only upper-case (or lowercase) letters. Assuming you go for upper-case, then subtracting 65 from the ASCII value will give you a convenient 0-25 value work with with. Then you can use addition, modulo-26 to achieve your goal.
I've fixed up your encryption, now try doing the decryption:
public static String encrypt(String key, String msg) {
String emsg = "";
final int offset = 'A'; // 65
for (int i = 0; i < msg.length(); i++) {
int m = msg.charAt(i) - offset;
int k = key.charAt(i % key.length()) - offset;
int e = (m + k) % 26;
char s = (char) (e + offset);
emsg += s;
}
return emsg;
}

Java Eclipse Encryption Trouble

I need to make a program that will encrypt and decrypt what the user enters. I am having trouble figuring out a way that will combine all the chars to make the encrypted word. Here is my code (I am using Eclipse):
import java.util.Scanner;
public class Encryption
{
public static String message = "";
public static boolean hasMessage = false;
public static boolean encrypted = false;
static char a = 0;
static char b;
static int w;
static int x;
static int y;
static int z;
static int i;
public static void display()
{
System.out.println("Message: " + message + "\n");
}
public static void encrypt(String word)
{
if(!hasMessage)
{
System.out.println("No message");
// Tell the user there is no message
}
else if(encrypted)
{
System.out.println("Message is already encrypted");
// Tell the user the message is already encrypted
}
else
{
// Reset the message to blank
for (int i = 0; i < message.length(); i++) {
i = j;
``char a = message.charAt(i);
for (int j=0; j==message.length(); j++)
{
int w = (int) a * 2;
int x = (int) w + 2;
char y = (char) x;
}
}
}
=
//get char from each letter (increase char each time), cast as int
}
System.out.println(message);
encrypted = true;
// Using the parameter word, modify message
// to contain a new value following a predictable pattern
// Hint: alter each character's ASCII value by casting
// to an integer and using math operators
// Display the new message
// Set encrypted to true
}
public static void decrypt(String word)
{
if(!hasMessage)
{
System.out.println("No message");
// Tell the user there is no message
}
else if(!encrypted)
{
System.out.println("Message not encrypted");
// Tell the user the message is not encrypted
}
else
{
int a = (int) w / 2;
int w = (int) x - 2;
char x = (char) y;
System.out.println(message);
// Like encrypt, but in reverse
}
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int menuChoice = 0;
while(menuChoice != 4)
{
System.out.println( "[1] Enter Word\n" +
"[2] Encrypt\n" +
"[3] Decrypt\n" +
"[4] Quit\n");
menuChoice = sc.nextInt();
if(menuChoice == 1)
{
System.out.println("Input message");
message = sc.next();
// prompt user to input message
// assign next word to the class-level variable message
hasMessage = true;
encrypted = false;
// set hasMessage to true
// set encrypted to false
}
else if(menuChoice == 2)
{
encrypt(message);
}
else if(menuChoice == 3)
{
decrypt(message);
}
}
}
}
The trouble probably from the for loop. I don't really know what this for loop should do so I can't help you to change it.
for (message.charAt(a); a==message.length(); a++)
{
int w = (int) a * 2;
int x = (int) w + 2;
char y = (char) x;
}
What this does in pseudocode:
Ask for the character at 0 in string a and do nothing. This is only wasting time so I don't know what this actually is for.
Check if the message is empty if yes go on otherwise quite the loop.
Execute the code in this loop.
I guess what you want to do is loop through the string char by char like this:
for (int i = 0; i < message.length(); i++) {
char a = message.charAt(i);
}

Simple caesar cipher in java

Hey I'm making a simple caesar cipher in Java using the formula [x-> (x+shift-1) mod 127 + 1] I want to have my encrypted text to have the ASCII characters except the control characters(i.e from 32-127). How can I avoid the control characters from 0-31 applying in the encrypted text. Thank you.
How about something like this:
public String applyCaesar(String text, int shift)
{
char[] chars = text.toCharArray();
for (int i=0; i < text.length(); i++)
{
char c = chars[i];
if (c >= 32 && c <= 127)
{
// Change base to make life easier, and use an
// int explicitly to avoid worrying... cast later
int x = c - 32;
x = (x + shift) % 96;
if (x < 0)
x += 96; //java modulo can lead to negative values!
chars[i] = (char) (x + 32);
}
}
return new String(chars);
}
Admittedly this treats 127 as a non-control character, which it isn't... you may wish to tweak it to keep the range as [32, 126].
Map your characters from [32..127] to [0..95], do a mod 95+1 and map the result back to [32..127].
Usually cipher text is base64 encoded, base16 (hex) also works well. Base64 is used most often for cipher text because it takes up less space than hex, hex is most commonly used for message digests. In the java.util.prefs.Base64 library you will find byteArrayToBase64() and base64ToByteArray().
On a side note you should NEVER write your own encryption algorithm for security reasons, you should be using a block cipher or stream cipher. I hope this is for fun!
there! Is there any way to consider the whole range of characters? For example, "á", "é", "ö", "ñ", and not consider " " (the [Space])? (For example, my String is "Hello World", and the standard result is "Khoor#Zruog"; I want to erase that "#", so the result would be "KhoorZruog")
I'm sure my answer is in this piece of code:
if (c >= 32 && c <= 127)
{
// Change base to make life easier, and use an
// int explicitly to avoid worrying... cast later
int x = c - 32;
x = (x + shift) % 96;
chars[i] = (char) (x + 32);
}
... But I've tried some things, and the didn't work :S So, I'll wait for your answers :D See you!
Why not try
for(int i = 0; i < length; i++)
{
char c = chars[i]
if(Character.isLetter(c))
{
int x = c - 32;
x = (x + shift) % 96;
chars[i] = (char) (x+32);
}
}
Copy paste this in NetBeans with name "caesar":
//package caesar;
import java.io.*;
public class caesar {
int offset=3;
public String encrypt(String s) throws IOException
{
StringBuilder sb=new StringBuilder();
for(int i=0;i<s.length();i++)
{
char t=s.charAt(i);
if(t>='A' && t<='Z')
{
int t1=t-'A'+offset;
t1=t1%26;
sb.append((char)(t1+'A'));
}
else if(t>='a' && t<='z')
{
int t1=t-'a'+offset;
t1=t1%26;
sb.append((char)(t1+'a'));
}
}
return sb.toString();
}
public String decrypt(String s) throws IOException
{
StringBuilder sb=new StringBuilder();
for(int i=0;i<s.length();i++)
{
char t=s.charAt(i);
if(t>='A' && t<='Z')
{
int t1=t-'A'-offset;
if(t1<0)t1=26+t1;
sb.append((char)(t1+'A'));
}
else if(t>='a' && t<='z')
{
int t1=t-'a'-offset;
if(t1<0)t1=26+t1;
sb.append((char)(t1+'a'));
}
}
return sb.toString();
}
public static void main(String[] args) {
try
{
System.out.println("Caesar encrypion technique");
BufferedReader b;
String oriTxt,encTxt,decTxt;
System.out.println("Enter string to encrypt:");
b=new BufferedReader(new InputStreamReader(System.in));
oriTxt=b.readLine();
caesar c=new caesar();
encTxt=c.encrypt(oriTxt);
System.out.println("Encrypted text :"+encTxt);
decTxt=c.decrypt(encTxt);
System.out.println("Derypted text :"+decTxt);
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
import java.util.Scanner;
//caeser
public class Major_Assingment {
public static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZhh";
public static String encrypt(String plainText,int shiftKey)
{
plainText = plainText.toUpperCase();
String cipherText= " ";
for(int i=0; i<plainText.length(); i++)
{
int charPosition = ALPHABET.indexOf(plainText.charAt(i));
int keyVal = (shiftKey + charPosition)% 26 ;
char replaceVal = ALPHABET.charAt(keyVal);
cipherText += replaceVal;
}
return cipherText;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the string for Encryption:");
String message = new String();
message = sc.next();
System.out.println(encrypt(message,3));
sc.close();
}
}

Categories