I'm trying to fix my code. In my code, I'm trying to generate a 16bit key which I've already done. Secondly, generate a random message which is also done. Encrypt and decrypt the data which I'm getting errors on. Lastly have a brute force algorithm to decrypt the message which i'll try doing later. So for my encryption the code encrypts it but doesn't encrypt the random generated string. I'm getting bunch of errors.
My Code:
import java.util.Random;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Assignment1Demo {
private static String msg;
private static String msgE;
private static String msgD;
private static int key;
public static void main(String[] args){
//TODO: You can only call methods in main method
key = generateKey();
msg = generateMsg();
msgE = encryption(key,msg);
bruteForce(msgE);
}
private static int generateKey() {
//TODO: implement step a (randomly generate 16-bit key)
//16 bit digit means 2^16 -1 in decimal
Random rand = new Random();
return rand.nextInt((int) (Math.pow(2, 16)-1));
}
private static String generateMsg() {
//TODO: implement step b (randonly generate a string with an even number of characters)
String chractersU="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String chractersL=chractersU.toLowerCase();
String space=" ";
String alphanum=chractersU+space+chractersL;
String random="";
int length=alphanum.length();
Random rand=new Random();
char[] text=new char[length];
for(int i=0;i<length;i++) {
text[i]=alphanum.charAt(rand.nextInt(alphanum.length()));
}
for(int i=0;i<text.length/2;i++) {
if(text.length%2!=0) {
random += text[i];
}}
return random;
}
private static String encryption (int key, String msg) {
//TODO: implement step c (encrypt the message)
String strData="";
String strKey=Integer.toString(key);
try {
SecretKeySpec skeyspec=new SecretKeySpec(strKey.getBytes(),"Blowfish");
Cipher cipher=Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, skeyspec);
byte[] encrypted=cipher.doFinal(msg.getBytes());
strData=new String(encrypted);
} catch (Exception e) {
e.printStackTrace();
}
return strData;
}
private static void decryption(int key, String msgE) {
//TODO: implement step d (decryption)
String strKey = Integer.toString(key);
String strData="";
try {
SecretKeySpec skeyspec=new SecretKeySpec(strKey.getBytes(),"Blowfish");
Cipher cipher=Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeyspec);
byte[] decrypted=cipher.doFinal(msgE.getBytes());
strData=new String(decrypted);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(strData);
}
private static void bruteForce(String msgE) {
//TODO: implement bruteForce algorithm, you may need the above decryption(key,msgE) method
boolean isEnglisString = msgE.matches("[a-zA-Z]+");
if(isEnglisString)
System.out.println("Yes encrypted message is Randomly English generated message " + msgE);
else
System.out.println("encrypted message is Not Randomly english generated message "+msgE);
decryption(key, msgE);
isEnglisString = msgD.matches("[a-zA-Z]+");
if(isEnglisString)
System.out.println("Yes decrypted message is Randomly english generated message "+ msgD);
else
System.out.println("decrypted message is not Randomly english generated message "+ msgD);
}}
Errors:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at java.base/com.sun.crypto.provider.BlowfishCipher.engineDoFinal(BlowfishCipher.java:319)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2189)
at Assignment1Demo.decryption(Assignment1Demo.java:110)
at Assignment1Demo.bruteForce(Assignment1Demo.java:132)
at Assignment1Demo.main(Assignment1Demo.java:30)
Exception in thread "main" java.lang.NullPointerException
at Assignment1Demo.bruteForce(Assignment1Demo.java:133)
at Assignment1Demo.main(Assignment1Demo.java:30)
Your string is randomly generated, but when the block size does not match what the cipher expects, you need to apply an acceptable padding algorithm, so the size of your input is aligned with algorithm. This is applicable to all block ciphers.
This example is a simple meter for a cipher, not that one could use something like as algorithm "AES/CBC/PKCS5Padding" "RC2/CBC/PKCS5Padding" "DESede/CBC/PKCS5Padding (PKCS#5 padding is defined for 8-byte block sizes)
Another example without the streams:
It is really not necessary, but if you wanna go with the base64, you can look for Apache: http://commons.apache.org/proper/commons-codec/
Examples using your code
1) ECB mode
Example 2) your code with CBC mode