When we receive signed only OpenPGP file from our partners we can decrypt it with a random private key, ignoring this way the digital signature or we can verify and extract the data.
The examples below show how to verify the digital signature and extract the data in one pass with OpenPGP Library for Java. In order to pass the signature verification we must use the public key of the sender.
Note: As of version 3.1 of the library new methods are used for signature verification. They return an enumeration of type com.didisoft.pgp.SignatureCheckResult with possible signature verification results. If you need examples for the old methods, please check here.
Verify a signed file
1. with sender’s public key located in a file on the disk.
2. with sender’s public key located in a KeyStore.
Verify a signed Stream
3. with sender’s public key located in a file on the disk.
4. with sender’s public key located in a KeyStore.
Appendix A
Exception Handling
1. Verify a signed file with sender’s public key located in file on the disk.
This example assumes that the file signed.pgp was only signed with the private key of the sender. Note that this is different from sign and encrypt in one pass.
import com.didisoft.pgp.*; public class VerifyFile { public static void main(String[] args) throws Exception{ // create an instance of the library PGPLib pgp = new PGPLib(); // verify and extract the signed content SignatureCheckResult signatureCheck = pgp.verifyAndExtract("signed.pgp", "sender_public_key.asc", "OUTPUT.txt"); if (signatureCheck == SignatureCheckResult.SignatureVerified) { System.out.println("The signature is valid."); } else if (signatureCheck == SignatureCheckResult.SignatureBroken) { System.out.println("Message corrupted or signature forged"); } else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching) { System.out.println("Signature not matching provided public key (the message is from another sender)"); } else { System.out.println("No signature found in message"); } } } |
2. Verify signed file with sender public key located in a KeyStore.
In this example the digital signature in the signed file we have received is tried to be verified with the public keys we have imported previously in our KeyStore file. If the public key of the sender is not present in this KeyStore the verification will fail, but anyway the embedded file will be extracted.
import com.didisoft.pgp.*; public class VerifyFile { public static void main(String[] args) throws Exception{ // create an instance of the library PGPLib pgp = new PGPLib(); // initialize the KeyStore KeyStore keyStore = new KeyStore("mykeys.keystore", "my password"); // verify and extract the signed content SignatureCheckResult signatureCheck = pgp.verifyAndExtract("signed.pgp", keyStore, "OUTPUT.txt"); if (signatureCheck == SignatureCheckResult.SignatureVerified) { System.out.println("The signature is valid."); } else if (signatureCheck == SignatureCheckResult.SignatureBroken) { System.out.println("Message corrupted or signature forged"); } else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching) { System.out.println("Signature not matching provided public key (the message is from another sender)"); } else { System.out.println("No signature found in message"); } } } |
3. Verify signed stream data with sender’s public key located in a file on the disk.
In the example below the signed data is supplied as a file stream but it can be any kind of input stream.
import java.io.*; import com.didisoft.pgp.*; public class VerifyAndExtractStreamDemo { public static void main(String[] args) throws Exception{ // create an instance of the library PGPLib pgp = new PGPLib(); InputStream dataStream = new FileInputStream("signed.pgp"); InputStream keyStream = new FileInputStream("sender_public_key.asc"); OutputStream outputStream = new FileOutputStream("OUTPUT.txt"); try { // verify and extract the signed content SignatureCheckResult signatureCheck = pgp.verifyAndExtract(dataStream, keyStream, outputStream); if (signatureCheck == SignatureCheckResult.SignatureVerified) { System.out.println("The signature is valid."); } else if (signatureCheck == SignatureCheckResult.SignatureBroken) { System.out.println("Message corrupted or signature forged"); } else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching) { System.out.println("Signature not matching provided public key /it is from another sender/"); } else { System.out.println("No signature found in message"); } } finally { dataStream.close(); keyStream.close(); outputStream.close(); } } } |
4. Verify signed stream data with sender’s public key located in a KeyStore.
The example below checks a signed only stream data against the public keys located in a KeyStore file. Even if none of the public keys can decode the OpenPGP digital signature packet the content of the signed input stream is extracted into a destination decrypted output stream.
import java.io.*; import com.didisoft.pgp.*; public class VerifyAndExtractStreamDemo { public static void main(String[] args) throws Exception{ // create an instance of the library PGPLib pgp = new PGPLib(); InputStream dataStream = new FileInputStream("signed.pgp"); // initialize the KeyStore KeyStore keyStore = new KeyStore("mykeys.keystore", "password"); OutputStream outputStream = new FileOutputStream("OUTPUT.txt"); try { // verify and extract the signed content SignatureCheckResult signatureCheck = pgp.verifyAndExtract(dataStream, keyStore, outputStream); if (signatureCheck == SignatureCheckResult.SignatureVerified) { System.out.println("The signature is valid."); } else if (signatureCheck == SignatureCheckResult.SignatureBroken) { System.out.println("Message corrupted or signature forged"); } else if (signatureCheck == SignatureCheckResult.PublicKeyNotMatching) { System.out.println("Signature not matching provided public key /it is from another sender/"); } else { System.out.println("No signature found in message"); } } finally { dataStream.close(); outputStream.close(); } } } |
Exception Handling
When verifying a signed OpenPGP data we can simply catch java.io.IOException and com.didisoft.pgp.PGPException.
We can also catch a number of PGPException sub classes located in the com.didisoft.pgp.exceptions package. They must be caught before PGPException.
Below is an example code snippet that shows this extended error handling:
import java.io.IOException; import com.didisoft.pgp.*; import com.didisoft.pgp.exceptions.*; public class ExceptionHandlingDemo { public static void main(String[] a) { PGPLib pgp = new PGPLib(); try { pgp.verify... } catch (IOException e) { // error reading input or writing output } catch (NonPGPDataException e) { // the passed encrypted input is not a valid OpenPGP archive } catch (NoPublicKeyFoundException e) { // if the passed public key file does not contain a public key or is corrupted } catch (FileIsEncryptedException e) { // if the passed input is OpenPGP encrypted, it should either be extracted with // decrypt method call or decrypted and verified in one pass // with decryptAndVerify method call } catch (DetachedSignatureException e) { // the input is not an encrypted message, but a detached OpenPGP signature } catch (PGPException e) { // general decryption error not among the above ones } } } |
Summary
In this chapter we have discussed OpenPGP signed data digital signature verification with DidiSoft OpenPGP Library for Java.