Affine Cipher decryption process wrong result - java

I have the problem when decrypting the text message. Example :
Plaintext : "halo brother"
Ciphertext : "žiÌ=ßOÌÅbO"
Plaintext : "haフo`bメothナメ"
k1 : 33 ->first key
k2 : 125 ->second key
I use ASCII printable & ASCII extended characters set total 224 characters.
Here is my code :
public class Affine {
//encyption method
public static String enkripsi(String pesan, int k1, int k2){
//change text message into array
char[] chars = pesan.toCharArray();
//getting ASCII code from each characters index
int[] ascii = new int[chars.length];
for (int i = 0; i < chars.length; i++) {
ascii[i] = (int) chars[i];
}
//Affine encryption formula
int[] c = new int[ascii.length];
for (int j = 0; j < ascii.length; j++) {
c[j] = ((k1*ascii[j])+k2) % 224 ;
}
//change the decimal (ASCII code) value back to characters
char[] charen = new char[c.length];
for (int i = 0; i < c.length; i++) {
charen[i] = (char)c[i];
}
//change characters to String
String pesan_en = String.valueOf(charen);
return pesan_en;
}
//decryption method
public static String dekripsi(String isipesanMasuk, int k1, int k2){
int j,g;
int[] c;
int[] f = new int [224];
//change text message into array
char[] chars = isipesanMasuk.toCharArray();
//getting ASCII code from each characters index
int[] ascii = new int[chars.length];
for (int i = 0; i < chars.length; i++) {
ascii[i] = (int) chars[i];
}
//getting inverse from encryption formula of Affine
//example 33f = 1 (mod) 224 -> f = (1+(224 * j)) / 5
//g = (33 * f) mod 224
//if g = 1 then stop
for (j = 1; j < 224; j++) {
f[j] = (1 +(224*j)) / k1;
g = (k1*f[j]) % 224 ;
if (g==1) {
break;
}
}
//Affine decrypion formula
c = new int[ascii.length];
for (int k = 0; k < ascii.length; k++) {
c[k] = (f[j]*(ascii[k]-k2)) % 224 ;
}
//change the decimal (ASCII code) value back to characters
char[] charde = new char[c.length];
for (int i = 0; i < c.length; i++) {
charde[i] = (char)c[i];
}
//change characters to String
String pesan_de = String.valueOf(charde);
return pesan_de;
}
}

The decryption formula breaks down if ascii[k]-k2 gives a negative value. To fix that use this:
c[k] = (f[j]*(ascii[k]-k2+224)) % 224;
Some other remarks:
you don't need an array to calculate the inverse of k1, a simple integer variable will do.
The encryption can result in control characters (\u0000 to \u000f and \u007f to \u009f) that might not be transported unaltered across all channels.

Related

2d array out of bound exception in for-loop

