How to encrypt / decrypt a text by using RSA method? - java

I have a simple java code that encrypts and decrypts numbers using the RSA algorithm
If anyone could help me to make this code reads a text (string) from the user and decrypt it instead of only numbers but in a simple way so I can draw a flowchart for the code afterward :)
https://codedost.com/css/java-program-rsa-algorithm/
import java.util.*;
import java.math.*;
public class RSA {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int p, q, n, z, d = 0, e, i;
System.out.println("Enter the number to be encrypted and decrypted");
int msg = sc.nextInt();
double c;
BigInteger msgback;
System.out.println("Enter 1st prime number p");
p = sc.nextInt();
System.out.println("Enter 2nd prime number q");
q = sc.nextInt();
n = p * q;
z = (p - 1) * (q - 1);
System.out.println("the value of z = " + z);
for (e = 2; e < z; e++) {
if (gcd(e, z) == 1) // e is for public key exponent
{
break;
}
}
//e should be in the range 1-z
System.out.println("the value of e = " + e);
// calculate d
for (i = 0; i <= 9; i++) {
int x = 1 + (i * z);
if (x % e == 0) //d is for private key exponent
{
d = x / e;
break;
}
}
System.out.println("the value of d = " + d);
c = (Math.pow(msg, e)) % n;
//Encryptin C = msg ^e mod n
System.out.println("Encrypted message is : -");
System.out.println(c);
//converting int value of n to BigInteger
BigInteger N = BigInteger.valueOf(n);
//converting float value of c to BigInteger
BigInteger C = BigDecimal.valueOf(c).toBigInteger();
msgback = (C.pow(d)).mod(N);
//Decrypt , P = Cˆd mod N , msgback = P
System.out.println("Derypted message is : -");
System.out.println(msgback);
}
static int gcd(int e, int z) {
if (e == 0) {
return z;
} else {
return gcd(z % e, e);
}
}
}

As you already implemented encryption and decryption for single number you can easily extend it and provide support for longer messages. In fact, the only change you need is to perform same operation N times (for each character in input message). Have a look at below code:
import java.util.*;
import java.math.*;
public class Rsa {
private static final Scanner sc = new Scanner(System.in);
private int p, q, n, z, d = 0, e, i;
public Rsa() {
System.out.println("Enter 1st prime number p");
p = sc.nextInt();
System.out.println("Enter 2nd prime number q");
q = sc.nextInt();
n = p * q;
z = (p - 1) * (q - 1);
System.out.println("the value of z = " + z);
for (e = 2; e < z; e++) {
if (gcd(e, z) == 1) // e is for public key exponent
{
break;
}
}
//e should be in the range 1-z
System.out.println("the value of e = " + e);
// calculate d
for (i = 0; i <= 9; i++) {
int x = 1 + (i * z);
if (x % e == 0) //d is for private key exponent
{
d = x / e;
break;
}
}
System.out.println("the value of d = " + d);
}
private static int gcd(int e, int z) {
if (e == 0) {
return z;
} else {
return gcd(z % e, e);
}
}
double encrypt(int msg) {
//Encrypting C = msg ^e mod n
return (Math.pow(msg, e)) % n;
}
double[] encrypt(String msg) {
int[] charactersAsNumbers = new int[msg.length()];
for(int i = 0; i < msg.length(); i++) {
charactersAsNumbers[i] = msg.codePointAt(i);
}
System.out.println("Plain text as sequence of numbers: " + Arrays.toString(charactersAsNumbers));
double[] encryptedMsg = new double[msg.length()];
for(int i = 0; i < charactersAsNumbers.length; i++) {
encryptedMsg[i] = encrypt(charactersAsNumbers[i]);
}
return encryptedMsg;
}
BigInteger decrypt(double encrypted) {
//converting int value of n to BigInteger
BigInteger N = BigInteger.valueOf(n);
//converting float value of c to BigInteger
BigInteger C = BigDecimal.valueOf(encrypted).toBigInteger();
//Decrypt , P = Cˆd mod N , msgback = P
return (C.pow(d)).mod(N);
}
String decrypt(double[] encrypted) {
StringBuilder builder = new StringBuilder();
for(double encryptedCharacter: encrypted) {
BigInteger decryptedCharacter = decrypt(encryptedCharacter);
builder.append(Character.toChars(decryptedCharacter.intValue()));
}
return builder.toString();
}
public static void main(String args[]) {
System.out.println("Enter the text to be encrypted and decrypted");
String msg = sc.nextLine();
Rsa rsa = new Rsa();
double[] c = rsa.encrypt(msg);
System.out.println("Encrypted message is: " + Arrays.toString(c));
String msgBack = rsa.decrypt(c);
System.out.println("Decrypted message is: " + msgBack);
}
}
What I did here is:
Overloaded encrypt and decrypt methods. Now they support longer messages; encrypt accepts String parameter and returns double[], decrypt accepts double[] and returns String
Logic moved to methods without changing original data types and general flow
I know given solution is not optimal but I guess performance and code style aren't critical for you in this case.
Hope it helps you solve your problem.
Edit: I improved logs slightly, here is the sample output (and input):
Enter the text to be encrypted and decrypted
Secret.
Enter 1st prime number p
13
Enter 2nd prime number q
19
the value of z = 216
the value of e = 5
the value of d = 173
Plain text as sequence of numbers: [83, 101, 99, 114, 101, 116, 46]
Encrypted message is: [239.0, 43.0, 112.0, 95.0, 43.0, 51.0, 50.0]
Decrypted message is: Secret.

