1

I have a serialisable class called DataSet which has a static method Load(string filename, string password) which returns the deserialised DataSet.

Here it is:

public static DataSet Load(string filename, string password)
{
  if (!File.Exists(filename))
    throw new FileNotFoundException("File not found.", filename);

  DataSet ds;

  ICryptoTransform ct = Encryption.getDecryptor(password, salt, iv);

  using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
  {
    using (CryptoStream cs = new CryptoStream(fs, ct, CryptoStreamMode.Read))
    {
      using (GZipStream zs = new GZipStream(cs, CompressionMode.Decompress))
      {
        try
        {
          ds = (DataSet)new BinaryFormatter().Deserialize(zs);
          return ds;
        }
        catch
        {
          throw new ApplicationException("This password cannot be used to decrypt this file. Either the password is incorrect or the file is corrupt");
        }
        finally
        {
          zs.Close();
        }
      }
    }
  }
}

And I'm calling it like this:

try
{
  dataSet = DataSet.Load(ofd.FileName, ep.Password);
}
catch (ApplicationException ae)
{
  MessageBox.Show("Error:\r\n" + ae.Message, "Authorisation Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
}

With the correct password, it works fine. I'm testing it with the incorrect password. The expected result is for a MessageBox to pop up saying "This password cannot be used to decrypt this file [...]". Instead, what happens is I get an uncaught exception window.

If I'm debugging in VS, I can see that an uncaught CryptographicException occurred. I originally had a try/catch with 2 catches, one for CryptographicException and one for SerializationException. That didn't work. I replaced it to catch Exception. Finally, I have a catch all.

I don't know why, but for some reason it cannot seem to catch this? I'm sure the answer is very obvious but I just can't see it.

I know some exceptions are uncatchable such as StackoverflowException. I suspect CryptographicException is not uncatchable.

Ozzah
  • 10,631
  • 16
  • 77
  • 116

2 Answers2

0

Why are you catching with ApplicationException? If you catch with Exception you should catch the exception.

Given your comment, it looks like the exception is being thrown in one of the stream constructors. If you place your try catch around more of the code, you will catch it ok.

Nick Randell
  • 17,805
  • 18
  • 59
  • 74
  • Ok, with catch (Exception) it's catching, but behaviour is still not as expected. I'm catching all in DataSet.Load() and throwing a new ApplicationException with a particular message. Instead, the calling function catches a CryptographicException with message "Padding is invalid and cannot be removed." - Why isn't the try/catch in DataSet.Load() catching the CryptographicException??? – Ozzah May 30 '11 at 04:33
  • Ok - that makes sense. I've updated my answer to take this into account. – Nick Randell May 30 '11 at 05:51
0

The reason that your ApplicationException is not "taking precedence" is because the CryptographicException is being thrown from outside your try/catch block.

In other words, Deserialize is not the only API that can throw a CryptographicException. You simply need to enlarge your try/catch/finally block to encompass all API calls that might throw an exception. After you have done this, ApplicationException will be the only possible exception that Load can throw and your code should work as expected.

Rick Sladkey
  • 33,988
  • 6
  • 71
  • 95
  • Perfect, thanks. What was throwing me was that VS was highlighting the line inside the try/catch block rather than outside, so it didn't make sense why it wouldn't be caught. I'll know for next time ;) – Ozzah May 30 '11 at 06:14