I'm working on keyword columnar cipher and I keep getting array out of bound exception, I have tried debugging the code and try and catch to understand the problem but I couldn't!
public Decryption (String cipherText, String keyWord) {
cipherText = cipherText.replaceAll("\\s+","");
cipherText = cipherText.toUpperCase();
cipherText = cipherText.trim();
keyWord = keyWord.toUpperCase();
int column = keyWord.length();
int row = (cipherText.length() / keyWord.length());
if (cipherText.length() % keyWord.length() != 0)
row += 1;
char [][] matrix = new char [row][column];
int re = cipherText.length() % keyWord.length();
for (int i = 0; i < keyWord.length() - re; i++)
matrix[row - 1][keyWord.length() - 1 - i] = '*';
char[] sorted_key = keyWord.toCharArray();
Arrays.sort(sorted_key);
int p = 0, count = 0;
char[] cipher_array = cipherText.toCharArray();
Map<Character,Integer> indices = new HashMap<>();
for(int i = 0; i < column; i++){
int last = indices.computeIfAbsent(sorted_key[i], c->-1);
p = keyWord.indexOf(sorted_key[i], last+1);
indices.put(sorted_key[i], p);
for(int j = 0; j < row; j++){
if (matrix[j][p] != '*')
matrix[j][p] = cipher_array[count];
count++;
}}
}
I'm getting the exception in:
matrix[j][p] = cipher_array[count];
there is a problem with the loop, if I start with j = 1 it doesn't give me the exception but I don't get the correct results (It doesn't print the last row)
The cipher text that I'm trying to decrypt:
YARUEDCAUOADGRYHOBBNDERPUSTKNTTTGLORWUNGEFUOLNDRDEYGOOAOJRUCKESPY
Keyword:
YOURSELF
The result I get when I start the loop with 1:
JUDGE YOURSELF ABOUT YOUR BACKGROUND KNOWLEDGE TO UNDERSTAND CRYP
What I'm supposed to get:
JUDGE YOURSELF ABOUT YOUR BACKGROUND KNOWLEDGE TO UNDERSTAND
CRYPTOGRAPHY
I'm not precisely sure, because your code doesnt allow me to validate this (there is no easy way to check the output of the algorithm without digging in), so... I assume that solution is:
for (int j = 0; j < row; j++) {
if (matrix[j][p] != '*'){
matrix[j][p] = cipher_array[count];
count++;
}
}
instead of:
for (int j = 0; j < row; j++) {
if (matrix[j][p] != '*')
matrix[j][p] = cipher_array[count];
count++;
}
I think that the strategy of appending '*' to the string in this case is not the way to go - like what you did. Better to append some character when you are building the grid.
Following this approach here is a fixed version of your code (check the comments in the code for the changed parts):
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Decryption {
private final String result;
public Decryption(String cipherText, String keyWord) {
cipherText = cipherText.replaceAll("\\s+", "");
cipherText = cipherText.toUpperCase();
cipherText = cipherText.trim();
keyWord = keyWord.toUpperCase();
int column = keyWord.length();
int row = (cipherText.length() / keyWord.length());
if (cipherText.length() % keyWord.length() != 0)
row += 1;
int[][] matrix = new int[row][column];
// Changed to calculate the irregular columns
int re = column - (row * column - cipherText.length());
char[] sorted_key = keyWord.toCharArray();
Arrays.sort(sorted_key);
int p, count = 0;
char[] cipher_array = cipherText.toCharArray();
Map<Character, Integer> indices = new HashMap<>();
for (int i = 0; i < column; i++) {
int last = indices.computeIfAbsent(sorted_key[i], c -> -1);
p = keyWord.indexOf(sorted_key[i], last + 1);
indices.put(sorted_key[i], p);
// Changed: Detects the need of an extra character and fills it in case of need
boolean needsExtraChar = p > re - 1;
for (int j = 0; j < row - (needsExtraChar ? 1 : 0); j++) {
matrix[j][p] = cipher_array[count];
count++;
}
if(needsExtraChar) {
matrix[row - 1][p] = '-';
}
}
result = buildString(matrix);
}
public static void main(String[] args) {
System.out.println(new Decryption("EVLNE ACDTK ESEAQ ROFOJ DEECU WIREE", "ZEBRAS").result);
System.out.println(new Decryption("EVLNA CDTES EAROF ODEEC WIREE", "ZEBRAS").result);
System.out.println(new Decryption("YARUEDCAUOADGRYHOBBNDERPUSTKNTTTGLORWUNGEFUOLNDRDEYGOOAOJRUCKESPY", "YOURSELF").result);
}
private String buildString(int[][] grid) {
return Arrays.stream(grid).collect(StringBuilder::new, (stringBuilder, ints) -> Arrays.stream(ints).forEach(t -> {
stringBuilder.append((char) t);
}), (stringBuilder, ints) -> {
}).toString().replace("-", "");
}
}
If you run this, this will print:
WEAREDISCOVEREDFLEEATONCEQKJEU
WEAREDISCOVEREDFLEEATONCE
JUDGEYOURSELFABOUTYOURBACKGROUNDKNOWLEDGETOUNDERSTANDCRYPTOGRAPHY

Affine cipher: decrypted text does not match the plain text

This is my affine encryption and decryption code.
I have char array of 26 characters. The cipher text generated by
ax + b % 26
does not match with decryption formula
a - inverse(ciphertext[c]-b) % 26
For example, when a=3 and b=5, when I encrypt r. Location of r in the character array is 17 by encryption formula:
((3*17+5) %26) = (56%26) = 4
Character at position 4 in the array is e. When I decrypt the cipher text inverse value for 3 is 9. So, Math.abs(3(4-5)%26)=3 which is incorrect.
private static String affinecipher(String plainText) {
String encrypt = "";
int value = 0;
int location=0;
String text=plainText.toUpperCase();
Scanner inputData = new Scanner(System.in);
System.out.print("Enter a:");
a = inputData.nextInt();
System.out.print("Enter b:");
b = inputData.nextInt();
for(int p = 0; p < text.length(); p++){
for(int q =0 ; q<letter.length; q++){
if(text.charAt(p)==letter[q]){
// checking each plaintext character position to letter array position.
// if match found returning the letter position
location=q;
}
}
value= (((a*location)+b) % m);
// value of a multiplied by letter position adding to b and taking the mod.
// adding the string with value position from letter
encrypt = encrypt +letter[value];
}
return encrypt;
}
//decryption
private static String decryptAffineCipher(String encryptText){
String decrypt=" ";int location=0;
//calculating the inverse value
a %= 26;
for(int x = 1; x < 26; x++) {
if((a*x) % 26 == 1) {
inverse=x;
}
}
for (int p = 0; p < encryptText.length(); p++){
for(int q =0 ; q<letter.length; q++){
//finding the location of cipher character
if(encryptText.charAt(p)==letter[q]){
location=q;
}
}
//decryption formula a-inverse(c-b)%26
int step1=Math.abs(location-b);
int step2=inverse* step1;
int value=step2 %26;
//char letter[26] that stores value from A to Z
decrypt = decrypt +letter[value];
}
return decrypt;
}

Converting integer to character in java display un readerble wrong values

I use simple method to change string values without changing original length of string.then back convert change the text back into pure string(into Original text).
My code :
String someText = "abcdefgHIJKLMN";
char[] data = someText.toCharArray();
int LEN = someText.length();
char[] datas = new char[LEN];
System.out.println("Original Text ("+String.valueOf(LEN)+"): "+someText);
for (int i = 0; i < LEN; i++) {
data[i] = Character.valueOf((char) i);
System.out.println(String.valueOf(i) + " = " + String.valueOf((char) i));
}
System.out.println("Add 10 into each charactor : "); // ex a =1 , a+10 : now it's 'k'
for (int i = 0; i < LEN; i++) {
char c = Character.valueOf((char) (Character.getNumericValue(Character.valueOf(data[i])) + 10));
datas[i] = c;
System.out.print(String.valueOf(c));
}
System.out.println("Subtract 10 from each charactor : ");// ex k =11 , k-10 : now it should be 'a'
for (int i = 0; i < LEN; i++) {
char c = (char) (Character.getNumericValue(Character.valueOf(datas[i])) - 10);
System.out.print(String.valueOf(c));
}
But after adding and subtracting that loops dose not display anything.
If there is any solution to achieve this type of things without changing original length of text?
This is the thing I want to do:
Let say character value of a is 97 then we add 10 into it:(97+10) = 107 now it's not a it's should be different letter such as k because 107 character value is :K
I think the problem is in line 8:
data[i] = Character.valueOf((char) i);
When i = 0, data[i] is not 'a'. 'a' has a value of 97 (hex 61):
http://www.utf8-chartable.de/
Moreover you can add chars using '+' but the result of '+' operator is integer, so you only have to cast it to char - ie.
char c = (char) (data[i] + 10);.
Also in your loops you used print instead of println, that's why the output was not so clear. Try the code below and see if it works out for you.
String someText = "abcdefgHIJKLMN";
char[] data = someText.toCharArray();
int LEN = someText.length();
char[] datas = new char[LEN];
System.out.println("Original Text ("+String.valueOf(LEN)+"): "+someText);
for (int i = 0; i < LEN; i++) {
System.out.println(String.valueOf(i) + " = " + data[i]);
}
System.out.println("Add 10 into each charactor : "); // ex a =1 , a+10 : now it's 'k'
for (int i = 0; i < LEN; i++) {
char c = (char) (data[i] + 10);
datas[i] = c;
System.out.println(String.valueOf(c));
}
System.out.println("Subtract 10 from each charactor : ");// ex k =11 , k-10 : now it should be 'a'
for (int i = 0; i < LEN; i++) {
char c = (char) (datas[i] - 10);
System.out.println(String.valueOf(c));
}

Converting binary to decimals and characters

I want to convert binary to decimals and characters like this:
11010 --> 1101 + 0(parity bit) -->decimals= 11 --> char ";"
10101 --> 1010 + 1 -->decimals= 5 --> char "5"
.
.
public class stringek {
String bitek = "1101010101001000001000001";
String[] bits;
String four;
char par;
int parity;
String digits;
int n = 0;
int b;
int kurens;
int decimalis;
int digit;
public stringek() {
this.kurens = 0;
bits = new String[200];
for (int i = 0; i < 25; i += 5) {
bits[n] = bitek.substring(i, i + 5);
n++;
}
for (int i = 0; i < n; ++i) {
int j = 0;
four = bits[i].substring(j, j + 4);
for (int p = 0; p < 4; ++p) {
b = Integer.parseInt(four.substring(p));
kurens += b;
}
par = bits[i].charAt(j+4);
//System.out.print(par);
parity = par-'0';
decimalis = Integer.parseInt(four, 2);
digit = decimalis + 48;
if ((kurens + parity) % 2 == 0) {
System.out.println("Binarys: "+four+"-"+par+" = "+"'"+(char)digit+"'"+" Decimalis:"+decimalis+" Parity <INVALID> ");
}
else{
System.out.println("Binarys: "+four+"-"+par+" = "+"'"+(char)digit+"'"+" Decimalis:"+decimalis+" Parity <VALID> ");
}
}
}
}
but my program results this:
Binarys: 1101-0 = '=' Decimalis:13 Parity <INVALID>
Binarys: 1010-1 = ':' Decimalis:10 Parity <VALID>
Binarys: 0010-0 = '2' Decimalis:2 Parity <INVALID>
Binarys: 0001-0 = '1' Decimalis:1 Parity <INVALID>
Binarys: 0000-1 = '0' Decimalis:0 Parity <VALID>
Can anyone help me to resolve? I have to say cause in my case all Parity is VALID, but I don't know why here some Parity is Invalid (I know cause the results from if give me this results, but I want to know how to resolve to be VALID when is valid and INVALID when is really invalid). thanks
public String[] splitStringEvery(String s, int interval) {
int arrayLength = (int) Math.ceil(((s.length() / (double)interval)));
String[] result = new String[arrayLength];
int j = 0;
int lastIndex = result.length - 1;
for (int i = 0; i < lastIndex; i++) {
result[i] = s.substring(j, j + interval);
j += interval;
} //Add the last bit
result[lastIndex] = s.substring(j);
return result;
}
You wouldn't use String.split() or a StringTokenizer
Use a for loop that increments by 5, checking against length of your string
Use String.substring() to extract the 5 character strings.
To compute the length of the target array you need, you'll need to divide your string length by 5. A Better idea is to use a List<String>.
Use the Guava Libraries Splitter object, specifically the fixedLength(...) method which does exactly what you're trying to do.
Splitter splitter = Splitter.fixedLength(5);
Iterable<String> tokens= splitter.split(myVeryLongString);

RSA Encryption not working in java

I am working on the RSA algorithm and have made some progress but it is not working. I have the following code.
public class RSA
{
public static void main(String args[])
{
String plainText = "ITS ALL GREEK TO ME";//temp local plaintext ignoring parameter
plainText = plainText.toUpperCase();
plainText = plainText.replaceAll("\\s","");
System.out.println(plainText);
String cipherText = "";
int p = 47; //has been provided
int q = 59; //has been provided
int d = 157; //has been provided
int n = p * q;//calculate n
int w = (p - 1)*(q - 1);// calculate W
int c = 0;//we will compute this = cipher variable
int m = 920;//hardcoded for now
int e = 17;//hardcoded for now
//start of euclids
ArrayList<Integer> remainderlist=new ArrayList<Integer>();//array list to hold the remainder values in euclids algorithm from the quotient
remainderlist.add(w);// step 1 of euclids algorithm starting with value of w as above
remainderlist.add(d);// step 2 of euclids algorithm to add value of d
int remainderposition1 = 0;
int remainderposition2 = 1;
int quotient = 0;
int remainder = 0;
while (remainderlist.get(remainderposition1)%(remainderlist.get(remainderposition2))>0){
quotient = remainderlist.get(remainderposition1)/remainderlist.get(remainderposition2);
remainder = remainderlist.get(remainderposition1)%remainderlist.get(remainderposition2);
remainderlist.add(remainder);
System.out.println("Q: " +quotient);
System.out.println("R: " +remainder);
System.out.println("");
remainderposition1++;
remainderposition2++;
}
//start string processing
//loop etc
if (plainText.length()%2!=0)
{
plainText = plainText + " ";
}
for (int i = 0, i < plainText.length(); i = i+2)
{
char plTChar1 = plainText.CharAt(i);
char plTChar2 = plainText.CharAt(i + 1);
// Convert the character into an ASCII table value.
int asciiValue1 = (int) plTChar1;
int asciiValue2 = (int) plTChar2;
String numStr1 = asciiValue1.parseInt;
String numStr2 = asciiValue2.parseInt;
if (numStr.length() < 2)
{
numStr = "0" + numStr;
}
String fullNum = numStr1 + numStr2;
int m = Integer.parse(fullNum);
//start of encryption algorithm
String binarystring = Integer.toBinaryString(e);// step 1
System.out.println(binarystring);
c = 1; // step 2 of the encryption algorithm - notes
for (int i = 0; i<binarystring.length();i++)
{
c = (c*c)%n;// setp 3a
System.out.println(binarystring.charAt(i));
// step 3b notes
if (binarystring.charAt(i)=='1') {
c = (c*m)%n;
}
}
System.out.println("Cipher"+c);
}
When I build the file I get errors on the line for (int i = 0, i < plainText.length(); i = i+2) saying that quotation marks are expected and that it is an illegal start to an expression. I'm lost
You have a comma instead of a semi-colon.
for (int i = 0, i < plainText.length(); i = i+2)
Should be
for (int i = 0; i < plainText.length(); i = i+2)
Often the smallest syntax error will confuse you for hours!

Categories