Blazor server app with PGP encryption

Recently we were asking ourselves will OpenPGP Library for .NET work in a Blazor application.

As you probably know there are two types of Blazor applications, server and WASM (web assembly). In this article, we will demonstrate the usage of the library in a server application. For WASM a few words will be said at the end of this page.

Getting started

First, let’s create a starter Blazor app:

dotnet new blazorserver -o BlazorPgpDemo

Adding reference for PGP

In order to use DidiSoft.Pgp.dll we need to add a reference for it. We can do that with NuGet:

PM>Install-Package DidiSoft.Pgp.Trial

or if we already have access to the production version of the library:

PM>Install-Package DidiSoft.Pgp.Trial

Register PGPLib as a service

In order to use PGPLib (the main class of DidiSoft OpenPGP Library for .NET providing PGP cryptography functionality) in Blazor pages, we need to make it available as a service in Startup.cs

1. In the Startup.cs file in your Blazor application, append in the usage clauses:

using DidiSoft.Pgp;

2. Then scroll below to the method ConfigureServices and append at the end:

public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddSingleton<PGPLib>();// Append here
}

Encrypt an uploaded file

Now when we have PGPLib registered as a service class, we can use it on a Blazor page by injecting it:

@inject PGPLib pgp

Let’s add an InputFile element into our page and a button that will encrypt it:

<InputFile OnChange="OnInputFileChange" />
<button class="btn btn-primary" disabled="disabled">Encrypt file</button>
Encrypted File in ASCII armored format: @encryptedFileAsciiArmored

And here goes the code that handles the file upload and the encryption

static String inlinePublicKey = "-----BEGIN PGP PUBLIC KEY BLOCK-----" + Environment.NewLine +
 "Version: 2.6.3ia" + Environment.NewLine +
 Environment.NewLine +
 "mQBNA1MFDdUAAAECAKu8k6fMN3O/C1VS7JwBFebXCUQLKeedZ9gQ6uRGTmcw2J8k" + Environment.NewLine +
 "N1SqzYpSbEl4U+iOOBfE84IzRLLf3AatXXcDZF0ABRG0BHBncDKJAFUDBRBTBQ3V" + Environment.NewLine +
 "3AatXXcDZF0BAXGMAf0f9beO+xIpFOIt5derM3DyB/MJdmRHYeM77+v3QH/u91XI" + Environment.NewLine +
 "sglY26p0pShNVIIgWv8zdNYetXnWMYxAdaGgej51" + Environment.NewLine +
 "=ro8q" + Environment.NewLine +
 "-----END PGP PUBLIC KEY BLOCK-----" + Environment.NewLine;
 
private BrowserFile file;
private string encryptedFileAsciiArmored;
 
async Task OnInputFileChange(InputFileChangeEventArgs e)
{
 using (var stream = new MemoryStream())
 {
   await e.File.OpenReadStream().CopyToAsync(stream);
   stream.Seek(0, SeekOrigin.Begin);
   file = new BrowserFile() { Content = stream.ToArray(), Name = e.File.Name, Size = e.File.Size };
 }
}
 
private void EncryptFile()
{
 if (file != null)
 {
  using (var outStream = new MemoryStream())
  using (var inStream = new MemoryStream(file.Content))
  using (var pkStream = new MemoryStream(Encoding.UTF8.GetBytes(inlinePublicKey)))
  {
    pgp.EncryptStream(inStream, pkStream, privateKeyPassword, outStream, true);
    outStream.Seek(0, SeekOrigin.Begin);
 
    var reader = new System.IO.StreamReader(outStream);
    encryptedFileAsciiArmored = reader.ReadToEnd();
   }
 }
}
 
public class BrowserFile
{
 public byte[] Content { get; set; }
 public string Name { get; set; }
 public long Size { get; set; }
}

The code above stores the uploaded file in a variable of a custom type BrowserFile and then when the “Encrypt File” button is clicked it invokes the EncryptStream method from the PGPLib class and prints it into ASCII armored format.

Summary

The purpose of this sample is to illustrate how to use PGP encryption in a Blazor server application. You can start from here and incorporate any of the available PGP cryptography operations

PGP in Blazor WASM

We have tried to implement DidiSoft.Pgp.dll in a Blazor WASM application but unfortunately, the current execution speed of the Web Assembly bytecode is very slow and a simple encryption operation takes an enormous amount of time, which is far ahead of a practical approach nowadays when the main purpose of Blazor is speed performance in the user interface similar to the one we know from React.