RSA Encrypting and Decrypting JAVA - java

I've been trying to decrypt my encrypted message for a while now, but it isn't working as I'd like it to. I have my outputs for encryption working, but I can't decrypt the encrypted message!
Here are my values:
P: 67
Q: 71
PQ: 4757
PhiPQ: 4620
E: 13
D: 1777
Here is my output for the encrypted message (when 'hello' is entered):
???? (Which is working fine)
Here is my output for the decrypted message (when 'hello' is entered):
1109 314 2309 2309 4015 (Which is working, but does not give me back the characters 'hello')
We're supposed to implement this formula into the code (C^D)%PQ but I'm not entirely sure how to implement it when decrypting the encrypted message.
I'm not sure what the problem is, here is my code below:
ENCRYPTION
String encryptedMessage = "";
String message = JOptionPane.showInputDialog(null, "Enter a message: ");
int c = 0;
for (int i = 0; message.length() > i; i++) {
char l = message.charAt(i);
int m = l;
c = 1;
int newE = e;
while (newE > 0) {
if (newE % 2 != 0) {
c = ((c * m) % (pq));
}
newE = newE / 2;
m = (((m * m)) % (pq));
}
encryptedMessage = encryptedMessage + (char) c;
}
System.out.println("Encrypted Message is: " + encryptedMessage);
DECRYPTION
String decryptedMessage = "";
c = 0;
for (int i = 0; encryptedMessage.length() > i; i++) {
char l = encryptedMessage.charAt(i);
int m = l;
c = 1;
int newE = e;
while (newE > 0) {
if (newE % 2 != 0) {
c = ((c * m) % (pq));
}
newE = newE / 2;
m = (((m * m)) % (pq));
}
decryptedMessage = decryptedMessage + " " + (c);
}
// prints out 'decryptedMessage' value
System.out.println("Decrypted Message is: " + decryptedMessage);
}
}

Your code for encryption and decryption look, well, symmetric. That's not the trick with RSA. In RSA, you have the public key e for encryption and the private key d for decryption. I don't even see d in your decryption code?!

#EJP was right.
I put in the decryption key and it worked perfectly! So, instead of my encryption key being newE, I switched it with newD and it finally works now. It was a stupid, small mistake on my part. Thanks for the hints!

Related

RC4 encryption PRGA method throwing odd exceptions

