OpenPGP in Windows 8 WinRT

DidiSoft OpenPGP Library for .NET  provides DLL files for use in Windows 8 Metro style applications. In this chapter we are going to explain the differences in working with OpenPGP files provided by the library in the WinRT environment.

1. Setup
2. Working with files
3. Exception handling
4. File access settings for your application
5. Encrypting
6. Decrypting
7. Signing
8. Verifying
9. JavaScript/Html5 applications
A. Summary

1. Setup

In order to use the library for Windows 8 WinRT development, we must reference the located under the Bin\WinRT subfolder (in the library installation folder)

1. \Bin\WinRT\DidiSoft.Pgp.dll (differs from the one located in \Bin\DidiSoft.Pgp.dll)
2. \Bin\WinRT\BouncyCastle.WinRT.dll
3. \Bin\WinRT\DidiSoft.Pgp.WinRT.winmd (provides async methods that accept StorageFile in a namespace DidiSoft.Pgp.WinRT)
Back to Top

2. Working with files

If you have already started your first WinRT .NET application you may wonder where are the file access methods in the DidiSoft.Pgp.PGPLib class.

WinRT provides different file access paradigm and for this reason we have added an additional namespace DidiSoft.Pgp.WinRT exposed from the DidiSoft.Pgp.WinRT.winmd file located under the Bin\WinRT subfolder located in the library installation folder. There you can find asynchronous file access methods for Windows 8 WinRT that can be used from Metro style .NET and JavaScript/Html5 applications.

C# example

using DidiSoft.Pgp.WinRT;
...
var pgp = new PGPLibRT;

VB.NET example

Imports DidiSoft.Pgp.WinRT
...
Dim pgp As New PGPLibRT

Back to Top

3. Exception handling

The exception handling paradigm provided in WinRT differs from the traditional .NET exception handling where we could catch various exception classes. In WinRT we can rely only on the Exception.HResult as shown below:

var pgp = new PGPLibRT;
...
try
{
  await pgp.EncryptFileAsync(dataFile, keyFile, outFile);
}
catch (Exception ex)
{  
  txtDisplay.Text += ex.Message;
  PGPErrorStatus status = PGPError.GetStatus(ex.HResult);
  switch (status)
  {
    case PGPErrorStatus.WrongPublicKey:
      txtDisplay.Text += "The selected public key file does not contain a valid OpenPGP public key";
      break;
    default:
      break;
  }
}

All known exception cases recognized by the library are listed in the enumeration PGPErrorStatus. They correspond to the exceptions used in the traditional .NET development.

Back to Top

4. File access settings for your application

If your WinRT application will access files only through file pickers then you don’t have to define any additional file access settings (because it is assumed that the user knows what she’s doing).

On the other hand if you plan to access files directly from the code (for example invoking KnownFolders.DocumentsLibrary.CreateFileAsync) then you will have to define the appropriate file access permissions in the Package.appxmanifest file.
Back to Top

5. Encrypting

The example below demonstrates OpenPGP file encrypting in WinRT.

C# example

using System;
using System.Threading.Tasks;
using Windows.Storage;
using DidiSoft.Pgp.WinRT;
 
public class Demo
{
 public async void EncryptDemo()
 {
    // Data file to be encrypted
    StorageFile dataFile = await KnownFolders.DocumentsLibrary.GetFileAsync("afile.txt");
    // Usually the public key of the recipient
    StorageFile publicKeyFile = await KnownFolders.DocumentsLibrary.GetFileAsync("public_key.asc");
 
    StorageFile encryptedFile = 
	   await KnownFolders.DocumentsLibrary.CreateFileAsync("output.pgp", 
	                                                       CreationCollisionOption.ReplaceExisting);
 
    // Create an instance of the library
    PGPLibRT pgp = new PGPLibRT();
    // should the output be in binary (false) or ASCII armoured format (true)
    bool asciiArmour = true;
    await pgp.EncryptFileAsync(dataFile, publicKeyFile, encryptedFile, asciiArmour);
 }
}

VB.NET example

Imports System
Imports System.Threading.Tasks
Imports Windows.Storage
Imports DidiSoft.Pgp.WinRT
 