Related

Affine Cypher in Java

I'm an Engineering Student and I'm stuck on this part of the Affine Cypher.
import java.util.Scanner;
public class abcd {
public static int a, b;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter key(a,b): ");
a = sc.nextInt();
b = sc.nextInt();
Scanner hj = new Scanner(System.in);
System.out.print("Enter String: ");
String word = hj.nextLine();
sc.close();
hj.close();
System.out.println("Cyphered text: " + cypher(word));
System.out.println("Decyphered text: " + decypher(cypher(word)));
}
public static String cypher(String plaintext) {
String CT = "";
for (int i = 0; i < plaintext.length(); i++) {
char x = plaintext.charAt(i);
int val = (char)x-97;
int C = ((a* val + b)%26);
char n = (char) (C + 97);
CT = CT + n;
}
return CT;
}
public static int inv (int a, int b) {
a=a%b;
for (int x = 1; x<26; x++) {
if ((a*x)%26==1) {
return x;
}
}
return 1;
}
public static String decypher(String cyphertext) {
String t = "";
for (int i = 0; i<cyphertext.length(); i++) {
char x = cyphertext.charAt(i);
int val = (char)x - 97;
int D = ((inv(a, 26)*(val-b))%26);
char n = (char)(D + 97);
t = t + n;
}return t;
}
}
The cyphered text shows the desired output but the deciphered text doesn't match the original text.
Here is my console input and output:
Enter key(a,b):
7
2
Enter String: hello
Cyphered text: zebbw
Decyphered text: heRRo
I was expecting the deciphered text to match the original text since that is what it was supposed to do.
As Joachim Sauer and Tan Yu Hau Sean suggest, % does things you may not expect on negative numbers. If a is negative, a%b will be a number between -b and 0.
If you add a method like this
public static int mod(int a, int b) {
return (a%b+b)%b;
}
and replace your instances of % with calls to it, e.g.:
int C = mod(a* val + b,26);
things will work a lot better.

Converting Binary to Decimal Numbers in Java strictly using multiplication and division