I'm currently implementing a chat program that lets the user choose between RC4 and TEA encryption. It's a partner assignment, and I have taken RC4. I've used the wikipedia page mostly, as well as our book (which the code I believe is the same as on the wikipedia page).
https://en.wikipedia.org/wiki/RC4
Going off of the code on there, I've changed it into Java. Note that my convertKey method will be taking in a key from a separate class which utilizes Diffie-Hellman to obtain the key (I have the key hard coded right now to ensure RC4 works as intended), but only my RC4 class is non-functional, so unless specifically requested (since the other classes work fine and this RC4 one doesn't use them currently) I will just paste the RC4 class to avoid wasted space.
STACK TRACE:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -24 at cryptochat2.RC4.PRGA(RC4.java:80) at cryptochat2.RC4.main(RC4.java:132) Java Result: 1 –
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package cryptochat2;
/**
*
* #author Braydon
*/
//Initialize array of 256 bytes
// Run KSA on them (key stream algorithm)
// Run PRGA on KSA to generate keystream
// XOR the data with the keystream
import java.util.Arrays;
import java.util.*;
import java.util.stream.IntStream;
// The interesting feature of RC4 is that the key can be of any length from 1 to 256
//bytes. And again, the key is only used to initialize the permutation S.
//Note that the 256-byte array K is filled by simply repeating the key until
//the array is full.
public class RC4 {
byte[] lookUpTable = new byte[256]; // S
byte[] key = new byte[256];
byte[] initializedKey = new byte[256]; // key
byte[] keyStream;
byte keyStreamByte;
boolean generatingOutput;
//int key;
int keylength = 256;
// Call KSA then PRGA
public void KSA() {
// uses identity permutation while also converting to bytes
// then must process S
for (int k = 0; k < 256; k++) {
lookUpTable[k] = (byte) k;
}
// now processing permutation of array
int j = 0;
int tempOne = 0;
int tempTwo = 0;
for (int k = 0; k < 256; k++) {
j = (j + lookUpTable[k] + initializedKey[k % keylength]) % 256;
// Switching S[i] and S[j]
byte tmp;
for (int i = 0; i < 256; i++) {
j = (j + lookUpTable[i] + initializedKey[i]) & 0xFF;
tmp = lookUpTable[j];
lookUpTable[j] = lookUpTable[i];
lookUpTable[i] = tmp;
}
}
}
//Error in PRGA-- arrayIndexOutOfBounds, value differs based on key but
// error remains the same. It's an issue with the following method.
public void PRGA() {
int i = 0;
int j = 0;
byte tmp;
boolean generatingOutput = true;
while (generatingOutput) {
i = (i + 1) % 256;
j = (j + lookUpTable[i]) % 256;
for (int k = 0; k < 256; k++) {
j = (j + lookUpTable[i] + initializedKey[i]) & 0xFF;
tmp = lookUpTable[j];
lookUpTable[j] = lookUpTable[i];
lookUpTable[i] = tmp;
}
int keyStreamByteTemp = ((lookUpTable[i] + lookUpTable[j]) % 256);
try {// error's in this part vvvvvv
keyStreamByte = lookUpTable[keyStreamByteTemp];
System.out.println("keystream byte: " + keyStreamByte);
} catch (IndexOutOfBoundsException exception){
System.out.println(keyStreamByte + " has given an exception");
}
}
}
public void convertKey(int key) {
// call this first. it gives us our key.
int nonByte = key;
byte bytedKey = (byte) key;
// We create an int array and from it we initialize our key byte array
int[] data = IntStream.generate(() -> bytedKey).limit(256).toArray();
for (int i = 0; i < 256; i++) {
initializedKey[i] = (byte) data[i];
}
keylength = numberOfLeadingZeros(key);
}
public static int numberOfLeadingZeros(int i) {
// http://stackoverflow.com/questions/2935793/count-bits-used-in-int
if (i == 0) {
return 32;
}
int n = 1;
if (i >>> 16 == 0) {
n += 16;
i <<= 16;
}
if (i >>> 24 == 0) {
n += 8;
i <<= 8;
}
if (i >>> 28 == 0) {
n += 4;
i <<= 4;
}
if (i >>> 30 == 0) {
n += 2;
i <<= 2;
}
n -= i >>> 31;
return n;
}
public static void main(String[] args) {
RC4 RC4 = new RC4();
// temp hard coded key
RC4.convertKey(16);
RC4.KSA();
RC4.PRGA();
}
}
While I have a general understanding of RC4, it's very possible that I have an element or two confused, or incorrect, or something like that. The try/catch block gives me an infinite loop (due to the generatingOutput boolean I'd imagine, and since we aren't passing in an actual message yet) of numbers, positive and negative, throwing IndexOutOfBounds exceptions, until I stop the program.
keystream byte: -53
keystream byte: 105
105 has given an exception
keystream byte: 6
6 has given an exception
keystream byte: -111
keystream byte: 73
73 has given an exception
keystream byte: 66
keystream byte: -86
keystream byte: -104
keystream byte: -114
keystream byte: -117
keystream byte: 56
keystream byte: 67
67 has given an exception
keystream byte: 121
keystream byte: 10
keystream byte: -7
keystream byte: 16
keystream byte: 103
103 has given an exception
keystream byte: -65
-65 has given an exception
keystream byte: 31
31 has given an exception
keystream byte: 21
I would really appreciate any help, I'd like to learn this well and not disappoint my professor or myself.

Java: Scanner Issue?

