New digital signature checking in v 1.7.12 of OpenPGP Library for .NET

Version 1.7.12 of DidiSoft OpenPGP Library for .NET completely changes the outcome of the methods that verify OpenPGP digital signatures. Fortunately the .NET framework allowed us to make this big change and still offer backward compatibility with the current code base that uses versions prior to 1.7.12.

Read below:

The problem with the old design

All methods of the library that were dealing with digital signatures : Verify, DecryptAndVerify, DetachedVerify had one big problem: the outcome was a Boolean result with meanings True = signature has been verified and False = a very fuzzy situation, could be that the signature is forged, the provided for the check public key doesn’t match or there is no signature at all:

       DidiSoft.Pgp.PGPLib pgp = new DidiSoft.Pgp.PGPLib();
       // check the signature and extract the data 
       bool validSignature = pgp.Verify...
       Console.WriteLine("Valid Signature: " + validSignature);

The new solution

As of version 1.7.12 of the library all the digital signature verification methods return a value of type DidiSoft.Pgp.SignatureCheckResult. This value has static fields that describe the four possible outcomes of a signature check:

DidiSoft.Pgp.PGPLib pgp = new DidiSoft.Pgp.PGPLib();
// check the signature and extract the data 
DidiSoft.Pgp.SignatureCheckResult signatureCheck = pgp.Verify... 
 
if (signatureCheck == SignatureCheckResult.SignatureVerified)
{
   Console.WriteLine("Signature OK");
}
else if (signatureCheck == SignatureCheckResult.SignatureBroken)
{
   Console.WriteLine("Signature of the message is either broken or forged");
}
else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching)
{
   Console.WriteLine("The provided public key doesn't match the signature");
}
else if (signatureCheck == SignatureCheckResult.NoSignatureFound)
{
   Console.WriteLine("This message is not digitally signed");
}

Backward compatibility

Having in mind that many organization have already build a solid code base around the old style of the methods, we relied on the operator overloading provided by the .NET Framework in order to provide backward compatibility. This way all the old code (except clear text signatures) will work fine with all new versions of the library. The following two lines will both compile :

DidiSoft.Pgp.PGPLib pgp = new DidiSoft.Pgp.PGPLib();
// check signature - old way
bool validSignature = pgp.Verify... 
// check signature - new way
DidiSoft.Pgp.SignatureCheckResult signatureCheck = pgp.Verify...

Clear text signatures

Unfortunately in the way that clear text signatures were verified in versions prior 1.7.12, there was an inconsistency when the provided public key doesn’t match the signature. In that case DidiSoft.Pgp.Exceptions.WrongPublicKeyException was thrown. As of version 1.7.12 there will be no exception and the resutt value will be DidiSoft.Pgp.SignatureCheckResult.PublicKeyNotMatching.

In order to migrate your code base for clear text signatures verification, you have to move the code inside the catch clause for DidiSoft.Pgp.Exceptions.WrongPublicKeyException into the check for DidiSoft.Pgp.SignatureCheckResult.PublicKeyNotMatching:

Old code for clear text signatures verification:

DidiSoft.Pgp.PGPLib pgp = new DidiSoft.Pgp.PGPLib();
// check a clear text signature
try {
  bool validClearTextSignature = pgp.Verify... 
} catch (DidiSoft.Pgp.Exceptions.WrongPublicKeyException) {
 // do something when the public key is not for this signature
}

New code for clear text signature verification

DidiSoft.Pgp.PGPLib pgp = new DidiSoft.Pgp.PGPLib();
// check a clear text signature
SignatureCheckResult signatureCheck = pgp.Verify... 
 
if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching)
{
 // do something when the public key is not for this signature
}

What if we don’t migrate our code for clear text signatures? In that case when you provide a public key from different recipient for clear text signature checking, your code will continue in the place where you handle the vague false result.