I am trying to get my Binary to Decimal method to calculate properly. I have to use the multiply and/or divide methods in the "bToD" method. I can't figure out how to get it return the answer correct. It should only be returning "5", but instead it is returning 45. I need to fix this method in order to continue the remaining Hexadecimal to Binary and Octal to Binary methods.
package numType;
import java.util.Scanner;
public class numType{
public static String multiply2(String n) { //return 2*n
String r = "";
int c = 0;
for (int i = n.length()-1; i >= 0; i--) {
int p = (n.charAt(i)-'0')*2+c;
c = p/10;
r = p%10+r;
}
if (c > 0)
r = c+r;
return r;
}
public static String divide2(String n) { //return n/2
String r = "";
int b = 0;
int i = 0;
if (n.charAt(0) < '2') {
b = 1;
i = 1;
}
for (; i < n.length(); i++) {
int p = (n.charAt(i)-'0')+b*10;
b = p%2;
r += p/2;
}
if (r.length() == 0)
r = "0";
return r;
}
//convert binary string b to an equivalent decimal string.
public static String bToD(String b)
{
String s = "";
int n = 0;
if (b.charAt(b.length()-1) == '1')
n = 1;
else
n = 0;
int pow = 1; //INITIALIZE POWER # FROM THE SECOND TO LAST 2^1
for (int i=b.length()-2; i>=0; i--) // LIST #'S FROM MOST RIGHT-HAND SIDE
{
char ch = b.charAt(i);
String temp = "" + ch;
for (int j=1; j<=pow; j++)
temp = multiply2(temp);
//System.out.println(temp);
int n1 = 0;
for (int k=0; k<temp.length(); k++)
{
n1 = n1*10 + (int) (temp.charAt(k)-'0');
}
n = n + n1;
s = temp;
pow++;
}
s = s + n;
return s;
}
//convert decimal string d to an equivalent binary string.
public static String dToB(String d)
{
String s = "";
while (!d.equals("0"))
{
String d1 = divide2(d);
d1 = multiply2(d1);
if (d1.equals(d))
s = "0" + s;
else
s = "1" + s;
d = divide2(d);
}
return s;
}
//convert binary string b to an equivalent octal string.
public static String bToO(String b)
{
String s = "";
int groups = b.length()/3;
int index = 0;
//System.out.println(index); //bToD(b)
while (groups != index)
{
for (int i = b.length()-3; i >= 0; i--)
{
for (int j=1; j<=i; j++)
{
String temp = b.substring(b.length()-3,b.length()); //last 3 digits in binary
String sSub = b.substring(0,b.length()-3); //first digits in binary
s = bToD(temp);
}
}
index++;
}
return s;
}
//convert octal string o to an equivalent binary string.
public static String oToB(String o)
{
String s ="";
int digits = o.length();
int index = 0;
while (digits != index)
{
for (int i=o.length()-1; i>=0; i--)
{
char ch = o.charAt(i);
//System.out.println(digits);
switch (ch)
{
case '7':
s = s + "111";
index++;
break;
case '6':
s = s + "110";
index++;
break;
case '5':
s = s + "101";
index++;
break;
case '4':
s = s + "100";
index++;
break;
case '3':
s = s + "011";
index++;
break;
case '2':
s = s + "010";
index++;
break;
case '1':
s = s + "001";
index++;
break;
case '0':
s = s + "000";
index++;
break;
}
}
}
return s;
}
//convert binary string b to an equivalent hexadecimal string.
public static String bToH(String b)
{
String s ="";
return s;
}
//convert hexadecimal string h to an equivalent binary string.
public static String hToB(String h)
{
String s ="";
return s;
}
public static void main(String[] args) {
// TODO code application logic here
String b,d,o,h;
b = "101";
System.out.println("Binary to Decimal:");
System.out.println(b + " => " + bToD(b));
System.out.println();
System.out.println("Decimal to Binary:");
d = "45";
System.out.println(d + " => " + dToB(d));
System.out.println();
System.out.println("Binary to Octal:");
b = "100101101";
System.out.println(b + " => " + bToO(b));
System.out.println();
System.out.println("Octal to Binary:");
o = "";
System.out.println(o + " => " + oToB(o));
System.out.println();
System.out.println("Binary to Hexadecimal:");
b = "";
System.out.println(b + " => " + bToH(b));
System.out.println();
System.out.println("Hexadecimal to Binary:");
h = "";
System.out.println(h + " => " + hToB(h));
}
}
Here's a solution, yours is quite convoluted.
//convert binary string b to an equivalent decimal string.
public static String bToD(String b)
{
int ans = 0, pow = 0;
//For every digit in binary
for(int i=b.length()-1; i>=0; i--){
// Get string of current char
String cur = Character.toString(b.charAt(i));
for (int j=0; j<pow; j++)
cur = multiply2(cur);
ans += Integer.parseInt(cur);
pow++;
}
return Integer.toString(ans);
}

