<img src="https://d5nxst8fruw4z.cloudfront.net/atrk.gif?account=J5kSo1IWhd105T" style="display:none" height="1" width="1" alt="">

Nexosis @ Work & Play

Nexosis @ Work & Play

Using Azure KeyVault to Manage Keys

Using Azure KeyVault to Manage Keys

Key Management has historically required specialized hardware and a significant amount of time to build an effective solution. Cloud-based Hardware Security Modules now make it more affordable and simpler. Jason discusses Key Management using Azure KeyVault below.


I've taught many classes and given several talks at conferences about application security - based on the vast material on the topic, I've never had time to delve into Key Management because it's a hard problem that historically, requires specialized hardware ($$$) and some time to work out the details on how to architect a good solution.

Typically, the guidance I'd give on Key Management was broad and vague in most areas, along the lines of:

  • Generate keys securely
  • Store keys securely
  • Perform key rotation at regular intervals
  • Protect who has access to keys
  • Audit access to keys
  • Transfer keys over secure transport
  • Have a mechanism to revoke keys
  • Oh...and back your keys up securely so you don't lose access to all of your data!

That's just Key Management...

Cloud providers such as AWS CloudHSM and Azure KeyVault now provide Cloud-based Hardware Security Modules (HSM) at a very affordable price so many of these challenges can be solved in a much easier fashion.

Here's a brief look at Azure KeyVault, and some of it's Key Management features that address some of the points above:

  • Key's are stored and safeguarded in HSMs which are validated at FIPS-140-2 Level 2
  • Keys can be generated securely or you can generate your own and upload them
  • Keys are invoked by URI when needed and transmitted securely over SSL/TLS
  • The key's are not viewable by the calling application
  • A SaaS Company can securely manage keys for protecting sensitive data OR a customer could share access to their own vault, giving them control over their keys, allowing a SaaS vendor to use the key but not see it.
  • A particular key can be versioned, allowing new versions of the keys to be generated while keeping the old key around until key rotation (decrypt / re-encrypt of old data) can be completed.
  • Auditing of key usage, revocation of keys and a flexible set of permissions around key access.
  • KeyVault can also just store and protect passwords and other 'secrets'
  • Keys can be backed up outside of KeyVault, off-site, etc - but deciding where to store these and how to protect them requires some real thought and planning. These are the most critical secrets.

Example

For a full, more complete example illustrating encryption of files, and JSON blobs, clone this project on github.

In this example, we'll use KeyVault to Wrap / Unwrap, or in more common terms, encrypt / decrypt a symmetric key. This symmetric key can then be used to encrypt data before storing it - this data could be a file on disk, data in a database, etc. Since the symmetric key is now encrypted using an asymmetric algorithm, the symmetric key can be stored along with the data you are encrypting.

This is called the envelope technique. This is analogous to taking something you want to secure and placing it in a protected envelope that only someone else can open for you, if they have permission. In this case, we'll be taking a symmetric AES key, which is great at encrypting and decrypting bulk data fast, but we need that symmetric key protected to prevent anyone from seeing or using it, so we wrap it by encrypting it with an asymmetric algorithm (even the application code itself).

The symmetric key should be short-lived and really should only be used to encrypt and then decrypt data once. Any changes to the underlying data should generate another symmetric key, re-encrypt the data and then wrap that key and store it. A unique symmetric key should be generated anytime data needs encrypted. They need not and should not be used to encrypt more then the file or selection of data required.

The following Nuget Packages will be needed to use Azure KeyVault:

PM> Install-Package Microsoft.Azure.KeyVault
PM> Install-Package Microsoft.Azure.KeyVault.Extensions
PM> Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.16.204221202

The KeyVault resource must exist in Azure, the permissions and audit levels must also be set appropriately. A key will also need generated (in this example we'll need an RSA key). Additionally an Application Principal must be created in Azure AD that grants the Wrap / Unwrap permission on that specific Key Vault Resource.

Once the App Principal Exists - the Application ID (client ID) and a Key is required to get a reference to that resource:

KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(Utils.GetToken);

GetToken uses the Application Principal created in Azure to retrieve a JTW Token containing the permissions needed to connect to the KeyVault.

// Retrive JWT token to be used for KeyVault access.
internal async static Task GetToken(string authority, string resource, string scope)
{
    var authContext = new AuthenticationContext(authority);
	// TODO: Look into using .pfx instead
    ClientCredential clientCred = new ClientCredential(
        ConfigurationManager.AppSettings["clientId"],
        ConfigurationManager.AppSettings["clientSecret"]
    );
    AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);

    if (result == null)
        throw new InvalidOperationException("Failed to obtain the JWT token.");

    return result.AccessToken;
}
    

This KeyVaultKeyResolver can then be used to retrieve use of the key encrypting key to encrypt and decrypt the AES Symmetric Key, using the Key Id (which is a URI pointing to a unique key in the Key Vault).

To Wrap the key:


// Resolve an IKey by Key ID
var keyEncryptionKey = cloudResolver.ResolveKeyAsync(keyId, CancellationToken.None).GetAwaiter().GetResult();

// Take our gen'ed AES Key and wrap (encrypt) it.
Tuple<byte[], string> wrappedKey = keyEncryptionKey.WrapKeyAsync(aeskey, null /* algorithm */, CancellationToken.None).GetAwaiter().GetResult();

The byte[] in the Tuple contains the encrypted bytes of the symmetric key and the name of the algorithm used.

To Unwrap (decrypt) the key:


// Retrieve the IKey by Key ID
var rsa = cloudResolver.ResolveKeyAsync(keyId, CancellationToken.None).GetAwaiter().GetResult();

// Unwrap Key
byte[] aesKey = rsa.UnwrapKeyAsync(wrappedKeyBytes, algoName, CancellationToken.None).GetAwaiter().GetResult();
}

Conclusion

Cloud HSM's such as AWS CloudHSM and Azure KeyVault have made key management more accessible and inexpensive to developers everywhere. If used properly they can help solve one of the more challenging aspects of cryptography - Key Management.

For all the details, a more complete sample can be found in the Nexosis github repo - clone this project on github.


Ready to start building machine learning applications?

Get your free API key  Talk to an expert


Jason Montgomery

Jason is the CTO and co-founder of Nexosis. He oversees and participates in engineering, devops, security, data science/machine learning, product, and technical direction. Some claim that he derives his power for good from his mighty beard.

 May 25, 2017 @ 1:50 PM |   Technical