Consider:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
impor
In actionPerformed(ActionEvent e)
you call encrypt()
, which is declared to throw Exception
. However, actionPerformed
neither catches this Exception (with try/catch around the call to encrypt()
) nor declares that it throws Exception
itself.
Your encrypt
method, however, does not truly throw Exception
. It swallows all Exceptions without even as much as logging a complaint. (Bad practice and bad style!)
Also, your encrypt
method does the following:
public static byte[] encrypt(String toEncrypt) throws Exception {
try{
....
return encrypted; // HERE YOU CORRECTLY RETURN A VALUE
} catch(Exception e) {
}
// YOU DO NOT RETURN ANYTHING HERE
}
That is, if you do catch any Exception, you discard it silently and then fall off the bottom of your encrypt
method without actually returning anything. This won't compile (as you see), because a method that is declared to return a value must either return a value or throw an Exception for every single possible code path.
The first error
java.lang.Exception; must be caught or declared to be thrown byte[] encrypted = encrypt(concatURL);
means that your encrypt
method throws an exception that is not being handled or declared by the actionPerformed
method where you are calling it. Read all about it at the Java Exceptions Tutorial.
You have a couple of choices that you can pick from to get the code to compile.
throws Exception
from your encrypt
method and actually handle the exception inside encrypt
.encrypt
and add throws Exception
and the exception handling block to your actionPerformed
method.It's generally better to handle an exception at the lowest level that you can, instead of passing it up to a higher level.
The second error just means that you need to add a return statement to whichever method contains line 109 (also encrypt
, in this case). There is a return statement in the method, but if an exception is thrown it might not be reached, so you either need to return in the catch block, or remove the try/catch from encrypt
, as I mentioned before.
You'll need to decide how you'd like to handle exceptions thrown by the encrypt
method.
Currently, encrypt
is declared with throws Exception
- however, in the body of the method, exceptions are caught in a try/catch block. I recommend you either:
throws Exception
clause from encrypt
and handle exceptions internally (consider writing a log message at the very least); or,encrypt
, and surround the call to encrypt
with a try/catch instead (i.e. in actionPerformed
).Regarding the compilation error you refer to: if an exception was thrown in the try
block of encrypt
, nothing gets returned after the catch
block finishes. You could address this by initially declaring the return value as null
:
public static byte[] encrypt(String toEncrypt) throws Exception{
byte[] encrypted = null;
try {
// ...
encrypted = ...
}
catch(Exception e){
// ...
}
return encrypted;
}
However, if you can correct the bigger issue (the exception-handling strategy), this problem will take care of itself - particularly if you choose the second option I've suggested.
All your problems derive from this
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
return encrypted;
Which are enclosed in a try, catch block, the problem is that in case the program found an exception you are not returning anything. Put it like this (modify it as your program logic stands):
public static byte[] encrypt(String toEncrypt) throws Exception{
try{
String plaintext = toEncrypt;
String key = "01234567890abcde";
String iv = "fedcba9876543210";
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec);
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
return encrypted;
} catch(Exception e){
return null; // Always must return something
}
}
For the second one you must catch the Exception from the encrypt method call, like this (also modify it as your program logic stands):
public void actionPerformed(ActionEvent e)
.
.
.
try {
byte[] encrypted = encrypt(concatURL);
String encryptedString = bytesToHex(encrypted);
content.removeAll();
content.add(new JLabel("Concatenated User Input -->" + concatURL));
content.add(encryptedTextField);
setContentPane(content);
} catch (Exception exc) {
// TODO: handle exception
}
}
The lessons you must learn from this:
The problem is in this method:
public static byte[] encrypt(String toEncrypt) throws Exception{
This is the method signature which pretty much says:
In this case the method signature says that when invoked this method "could" potentially throw an exception of type "Exception".
....
concatURL = padString(concatURL, ' ', 16);
byte[] encrypted = encrypt(concatURL); <-- HERE!!!!!
String encryptedString = bytesToHex(encrypted);
content.removeAll();
......
So the compilers is saying: Either you surround that with a try/catch construct or you declare the method ( where is being used ) to throw "Exception" it self.
The real problem is the "encrypt" method definition. No method should ever return "Exception", because it is too generic and may hide some other kinds of exception better is to have an specific exception.
Try this:
public static byte[] encrypt(String toEncrypt) {
try{
String plaintext = toEncrypt;
String key = "01234567890abcde";
String iv = "fedcba9876543210";
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec);
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
return encrypted;
} catch ( NoSuchAlgorithmException nsae ) {
// What can you do if the algorithm doesn't exists??
// this usually won't happen because you would test
// your code before shipping.
// So in this case is ok to transform to another kind
throw new IllegalStateException( nsae );
} catch ( NoSuchPaddingException nspe ) {
// What can you do when there is no such padding ( whatever that means ) ??
// I guess not much, in either case you won't be able to encrypt the given string
throw new IllegalStateException( nsae );
}
// line 109 won't say it needs a return anymore.
}
Basically in this particular case you should make sure the cryptography package is available in the system.
Java needs an extension for the cryptography package, so, the exceptions are declared as "checked" exceptions. For you to handle when they are not present.
In this small program you cannot do anything if the cryptography package is not available, so you check that at "development" time. If those exceptions are thrown when your program is running is because you did something wrong in "development" thus a RuntimeException subclass is more appropriate.
The last line don't need a return statement anymore, in the first version you were catching the exception and doing nothing with it, that's wrong.
try {
// risky code ...
} catch( Exception e ) {
// a bomb has just exploited
// you should NOT ignore it
}
// The code continues here, but what should it do???
If the code is to fail, it is better to Fail fast
Here are some related answers:
Catching Exceptions in Java
When to choose checked and unchecked exceptions
Why don’t you have to explicitly declare that you might throw some built in exceptions in Java?
Exception other than RuntimeException
In your 'encrypt' method, you should either get rid of the try/catch and instead add a try/catch around where you call encrypt (inside 'actionPerformed') or return null inside the catch within encrypt (that's the second error.