Additional decryption key (ADK) is a feature outside of the OpenPGP Standard. It allows public keys to hold internal information for other public keys noted as additional decryption keys (ADK for short).
The idea in short is : if Alice’s key has Bob’s key as an ADK, then when we encrypt with Alice’s key, the OpenPGP software should automatically also encrypt with Bob’s key, this way the message will be encrypted for multiple recipients and Bob can also decrypt it with his own private key.
ADK support is turned On by default as of version 1.7.11.
It is utilized only when we use the KeyStore key storage.
Table of Contents
1. Register and unregister an ADK key
1.1 registering
1.2 unregistering
2. Listing ADK keys
3. Encrypting
4. What if ADK keys are missing?
5. How to turn ADK support Off?
1. Register and unregister an ADK key
1.1 Registering ADK keys
Assuming that we have a KeyStore containing the main public key of ACM Company. We will produce a key pair for the employee John Doe and we will also register the company public key as an ADK (additional decryption key) for his key. Then his public key will be sent to the other employees of the ACM company, this way having each message encrypted for John, be also encrypted with the main company key.
With this feature if for some reason John leaves the company and deletes his keys or looses his password, the data encrypted for him can still be read and decrypted with the main company private key.
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; using DidiSoft.Pgp; public class RegisterADK { public static void Demo() { // new in-memory key storage KeyStore ks = new KeyStore(); // Import the main company public key KeyPairInformation mainCompanyKey = ks.ImportPublicKey("acmcompany_pub.asc"); // Create John's key string newKeyPassword = "test password"; ks.GenerateRsaKeyPair(1024, "John Doe <john.doe@acmcompany.com>", newKeyPassword); // Register the main company key as an ADK for John's key ks.AddAdkKey("John Doe", newKeyPassword, mainCompanyKey.UserId); // Now we can call ks.ExportPublicKey and distribute John's public key to the other employees } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Imports System Imports DidiSoft.Pgp Public Class RegisterADK Public Shared Sub Demo() ' new in-memory key storage Dim ks As New KeyStore() ' Import the main company public key Dim mainCompanyKey As KeyPairInformation = ks.ImportPublicKey("acmcompany_pub.asc") ' Create John's key Dim newKeyPassword As String = "test password" ks.GenerateRsaKeyPair(1024, "John Doe <john.doe@acmcompany.com>", newKeyPassword) ' Register the main company key as an ADK for John's key ks.AddAdkKey("John Doe", newKeyPassword, mainCompanyKey.UserId) ' Now we can call ks.ExportPublicKey and distribute John's public key to the other employees End Sub End Class |
1.1 Unregistering ADK keys
In order to modify the ADK list of an OpenPGP key, its private key must also reside in the same KeyStore. In the sample below the first key from the registered ADK keys will be unregistered:
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; using DidiSoft.Pgp; public class UnregisterADK { public static void Demo() { KeyStore ks = new KeyStore(); // Import the key pair of John Doe KeyPairInformation key = ks.ImportPublicKey("john_doe_pub.asc"); // In order to change the ADK list we need also the private key ks.ImportPrivateKey("john_doe_priv.asc"); // Remove the first ADK key from John's key string keyPassword = "test password"; if (key.GetAdkKeysCount() > 0) ks.DeleteAdkKey(key.KeyId, keyPassword, 0); else Console.WriteLine("There are no ADK key's in this key"); } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Imports System Imports DidiSoft.Pgp Public Class UnregisterADK Public Shared Sub Demo() Dim ks As New KeyStore() ' Import the key pair of John Doe Dim key As KeyPairInformation = ks.ImportPublicKey("john_doe_pub.asc") ' In order to change the ADK list we need also the private key ks.ImportPrivateKey("john_doe_priv.asc") ' Remove the first ADK key from John's key Dim keyPassword As String = "test password" If key.GetAdkKeysCount() > 0 Then ks.DeleteAdkKey(key.KeyId, keyPassword, 0) Else Console.WriteLine("There are no ADK key's in this key") End If End Sub End Class |
2. Listing ADK keys
An OpenPGP key with registered ADK keys contains internally only their fingerprints. The ADK keys that are in the same KeyStore, can be observed through the method KeyStore.GetKnownAdkKeys. For the ADK keys that are missing in the KeyStore, we can get only their fingerprints. This example demonstrates this:
C# example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using DidiSoft.Pgp; public class ListADKKeys { public static void Demo() { KeyStore ks = new KeyStore(); // Import John's key KeyPairInformation key = ks.ImportPublicKey("john_doe_pub.asc"); // known (in this KeyStore) ADK keys KeyPairInformation[] knownAdkKeys = ks.GetKnownAdkKeys(key.KeyIdHex); for (int i = 0; i < knownAdkKeys.Length; i++) { KeyPairInformation adkKey = knownAdkKeys[i]; Console.WriteLine(String.Format("ADK key {0} User ID is : {1}; Fingerprint: {2}", i, adkKey.UserId, adkKey.Fingerprint)); } // all ADK keys' fingerprints for (int i = 0; i < key.GetAdkKeysCount(); i++) { Console.WriteLine(String.Format("ADK key {0} Fingerprint is: {1}", i, key.GetAdkKeyFingerprint(i))); } } } |
VB.NET example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Imports System Imports DidiSoft.Pgp Public Class ListADKKeys Public Shared Sub Demo() Dim ks As New KeyStore() ' Import John's key Dim key As KeyPairInformation = ks.ImportPublicKey("john_doe_pub.asc") ' List known (in this KeyStore) ADK keys Dim knownAdkKeys As KeyPairInformation() = ks.GetKnownAdkKeys(key.KeyIdHex) For i As Integer = 0 To knownAdkKeys.Length - 1 Dim adkKey As KeyPairInformation = knownAdkKeys(i) Console.WriteLine([String].Format("ADK key {0} User ID is : {1}; Fingerprint: {2}", _ i, adkKey.UserId, adkKey.Fingerprint)) Next ' all ADK keys' fingerprints For i As Integer = 0 To key.GetAdkKeysCount() - 1 Console.WriteLine([String].Format("ADK key {0} Fingerprint is: {1}", i, key.GetAdkKeyFingerprint(i))) Next End Sub End Class |
3. Encrypting
When we encrypt using a public key with registered ADK keys, by default the message gets also automatically encrypted with the ADK keys listed in this public key and presented in the same KeyStore. This applies to the operations OpenPGP encrypring and one pass signing and encrypting.
4. What if ADK keys are missing?
The ADK keys that are missing in a KeyStore, are not used in the encryption process and are silently skipped.
5. How to turn ADK support Off?
In order to skip the silent additional encryption with ADK keys, a special setting exists in the PGPLib class, that has to be set to False:
C# example
PGPLib pgp = new PGPLib(); pgp.UseADKs = false; |
VB.NET example
Dim pgp As New PGPLib() pgp.UseADKs = False |
Summary
This chapter presented the support for ADK (additional decryption keys) offered by DidiSoft OpenPGP Library for .NET as of version 1.7.11.
ADK provides the ability to silently encrypt for multiple recipients by explicitly providing only one recipient. This can be useful in enterprises where a message must also be accessible by other employees, other than the original recipient.