RSA encryption sometimes works other time won't

Guys I really need your help, is this code correct? sometimes if I run it and change the word IMAHACKER to THANKYOU or anything it would work but when I run it again it wouldn't show the message. I think the problem is with the generated numbers? but how do I fix it. I'd really appreciate it if you help because I can't seem to figure out the mistake!
import java.util.*;
public class R{
private Random rnd= new Random();
//Finds the greatest common divisor of two integers, a and b
//Input: a and b integers
//Output: gcd of a and b, using Euclidean method
public long gcd(long a, long b) {
if (b==0)
return a;
return gcd(b,a%b);
}
//Finds the multiplicative inverse of a modulo m
//Input: a an integer, and modulus m
//Output: i: inverse of a modulo m, such that (a*i mod m)=1
public long find_inverse(long a, long m)
{
for (long i=1; i<m; i++)
{
long test=i*a;
if ((test%m)==1)
return i;
}
return 0;
}
//Generates a random prime number
//Input: None
//Output: A random prime number between 2 and 10000
public int random_prime()
{
boolean found=false;
int p=0;
while (!found)
{
p=rnd.nextInt(10000);
found= isPrime(p);
}
return p;
}
//Check if a number is prime or not
//Input: integer p
//Output: True if p is a prime number
//and False if it is composite
public boolean isPrime(int p)
{
if (p>1){
for (int i=2; i<= Math.sqrt(p); i++)
{
if (p%i==0)
return false;
}
return true;
}
return false;
}
static long t=0;
//Generate Keys method
//Input: None
//Output: n_e_d an array of longs containing:
//n_e_d[0]: the modulus n(which is p*q)
//n_e_d[1]: the exponent d(public key)
//n_e_d[2]: d is inverse of e modulo (p-1)*(q-1) (private key)
public long[] generate_keys()
{
long[] n_e_d= new long[3];
int p = random_prime();
int q = random_prime();
long n = p*q;
long euler = (p-1)*(q-1);
t = euler;
int e = random_prime();
long GCD = gcd (e, euler);
while ( e > euler && e < 1 && GCD != 1 )
e = random_prime();
long d = find_inverse(e, euler);
n_e_d[0] = n;
n_e_d[1] = e;
n_e_d[2] = d;
return n_e_d;
}
//Find (b^n mod m) when we are dealing with big numbers
//Same as algorithm 5 in 4.2 in the book
//Input: b: the base, n: the exponent, and m: the modulus
//All inputs are in decimal representation
//Output: Value of (b^n mod m)
public long modular_exponentiation(long b, long n, long m)
{
long x=1;
long pow=b%m;
//COMPLETE HERE (approx 5 lines)
//Convert n to binary (use method Long.toBinaryString(..))
//Iterate over the length of n
//Change pow and x as necessary
String nBi = Long.toBinaryString(n);
int a = 0;
for(int i=0;i<nBi.length();i++){
a = Character.getNumericValue(nBi.charAt(nBi.length()-(i+1)));
if(a==1)
x=(x*pow)%m;
pow=((long)Math.pow(pow,2))%m;}
return x;
}
//Convert from String_to_int
//Make sure you use two digits for each letter (e.g. 01 instead of 1)
//e.g. Input:KBL, Output: 100111
public long string_to_int(String text)
{
//COMPLETE HERE (approx 6 lines)
long num = 0;
String concat ="";
for (int i=0; i<text.length(); i++)
{
char c = text.charAt(i);
String rep = String.valueOf( c - 65 );
if ( rep.length() < 2 )
rep = "0" + rep;
concat = concat + rep ;
num = Long.parseLong(concat);
}
return num;
}
//Convert from int_to_String
//e.g. Input: 100111, Output:KBL
public String int_to_String(long inttext)
{
String text="";
long num=0;
while(inttext>1){
num= inttext%100;
text = String.valueOf((char)(num+65))+text;
inttext = inttext/100;
}
return text;
/*
String text="";
String i = inttext + "";
for(int j=0;j<i.length();j+=2)
text +=Integer.parseInt(i.charAt(j)+""+i.charAt(j+1))>-1 && Integer.parseInt(i.charAt(j)+""+i.charAt(j+1))<26? String.valueOf((char)((Integer.parseInt(i.charAt(j)+""+i.charAt(j+1)))+65)) : null;
return text;*/
}
public int intoBlocks(String s){
int len=0;
int c=0;
if(s.length()%2==0)
len = s.length()/2;
else
len=(s.length()/2)-1;
// System.out.println(len);
return len;
}
public String[] ArrayinBlocks(String s, int x){
String arr[] = new String[s.length()/x];
int j=0;
for(int i=0;i<s.length();i+=x){
arr[j]=s.substring(i,Math.min(s.length(),(i+x)));
j++;}
return arr;
}
//Encryption method
//Input: plaintext, e and n, where:
//Plaintext is a String of uppercase letters only
//e is the public key
//n is the modulus
//Output: Ciphertext, which is an array of longs, each element
// represents the ciphertext of the ith block
public long[] encrypt(String plaintext, long e, long n)
{long[] ciphertext;
int block=intoBlocks(plaintext);
//System.out.println(block);
int t = block;
if(block%2==0){
t = block/2;
ciphertext=new long[block/2];}
else
ciphertext=new long[block];
long C;
//COMPLETE HERE (approx 10 lines)
//Split text into blocks of appropriate size, get their integer representation,
String arr[] = ArrayinBlocks(plaintext,intoBlocks(plaintext));
// System.out.println(arr[0] + " " + arr[1]);
for(int i=0;i<t;i++)
ciphertext[i] = string_to_int(arr[i]);
System.out.println(ciphertext[0] + " " + ciphertext[1]);
for(int i=0;i<arr.length;i++)
ciphertext[i] = modular_exponentiation(ciphertext[i], e, n);
return ciphertext;
}
//Decryption method
//Input: ciphertext, d and n, where:
//Ciphertext is an array of longs, each element represents the ciphertext of the ith block
//d is the private key
//n is the modulus
//Output: Plaintext as a String
public String decrypt(long[] ciphertext, long d, long n)
{
String plaintext="";
for(int i=0;i<ciphertext.length;i++)
plaintext+=int_to_String(modular_exponentiation(ciphertext[i],d,n));
return plaintext;
}
public static void main(String[] args)
{
R cipher= new R(); //Create an instance of your cryptographic system
//Before starting, you must generate your keys
long[] n_e_d= cipher.generate_keys();
System.out.println("Modulus n is: "+n_e_d[0]);
System.out.println("Public key e is: "+n_e_d[1]);
System.out.println("Private key d is: "+ n_e_d[2]);
//Encrypt the plaintext using exponent e and modulus n
long[] ciphertext=cipher.encrypt("IMAHACKER", n_e_d[1],n_e_d[0]);
//Print each of the ciphertext blocks
for (long block: ciphertext)
System.out.print (block+ " ");
System.out.println();
//Decrypt the ciphertext and print out the plaintext
String plaintext=cipher.decrypt(ciphertext, n_e_d[2], n_e_d[0]);
System.out.println("Decrypting ciphertext we get: "+plaintext);
}
}