I have a pretty simple little program here that reads in an integer, encrypts it, and then decrypts it, but for whatever reason sometimes it gives me the right answers while other times it doesn't. Code:
public class Cipher {
public static void main(String[] args) {
System.out.println("Welcome to Caesar Cipher Demo:");
Scanner scanner = new Scanner(System.in);
CaesarCipher cipher = new CaesarCipher();
int a, n, x, y;
int i = 1;
while(true) {
System.out.println("====== General Test ======");
System.out.println("Please specify the following numbers:");
System.out.printf("n - ");
n = scanner.nextInt();
scanner.nextLine();
System.out.print("a - ");
a = scanner.nextInt();
scanner.nextLine();
cipher.setN(n);
cipher.setA(a);
//scanner.nextLine();
System.out.printf("plaintext value from [0 - %d] - ", (n-1));
x = scanner.nextInt();
y = cipher.encrypt(x);
System.out.printf("ciphertext value - %d%n", y);
x = cipher.decrypt(y);
System.out.printf("back to plaintext value - %d%n", x);
scanner.nextLine();
System.out.printf("Continue? (1 for yes, 0 for no) - ");
i = scanner.nextInt();
scanner.nextLine();
if(i == 0) break;
}
while(true){
System.out.println("====== Text Message Test ======");
cipher.setN(26);
System.out.printf("key [0-25] - ");
a = scanner.nextInt();
scanner.nextLine();
while(a < 0 || a > 25){
System.out.printf("key must be from [0-25] - ");
a = scanner.nextInt();
scanner.nextLine();
}
cipher.setA(a);
System.out.printf("plaintext (use English alphabet)- ");
String plaintext = scanner.nextLine();
plaintext = plaintext.toLowerCase();
String ciphertext = cipher.encrypt(plaintext);
System.out.printf("ciphertext - %s%n", ciphertext);
plaintext = cipher.decrypt(ciphertext);
System.out.printf("plaintext - %s%n", plaintext);
System.out.printf("Continue? (1 for yes, 0 for no) - ");
i = scanner.nextInt();
scanner.nextLine();
if(i == 0) break;
}
}
}
class CaesarCipher {
private int a;
private int n;
private char[] letters;
public CaesarCipher() {
this.letters = new char[]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
}
public int getA() {
return a;
}
public int getN() {
return n;
}
public void setA(int a) {
this.a = a;
}
public void setN(int n) {
this.n = n;
}
public int encrypt(int x){
if (x >= n){
System.out.println("X must be less than "+n+"-1");
}
return (a+x) % n;
}
public int inverseOf(int e){
return (n - e %n);
}
public int decrypt(int y){
if (y >= n) {
System.out.println("N must be "+ n +"-1");
}
return (inverseOf(a) + y % n);
}
public String encrypt(String plaintext){
char[] ciphertext= new char[plaintext.length()];
for (int j = 0; j<plaintext.length();j++) {
char c = plaintext.charAt(j);
int index = c- 'a';
if (index < 0 || index > 25) {
System.out.println("Illegal character!");
System.exit(1);
}
index = encrypt(index);
ciphertext[j] = letters[index];
}
return new String(ciphertext);
}
public String decrypt(String ciphertext){
char[] plaintext = new char[ciphertext.length()];
for (int j = 0; j < ciphertext.length();j++) {
char c = ciphertext.charAt(j);
int index = c- 'a';
index = decrypt(index);
plaintext[j] = letters[index];
}
return new String(plaintext);
}
}
Output I'm getting:
Welcome to Caesar Cipher Demo:
====== General Test ======
Please specify the following numbers:
n - 54
a - 44
plaintext value from [0 - 53] - 15
ciphertext value - 5
back to plaintext value - 15
Continue? (1 for yes, 0 for no) - 1
====== General Test ======
Please specify the following numbers:
n - 78
a - 55
plaintext value from [0 - 77] - 7
ciphertext value - 62
back to plaintext value - 85
Continue? (1 for yes, 0 for no) - 1
====== General Test ======
Please specify the following numbers:
n - 55
a - 54
plaintext value from [0 - 54] - 6
ciphertext value - 5
back to plaintext value - 6
Continue? (1 for yes, 0 for no) - 1
====== General Test ======
Please specify the following numbers:
n - 632
a - 43
plaintext value from [0 - 631] - 66
ciphertext value - 109
back to plaintext value - 698
Continue? (1 for yes, 0 for no) - 1
====== General Test ======
Please specify the following numbers:
n - 25
a - 3
plaintext value from [0 - 24] - 5
ciphertext value - 8
back to plaintext value - 30
Continue? (1 for yes, 0 for no) -
As you can see, sometimes it returns the right back to plaintext value and sometimes it adds n and the plaintext value from [0 - n-1]. I believe this is due to a scanner issue, but can't figure out where exactly the problem is coming from. I was hoping another set of eyes could see something I can't. Thanks for your time, I really do appreciate it!
I'm not sure what you are trying to do in your decrypt function, especially the method inverseOf. But it's not correct. What you want in the decrypt function is just to subtract the key from the encrypted value (and then keep it in the correct range using the modulo operator, and and extra check that's it not negative because the modulo operator in itself is not enough to keep the value inside the bottom end of the range)
public int decrypt(int y) {
if (y >= n) {
System.out.println("N must be " + n + "-1");
}
if (y < a)
return (y - a + n) % n;
else
return (y - a) % n;
}

Encrypting with large numbers, using a Caesar Cipher

Right now I have the following code for a Caesar Cipher, but I run into an issue when I try encrypting text with a very large number.
For example 1000.
static String encrypt(String plaintext) {
StringBuilder ciphertext = new StringBuilder(plaintext);
for (int i = 0; i < ciphertext.length(); i++) {
ciphertext.setCharAt(i, encrypt(ciphertext.charAt(i)));
}
return ciphertext.toString();
}
static String decrypt(String plaintext) {
StringBuilder ciphertext = new StringBuilder(plaintext);
for (int i = 0; i < ciphertext.length(); i++) {
ciphertext.setCharAt(i, decrypt(ciphertext.charAt(i)));
}
return ciphertext.toString();
}
static char encrypt(char c) {
return (char) ('!' + (c - '!' + 1000) % ('~' - '!' + 1));
}
static char decrypt(char c) {
return (char) ('!' + (c - '!' - 1000) % ('~' - '!' + 1));
}
Lets say I input "abc123" into the encryption, using 1000 as my key, I get a bunch of unknown characters. Keep in mind I don't want it to just cycle through a-z but symbols too, using ASCII codes.
Any help would be great!
In Java, the result of modulo is the same sign as the dividend. So when you compute c - '!' - 1000 you will get a negative value and after the modulo it will still be negative. When you add '!', you will have computed a values less than '!', which will be invisible or underflow for a char.
static char decrypt(char c) {
char d = '~' - '!' + 1;
int x = (c - '!' - 1000) % d;
if (x < 0) x += d;
return (char)('!' + x);
}
Here is a discussion for the problem your running into.
How does java do modulus calculations with negative numbers?

Vigenère cipher implementation

I have to implement a variant of the Vigenère cipher. I got the encryption part without issues, but I have a bug in the decryption code and I don't understand what I'm doing wrong.
The requirements are:
the key can only contain A - Z (uppercase)
code values for the key characters are 0 for A, 1 for B, ..., and 25 for Z
do not encode a character if the code is < 32 (preserve control characters)
encrypted character code = original character code + key character code
the final encrypted character must be between 32 and 126, exclusively so if the final encrypted character > 126 it must be brought back into the 32 - 126 range by adding 32 to the value and then subtracting 126
The encryption code:
// it works ok
// I have tested it with some provided strings and the results are as expected
public String encrypt(String plainText)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < plainText.length(); i++) {
char c = plainText.charAt(i);
if (c >= 32) {
int keyCharValue = theKey.charAt(i % theKey.length()) - 'A';
c += keyCharValue;
if (c > 126) {
c = (char) (c + 32 - 126);
}
}
sb.append(c);
}
return sb.toString();
}
The decryption code:
// there probably is an off-by-one error somewhere
// everything is decrypted ok, except '~' which gets decrypted to ' ' (space)
public String decrypt(String cipherText)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < cipherText.length(); i++) {
char c = cipherText.charAt(i);
if (c >= 32) {
int keyCharValue = theKey.charAt(i % theKey.length()) - 'A';
c -= keyCharValue;
if (c < 32) {
c = (char) (c + 126 - 32);
}
}
sb.append(c);
}
return sb.toString();
}
Example (with key ABCDEFGHIJKLMNOPQRSTUVWXYZ):
original ~~~~~~~~~~~~~~~~~~~~~~~~~~
encrypted ~!"#$%&'()*+,-./0123456789
decrypted ~ ('~' followed by spaces)
EDIT:
Here is the code I use for testing (it tests every character from 0 to 126 repeated as a string):
public static void main(String[] args) {
int passed = 0;
int failed = 0;
String key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int c = 0; c <= 126; c++) {
StringBuilder sbString = new StringBuilder();
for (int i = 0; i <= 25; i++) {
sbString.append((char) c);
}
String original = sbString.toString();
Cipher cipher = Cipher(key);
String encrypted = cipher.encrypt(original);
String decrypted = cipher.decrypt(encrypted);
if (!original.equals(decrypted)) {
failed++;
System.out.println("--FAILED--");
System.out.println(original);
System.out.println(encrypted);
System.out.println(decrypted);
} else {
passed++;
}
}
int tests = passed + failed;
System.out.println(tests + " tests");
System.out.println("passed: " + passed);
System.out.println("failed: " + failed);
}
I believe the If(c < 32) in the decryption needs to be If (c <= 32).
Reasoning: if you take the case of Char(126) or '~' then add one to it in the encryption you get 127, which goes through the encryption transform and becomes 33.
When decrypting that you get 33 minus that same 1 which leaves you with 32, which won't trigger the special decryption case. By including 32 in that statement it will trigger the special decryption and change the 32 (" ") to 126 ("~")
You are correct it is an off by one error, but it is kinda subtle
EDIT: there is a collision error because char(32) and char(126) are hashing to the same value. In my previous example that value would be 33, the equation needs to be changed such that Char(126) will hash to 32.
Changing the c = (char) (c + 32 - 126); to c = (char) (c + 32 - 127); should free up the extra space to prevent the collision from happening. THe decrypt will also have to be changed from c = (char) (c + 126 - 32); to c = (char) (c + 127 - 32);
And someone posted that in my comments.