Public Class Demo
  Public Async Sub EncryptDemo()
   ' Data file to be encrypted
   Dim dataFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("afile.txt")
   ' Usually the public key of the recipient
   Dim publicKeyFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("public_key.asc")
 
   Dim encryptedFile As StorageFile = _
	    Await KnownFolders.DocumentsLibrary.CreateFileAsync("output.pgp", _
	                                                        CreationCollisionOption.ReplaceExisting)
 
   // Create an instance of the library
   Dim pgp As New PGPLibRT()
   ' should the output be in binary (false) or ASCII armoured format (true)
   Dim asciiArmour As Boolean = True
   Await pgp.EncryptFileAsync(dataFile, publicKeyFile, encryptedFile, asciiArmour)
  End Sub
End Class

Back to Top

6. Decrypting

The sample code below shows how to decrypt an OpenPGP encrypted file in WinRT.
C# example

using System;
using System.Threading.Tasks;
using Windows.Storage;
using DidiSoft.Pgp.WinRT;
 
public class Demo
{
 public async void DecryptDemo()
 {
     // File to be decrypted 
     StorageFile encryptedFile = await KnownFolders.DocumentsLibrary.GetFileAsync("encrypted.pgp");
     // Usually our private key
     StorageFile privateKeyFile = await KnownFolders.DocumentsLibrary.GetFileAsync("my_private_key.asc");
     // File where the decrypted data will be stored
     StorageFile decryptedFile = 
       await KnownFolders.DocumentsLibrary.CreateFileAsync("output.txt", 
                                                           CreationCollisionOption.ReplaceExisting);
 
     // Create an instance of the library
     PGPLibRT pgp = new PGPLibRT();
     // Password for the private key
     string privateKeyPassword = "my password";
     await pgp.DecryptFileAsync(encryptedFile, privateKeyFile, privateKeyPassword, decryptedFile);
 }
}

VB.NET example

Imports System
Imports System.Threading.Tasks
Imports Windows.Storage
Imports DidiSoft.Pgp.WinRT
 
Public Class Demo
  Public Async Sub DecryptDemo()
    ' File to be decrypted 
    Dim encryptedFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("output.pgp")
    ' Usually our private key
    Dim privateKeyFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("my_private_key.asc")
    ' File where the decrypted data will be stored
    Dim decryptedFile As StorageFile = _
	  Await KnownFolders.DocumentsLibrary.CreateFileAsync("output.txt", _
		                                                      CreationCollisionOption.ReplaceExisting)
 
    ' Create an instance of the library
    Dim pgp As New PGPLibRT()
    ' Password for the private key
    Dim privateKeyPassword As String = "my password"
    Await pgp.DecryptFileAsync(encryptedFile, privateKeyFile, privateKeyPassword, decryptedFile)
  End Sub
End Class

Back to Top

7. Signing

This example code demonstrates OpenPGP signing in Windows 8 WinRT environment.

C# example

using System;
using System.Threading.Tasks;
using Windows.Storage;
using DidiSoft.Pgp.WinRT;
 
public class Demo
{
 public async void SignDemo()
 {
  StorageFile dataFile = await KnownFolders.DocumentsLibrary.GetFileAsync("afile.txt");
  // Usually our private key
  StorageFile privateKeyFile = await KnownFolders.DocumentsLibrary.GetFileAsync("my_private_key.asc"); 
 
  StorageFile signedFile = 
    await KnownFolders.DocumentsLibrary.CreateFileAsync("output.pgp", 
                                                      CreationCollisionOption.ReplaceExisting);
 
  // Create an instance of the library
  PGPLibRT pgp = new PGPLibRT();
  // Password for the private key
  string privateKeyPassword = "my password";
  // should the output be in binary (false) or ASCII armoured format (true)
  bool asciiArmour = true;
  await pgp.SignFileAsync(dataFile, privateKeyFile, privateKeyPassword, signedFile, asciiArmour);
 }
}

VB.NET example

Imports System
Imports System.Threading.Tasks
Imports Windows.Storage
Imports DidiSoft.Pgp.WinRT
 
Public Class Demo
 Public Async Sub SignDemo()
  Dim dataFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("afile.txt")
  ' Usually our private key
  Dim privateKeyFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("my_private_key.asc")
 
  Dim signedFile As StorageFile = _
    Await KnownFolders.DocumentsLibrary.CreateFileAsync("output.pgp", _
							CreationCollisionOption.ReplaceExisting)
 
  ' Create an instance of the library
  Dim pgp As New PGPLibRT()
  ' Password for the private key
  Dim privateKeyPassword As String = "my password"
  ' should the output be in binary (false) or ASCII armoured format (true)
  Dim asciiArmour As Boolean = True
  Await pgp.SignFileAsync(dataFile, privateKeyFile, privateKeyPassword, signedFile, asciiArmour)
 End Sub