How to resolve the error in the following code

I have written this code to generate the bit stream corresponding to string a and then invert
specific bits in a bit stream.the variable cc gets an integer value in the processing before the code snippet.
However it gives Array Index Out Of Bounds Exception on the following line.
if(sb2.charAt(cc)=='1')
can anyone tell me what is the probable cause?
package abc1;
import java.util.Scanner;
public class abc2 {
public static void main(String s[]) {
String seckey = " ";
String cbs = " ";
String a = "Manikaparasher";
System.out.println("String originally:" + a);
char[] car = a.toCharArray();
StringBuilder sb = new StringBuilder();
for (char c : car) {
cbs = Integer.toBinaryString((int) c);
sb.append(cbs);
}
Scanner sc = new Scanner(System.in);
System.out.println(" Enter your passkey ");
int n = sc.nextInt();
int ul, ll;
double nv1, nv2, ns;
ll = n * 3;
ul = n * 7;
nv1 = ll + (Math.random() * (ul - ll));
nv2 = ll + (Math.random() * (ul - ll));
int nv11 = (int) nv1 % 7; //inversion bit
int nv22 = (int) nv2 % 3; //embedding bit
ns = ll + (Math.random() * (ul - ll));
int ns1 = (int) ns % 5;//start bit
if (nv11 == nv22) {
nv11++;
}
if (nv22 == ns) {
ns++;
}
if (nv11 == ns) {
nv11++;
}
seckey = "I" + nv11 + "E" + nv22 + "S" + ns1;
System.out.println(seckey);
System.out.println("old" + sb.toString());
System.out.println("nv11" + nv11);
StringBuilder sb2 = new StringBuilder(sb);
int cc = 0;
while (!cbs.isEmpty()) {
cc = cc + nv11;
if (sb2.charAt(cc) == '1') {
sb2.setCharAt(cc, '0');
sb2.append(sb);
} else {
sb2.setCharAt(cc, '1');
sb2.append(sb);
}
}
System.out.println("new" + sb2.toString());
}
}
You haven't put anything inside sb2 variable before calling
if(sb2.charAt(cc)=='1')
and what ever the cc value, it exceeds the sb2.length() size.