The error about string encryption scheduling : (char) (ch + key) % 26

Problem one: Here are two code spinner. Code A runs wrong. But I do not know what is wrong.
Problem two: code B is right.but I do not understand why it need to delete 'A’. then add 'A' after fmod. What is the effect about 'A'? Why it has the error after delete?
Code A (ch + key) % 26 )
Code B ('A' + ((ch -'A' + key) % 26))
public void run() {
setFont("Arial-PLAIN-24");
String line = readLine ("Enter line: ");
int key = readInt ("Enter key: ");
String siphertext = encryptCaesar(line , key);
println("The result is: " + siphertext);
String newplain = encryptCaesar(siphertext , -key);
println("newplain:" + newplain);
}
private String encryptCaesar(String str , int key){
if(key < 0){
key = 26 - ( -key % 26 );
}
String result = "";
for(int i = 0; i < str.length(); i++){
char ch = str.charAt(i);
result += encryptChar(ch,key);
}
return result;
}
private char encryptChar(char ch, int key){
if(Character.isUpperCase(ch)){
return ( (char) ('A' + ((ch -'A' + key) % 26)) );
}
return ch;
}
'A' is added to make sure the result of "encryptChar" method, is a valid character in ASCII range 64 to 90, which is A (CAPITAL) to Z (CAPITAL). Refer the ASCII table here.
In your code subtracting of 'A' can also be ignored. That is the below will also work,
('A' + ((ch + key) % 26))
15.7.3 Remainder Operator %
...
It follows from this rule that the result of the remainder operation
can be negative only if the dividend is negative, and can be positive
only if the dividend is positive.
An example is then provided:
int e = (-5)%3; // -2
int f = (-5)/3; // -1
System.out.println("(-5)%3 produces " + e +
" (note that (-5)/3 produces " + f + ")");
If the result of ((ch -'A' + key) % 26)) is negative, then wouldn't the result of (char) ('A' + ((ch -'A' + key) % 26)) be some non-alphabet character? Perhaps you need to add 26 to any negative values or find the absolute value, so that they're positive and result in actual alphabet characters.

Categories

Resources