3

I'm reading up on the ProtectedMemory class in C# (which uses the Data Protection API in Windows (DPAPI)) and I see that in order to use the Protect() Method of the class, the data to be encrypted must be stored in a byte array whose size/length is a multiple of 16.

I know how to convert many different data types to byte array form and back again, but how can I guarantee that the size of a byte array is a multiple of 16? Do I literally need to create an array whose size is a multiple of 16 and keep track of the original data's length using another variable or am I missing something? With traditional block-ciphers all of these details are handled for you automatically with padding settings. Likewise, when I attempt to convert data back to its original form from a byte array, how do I ensure that any additional bytes are ignored, assuming of course that the original data wasn't a multiple of 16.

In the code sample provided in the .NET Framework documentation, the byte array utilised just so happens to be 16 bytes long so I'm not sure what best practice is in relation to this hence the question.

slickboy
  • 451
  • 2
  • 8
  • 24
  • 2
    [Find the next multiple](https://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number) of 16 >= the length of your data + 4, create a byte array that size, copy the 4 bytes of an int32 holding your data length to the start of the array then copy your data. To decode copy the 1st 4 bytes to an int32 and read that many bytes from index 4. – Alex K. Nov 06 '20 at 13:44
  • 2
    Yes, you have to create an array that's a multiple of 16. To recover the correct length you could just use [PKCS7 padding](https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS#5_and_PKCS#7) which is very simple to handle. – President James K. Polk Nov 06 '20 at 13:52

1 Answers1

0

Yes, just to iterate over the possibilities given in the comments (and give an answer to this nice question), you can use:

  1. a padding method that is also used for block cipher modes, see all the options on the Wikipedia page on the subject.
  2. prefix a length in some form or other. A fixed size of 32 bits / 4 bytes is probably easiest. Do write down the type of encoding for the size (unsigned, little endian is probably best for C#).

Both of these already operate on bytes, so you may need to define a character encoding such as UTF-8 if you use a string.

You could also use a specific encoding of the string, e.g. one defined by ASN.1 / DER and then perform zero padding. That way you can even indicate the type of the data that has been encoded in a platform independent way. You may want to read up on masochism before taking this route.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263