Using Built-in UWP Data Protection for Data Encryption

DZone 's Guide to

Using Built-in UWP Data Protection for Data Encryption

If you're working with UWP, read on to learn how to implement higher levels of data security using encryption and decryption methods.

· Security Zone ·
Free Resource


UWP has an easy-to-use helper class to perform encryption tasks on data. Before you can use the DataProtectionProvider class, you have to decide on which level you want the encryption to happen. The level is derived from the protection descriptor, which derives the encryption material internally from the user-specified data. For non-enterprise apps, you can choose between four levels (passed in as the protectionDescriptorparameter with the constructor):

  • "LOCAL=user"
  • "LOCAL=machine"
  • "WEBCREDENTIALS=MyPasswordName"
  • "WEBCREDENTIALS=MyPasswordName,myweb.com"

If you want the encryption to be only for the currently logged-in user, use the first provider, for a machine-wide implementation use the second one in the list above. The providers for web credentials are intended to be used within the browser/web view. Personally, I never used them, because of this, this post will focus on local implementations.

Encrypting Data

There are two ways to encrypt data with the DataProtectionProvider. You can encrypt a string or a stream. My implementation always uses the stream implementation. This way I can encrypt the whole file if needed and simple strings with the same method. Here is the encryption Task:

public async Task<byte[]> Encrypt(byte[] data)
    var provider = new DataProtectionProvider(UseForAllUsers ? _localMachineDescriptor : _localUserDescriptor);

    var contentBuffer = CryptographicBuffer.CreateFromByteArray(data);
    var contentInputStream = new InMemoryRandomAccessStream();
    var protectedContentStream = new InMemoryRandomAccessStream();

    //storing data in the stream
    IOutputStream outputStream = contentInputStream.GetOutputStreamAt(0);
    var dataWriter = new DataWriter(outputStream);
    await dataWriter.StoreAsync();
    await dataWriter.FlushAsync();

    //reopening in input mode
    IInputStream encodingInputStream = contentInputStream.GetInputStreamAt(0);

    IOutputStream protectedOutputStream = protectedContentStream.GetOutputStreamAt(0);
    await provider.ProtectStreamAsync(encodingInputStream, protectedOutputStream);
    await protectedOutputStream.FlushAsync();

    //verify that encryption happened
    var inputReader = new DataReader(contentInputStream.GetInputStreamAt(0));
    var protectedReader = new DataReader(protectedContentStream.GetInputStreamAt(0));

    await inputReader.LoadAsync((uint)contentInputStream.Size);
    await protectedReader.LoadAsync((uint)protectedContentStream.Size);

    var inputBuffer = inputReader.ReadBuffer((uint)contentInputStream.Size);
    var protectedBuffer = protectedReader.ReadBuffer((uint)protectedContentStream.Size);

    if (!CryptographicBuffer.Compare(inputBuffer, protectedBuffer))
       return protectedBuffer.ToArray();
        return null;

First, I am defining the provider based on a boolean property. The passed-in byte array is then converted to an IBuffer, which in turn makes it easier to pass it to the InMemoryRandomAccessStream that we will encrypt. After writing the data into this stream, we need to reopen the stream in input mode, which allows us to call the ProtectStreamAsync method. By comparing both streams, we are finally verifying that encryption happened.

Decrypting Data

Of course, it is very likely we want to decrypt the data we encrypted with the above method at some point. We are basically reversing the process above with the following Task:

public async Task<byte[]> Decrypt(byte[] encryptedBytes)
    var provider = new DataProtectionProvider();

    var encryptedContentBuffer = CryptographicBuffer.CreateFromByteArray(encryptedBytes);
    var contentInputStream = new InMemoryRandomAccessStream();
    var unprotectedContentStream = new InMemoryRandomAccessStream();

    IOutputStream outputStream = contentInputStream.GetOutputStreamAt(0);
    var dataWriter = new DataWriter(outputStream);
    await dataWriter.StoreAsync();
    await dataWriter.FlushAsync();

    IInputStream decodingInputStream = contentInputStream.GetInputStreamAt(0);

    IOutputStream protectedOutputStream = unprotectedContentStream.GetOutputStreamAt(0);
    await provider.UnprotectStreamAsync(decodingInputStream, protectedOutputStream);
    await protectedOutputStream.FlushAsync();

    DataReader reader2 = new DataReader(unprotectedContentStream.GetInputStreamAt(0));
    await reader2.LoadAsync((uint)unprotectedContentStream.Size);
    IBuffer unprotectedBuffer = reader2.ReadBuffer((uint)unprotectedContentStream.Size);

    return unprotectedBuffer.ToArray();

For decryption, we do not need to specify the protection descriptor again. The OS will find the right one on its own. While I have read that this sometimes makes problems, I haven't got any problems until now. Once again, we are creating InMemoryRandomAccessStreaminstances to perform decryption on it. Finally, after we unprotected our data with the UnProtectStreamAsync method, we are reading the data back into a byte array.


The use of these two helpers is once again pretty straightforward. Let's have a look at data encryption:

var textToCrypt = "this is just a plain test text that will be encrypted and decrypted";

//async method
var encrypted = await Encrypt(Encoding.UTF8.GetBytes(textToCrypt));
//non async method:
//var encrypted = Encrypt(Encoding.UTF8.GetBytes(textToCrypt)).GetAwaiter().GetResult();

Decryption of encoded data is done like this:

//async method
var decrypted = await Decrypt(encrypted);

//non async method
//var decrypted = Decrypt(encrypted).GetAwaiter().GetResult();

//getting back the string:
var decryptedString = Encoding.UTF8.GetString(decrypted);


Using the built-in DataProtectionAPI makes it very easy to protect sensitive data within a UWP app. You can use it on both a string or a stream, it is up to you whether you follow my way of always using a stream or making it dependent on your scenario. If you want to have more control over the key size, the encryption method used or any other detail, I wrote a post about doing everything on my own a while back (find it here). Even if it is from 2015 and based on WINRT (Win8.1), the APIs are still alive and the post should help you to get started.

You can have a look on Android encryption here, while you'll find the iOS post here.

As always, I hope this post will be helpful for some of you. If you have any questions/feedback, feel free to comment below or connect with me via my social networks.

Happy coding, everyone!

data protection, data security, encryption, security, uwp

Published at DZone with permission of Marco Siccardi , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}