Extracting polynomial variables from String input via a constructor

I was hoping somebody could help me with with this. I am trying to add a constructor to allow the input of polynomial data from a string in the form 3x^y and put the coefficient, variable, and exponent values into the corresponding variables defined in a class. The constructor I have implemented allows the program to compile, but will freeze when running the application if...
this:
trinomial[0] = new Term (3,'x',2);
is set to:
trinomial[0] = new Term ("3x^y");
Basically, I'm trying to get the defined class to accept both forms of input (string and double/char/exponent formats). Any help with this would be greatly appreciated.
public class TrinomialTest {
static void printTrinomial(Term[] x) {
for (int i = 0; i < x.length; i++) {
//AUTOMATICALLY CALLS TOSTRING() WHEN PRINTLN
System.out.print(x[i]);
}
}
public static void main(String[] args) {
Term[] trinomial = new Term[3];
trinomial[0] = new Term(3, 'x', 2);
trinomial[1] = new Term(12, 'x', 1);
trinomial[2] = new Term(-23, 'x', 0);
printTrinomial(trinomial);
}
}
class Term {
private double coefficient; //the number
private char variable; // the letter
private int exponent;
public Term(double c, char v, int e) {
coefficient = c;
variable = v;
exponent = e;
}
//New Constructor
public Term(String Term) {
String c = "";
String v = "";
String e = "";
int exponentIndex = 0;
exponentIndex = Term.indexOf("^");
if (Term.substring(0, 1).matches("[0-9]")) {
c = Term.substring(0, 1);
v = Term.substring(1, 2);
} else {
c = "0";
v = Term.substring(0, 1);
}
do {
e = Term.substring(exponentIndex, exponentIndex + 1);
} while (Term.indexOf("^") != -1);
coefficient = Double.parseDouble(c);
variable = v.charAt(0);
exponent = Integer.parseInt(e);
}
public String toString() {
int c = (int) coefficient;
if (exponent == 1 && c > 0)
return ("" + "+" + c + variable);
else if (exponent == 1 && c < 0)
return ("" + c + variable);
else if (exponent == 0 && c > 0)
return ("" + "+" + c);
else if (exponent == 0 && c < 0)
return ("" + c);
return ("" + c + variable + "^" + exponent);
}
}
Simple solution:
String term = "32x^33";
String[] tokens = term.split("\\^");
String coeff = tokens[0].substring(0, tokens[0].length()-1);
String var = tokens[0].substring(tokens[0].length()-1, tokens[0].length());
String exp = tokens[1];
System.out.println("coeff = "+coeff+", var = "+var+", exp = "+exp);

Categories

Resources