End Class

Back to Top

8. Verifying

This sample code illustrates verifying a signed only OpenPGP message in WinRT.

C# example

using System;
using System.Threading.Tasks;
using Windows.Storage;
using DidiSoft.Pgp.WinRT;
 
public class Demo
{
 public async void VerifyDemo()
 { 
  StorageFile signedFile = await KnownFolders.DocumentsLibrary.GetFileAsync("signed.pgp");
  // Usually the public key of the sender
  StorageFile publicKeyFile = await KnownFolders.DocumentsLibrary.GetFileAsync("public_key.asc");            
 
  StorageFile outputFile = 
    await KnownFolders.DocumentsLibrary.CreateFileAsync("output.txt", 
                                                      CreationCollisionOption.ReplaceExisting);
 
  // Create an instance of the library
  PGPLibRT pgp = new PGPLibRT();
  bool signatureIsValid = await pgp.VerifyFileAsync(signedFile, publicKeyFile, outputFile);
 }
}

VB.NET example

Imports System
Imports System.Threading.Tasks
Imports Windows.Storage
Imports DidiSoft.Pgp.WinRT
 
Public Class Demo
 Public Async Sub VerifyDemo()
  Dim signedFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("signed.pgp")
  ' Usually the public key of the sender
  Dim publicKeyFile As StorageFile = Await KnownFolders.DocumentsLibrary.GetFileAsync("public_key.asc")
 
  Dim outputFile As StorageFile = _
    Await KnownFolders.DocumentsLibrary.CreateFileAsync("output.txt", _
					  CreationCollisionOption.ReplaceExisting)
 
  ' Create an instance of the library
  Dim pgp As New PGPLibRT()
  Dim signatureIsValid As Boolean = Await pgp.VerifyFileAsync(signedFile, publicKeyFile, outputFile)
 End Sub

Back to Top

9. JavaScript/Html5 applications

Metro JavaScript applications can utilize only the classes exposed by the namespace DidiSoft.Pgp.WinRT. Below is an example that demonstrates OpenPGP file encrypting.

function encryptDemo() {
	var pgp = new DidiSoft.Pgp.WinRT.PGPLibRT();
 
	var inputFile;
	var keyFile;
	var outFile;
	var inputFilePromise = Windows.Storage.KnownFolders.documentsLibrary.getFileAsync("afile.txt");
	var keyFilePromise = Windows.Storage.KnownFolders.documentsLibrary.getFileAsync("public_key.asc");
	inputFilePromise.then(function (file) {
		inputFile = file;
		return keyFilePromise;
	}).then(function (file) {
		keyFile = file;
 
		return Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("output.pgp",
                                                     Windows.Storage.CreationCollisionOption.replaceExisting);
	}).then(function (file) {
		outFile = file;
 
		var encryptPromise = pgp.encryptFileAsync(inputFile, keyFile, outFile);
		encryptPromise.done(function () {
			var msg = new Windows.UI.Popups.MessageDialog("Successfully encrypted at " + outFile.path);
			msg.showAsync();
		},
		onError);
	});
}
 
function onError(error) {
	var errorMessage = "";
 
	var errorStatus = DidiSoft.Pgp.WinRT.PGPError.getStatus(error.number);
	switch (errorStatus) {
		case DidiSoft.Pgp.WinRT.PGPErrorStatus.generalPgpError: 
                   errorMessage = "General OpenPGP error"; break;
		case DidiSoft.Pgp.WinRT.PGPErrorStatus.fileIsEncrypted: 
                   errorMessage = "The provided file is encrypted, you have to use decryption method that accepts OpenPGP public key"; break;
                ...
		default: break;
	}
 
	if (errorMessage != "") {
		var msg = new Windows.UI.Popups.MessageDialog(errorMessage);
		msg.showAsync();
	} else {
		var msg = new Windows.UI.Popups.MessageDialog(error);
		msg.showAsync();
	}
}

Back to Top

Summary

In this chapter we have made a quick introduction to the DidiSoft OpenPGP Library for .NET files for WinRT development.

This chapter is still under development. If you don’t find the answer you are looking for, don’t hesitate to drop us a line.