I am doing an image Steganography project and I am implementing RSA cryptography to make the hidden message more secure.
I am using the BigInteger class, and the RSA on its own is ok, but when used after the encrypted text has been extracted from the cover image it is inconsistent in decrypting the cipher text.
RSA key = new RSA(1024);
BigInteger[] privateKey = key.getPrivKey();
String s = "Hello World";
byte[] bytes = s.getBytes();
BigInteger message = new BigInteger(bytes);
BigInteger encrypt = key.encrypt(message);
Stego steg = new Stego();
steg.encode(ImageIO.read(new File("horse_PNG2538.png")), encrypt.toString(), "stegTest");
String toDecrypt = steg.decode(ImageIO.read(new File("stegTest.png")));
BigInteger messageD = new BigInteger(toDecrypt);
BigInteger decrypt = key.decrypt(messageD, privateKey);
String plainText = new String(decrypt.toByteArray());
Encode takes in its parametes a BufferedImage, String (text to be hidden in the image) and the name of the output image.
Decode takes an image and extracts the hidden text and returns a String.
I have compared the toString() of both messageD (the cipherText extracted from the image) and encrypt, both should be the same all the time but on some runs their output differs giving the wrong plainText when decrypted.
How can I make this consistent?
Edit additional code: this is how I am embedding text into an image in Stego class;
public static BufferedImage encode(BufferedImage coverImage, String text, String newFileName) {
//create userSpace
BufferedImage userSpace = user_space(coverImage);
return embedText(userSpace, text, newFileName);
}//END OF ENCODE
public static BufferedImage embedText(BufferedImage image, String text, String name) {
int bitMask = 0x00000001;
int currentChar;
int x = 0;
int y = 0;
String toEmbed = "***" + text.length() + "***" + text;
byte[] msg = toEmbed.getBytes();
System.out.println("" + toEmbed.length());
for (int i = 0; i < msg.length; i++) {
currentChar = msg[i];
for (int j = 0; j < 8; j++) { //0-7 bits
int flag = currentChar & bitMask; // get 1 digit from the current character
if (x < image.getWidth()) {
image.setRGB(x, y, image.getRGB(x, y)& 0xFE | flag);
x++;
} else {
x = 0;
y++;
image.setRGB(x, y, image.getRGB(x, y)&0xFE | flag);
}
currentChar = currentChar >> 1; // get the next digit from the character
}
}
try {
File outputfile = new File(name + ".png");
ImageIO.write(image, "png", outputfile);
} catch (IOException e) {
e.printStackTrace();
System.out.println("Something went wrong with creating the new image");
}
return image;
}
and How I extract text;
public static String decode(BufferedImage image) {
Object[] details = isEncrypted(image);
int length = 0;
String secretMessage = "";
if ((boolean) details[0] == false) {
System.out.println("Not Encrypted");
return "nothing";
}
length = (int) details[1];
char[] temp = extractText(image, length);
for(int i = 0; i<temp.length; i++){
secretMessage += (new StringBuilder().append(temp[i])).toString();
}
return secretMessage.substring((int)details[2]);
}
public static char[] extractText(BufferedImage image, int length) {
int bitMask = 0x00000001;
int x = 0;
int y = 0;
int flag;
char[] c = new char[length];
for (int i = 0; i < length; i++) {
int bit = 0;
for (int j = 0; j < 8; j++) {
if (x < image.getWidth()) {
flag = image.getRGB(x, y) & bitMask;
x++;
} else {
x = 0;
y++;
flag = image.getRGB(x, y) & bitMask;
}
if (flag == 1) {
bit = bit >> 1;
bit = bit | 0x80;
} else {
bit = bit >> 1;
}
}
c[i] = (char) bit;
}
return c;
}