# Multiple XML files and known-plaintext attack

I have created an app which collects data in sets which may contain up to 20000 XML files of an average size of about 5 KB, and all with the same header and XML structure, so that only the data they contain differ.

For certain reasons I've decided to encrypt these XML files so that the data they contain cannot be exported without my consent. Problem is that the current users of the app already have a lot of unencrypted XML files and after these have been encrypted (they're required to be in order to use future versions of the app) they may still have backups of the unencrypted XML files, which I can't do anything about.

But that also means that they have the means for doing a known plain-text attack, in order to extract the key and thereby have access to also export the content of encrypted XML files added in the future. So I want to ensure that they're encrypted in a way that makes this if not impossible then at least very difficult.

As I understand from reading posts here, AES should be safe against known-plaintext attacks in a case like this, if it's correctly implemented. So I'm trying to encrypt the files using AES. I just want to be sure if I'm doing it correct, and hope someone here can tell me.

I'm using the code listed here:

Simple AES byte encryption and decryption routines in C#

and a 64 byte key with a 32 byte salt/IV. Same key and salt for each file. I've set iterations to 4096 as a higher number will slow things down too much.

I can create a unique key or salt/IV for each file as there is a unique ID connected with each XML file but it will complicate things a lot and in rare cases the ID for a file may change (beyond my control), so I want to avoid it if possible.

You can just use a fully random AES key of 128/192/256 bits. There is no need for PBKDF2 as displayed in the example. The IV should be fully random for CBC, so you would need to save it with each ciphertext. The IV of course always needs to be 128 bits (16 bytes). The code you point out is only useful if you're using a password or passphrase instead of a key.

AES-CBC is indeed secure against plaintext attacks in any secure mode. There is no particular need to worry about that. Note that CBC mode, the .NET default for block ciphers does not protect integrity / authenticity of the encrypted files (i.e. somebody can change them undetected or create a failure during unpadding).

• OK, will give that a try. Someone wanting to change the files is highly unlikely in this case as it wouldn't serve any purpose, so that shouldn't be a problem. Thanks! – Rado Dec 4 '17 at 19:15
• Beware! There are very few circumstances in which unauthenticated encryption provides meaningful security properties against a plausible adversary. If you want to do that, you should very clearly articulate the limited scope of the threat model you are considering, why that limited scope is relevant in your application, and what security properties you want to provide against that threat that are provided by unauthenticated encryption. – Squeamish Ossifrage Dec 4 '17 at 21:26
• Well the only concern here is if anyone can extract the key and thereby be able to decrypt the files. As I understand this will not be possible when using AES-CBC. The data is not critical as such, anyone with a copy of the app can view them, I'm just trying to prevent them from being exported without my consent. – Rado Dec 5 '17 at 23:20

First, don't use AES directly. AES itself is a pseudorandom permutation family, and if you don't understand what that means, then it's not a good fit for your application.

What you should do is use an authenticated encryption scheme (with associated data), or AE(AD) scheme for short. Popular examples are AES-GCM, NaCl crypto_secretbox_xsalsa20poly1305, and AES-SIV. Then pay attention to the security contract so that you understand what your obligations are in the application, and what security properties it affords you in exchange:

1. With AES-GCM, you are obligated (a) to choose a secret key uniformly at random, (b) to provide a unique 96-bit nonce for each message you want to encrypt, and (c) to never reuse the nonce with the same key.

The nonce must be derived from context, e.g. a message sequence number, or stored alongside the message, so that the decryption side of your protocol knows it. You must not pick the nonce at random, or you must use the key for no more than than $2^{32}$ messages. Messages must be no longer than one terabyte, $2^{40}$ bytes.

In exchange, you are guaranteed that an adversary without knowledge of the secret key learns nothing about the plaintext of each encrypted message (even if they know all but a single bit of the plaintext, the ciphertext does not inform them of that single bit) and cannot forge ciphertexts you did not already furnish. If you reuse a nonce, all is lost.

(The exact bound on the safe number of messages is squishy. A panel of crypto nerds could litigate endlessly over what the limit should be. Do you want to play games with squishy balls of crypto you don't understand, or just play it safe?)

2. With NaCl crypto_secretbox_xsalsa20poly1305, you are obligated (a) to choose a secret key uniformly at random, (b) to provide a unique 192-bit nonce for each message you want to encrypt, and (c) to never reuse the nonce with the same key.

The nonce must be derived from contxt, e.g. a message sequence number, or stored alongside the message, so that the decryption side of your protocol knows it. You may pick the nonce uniformly at random. You may encrypt up to $2^{64}$ messages each of up to $2^{72}$ bytes apiece, which is more bytes than you will ever have in your lifetime even if you never bother to chew.

In exchange, you are guaranteed that an adversary without knowledge of the secret key learns nothing about the plaintext of each encrypted message (even if they know all but a single bit of the plaintext, the ciphertext does not inform them of that single bit) and cannot forge ciphertexts you did not already furnish. If you reuse a nonce, all is lost.

3. With AES-SIV, you are obligated to choose a secret key uniformly at random. You may additionally supply a 128-bit nonce, even at random. You must not use the key for a total of more than $2^{48}$ bytes.

In exchange, you are guaranteed that an adversary without knowledge of the secret key learns nothing about the plaintext of each encrypted message (even if they know all but a single bit of the plaintext, the ciphertext does not inform them of that single bit) except that if the nonce is repeated or not supplied, the adversary will learn when a message is repeated or not. You are also guaranteed that the adversary cannot forge ciphertexts you did not already furnish.

(The limit on bytes here is also squishy. What have we learned about squishy balls of crypto?)

There are other considerations about the AES ones versus the XSalsa20/Poly1305 choice: software implementations of AES and GCM are either vulnerable to cache-timing attacks (vast majority), or unusably slow (you are not likely to encounter these); guaranteeing that you can rely on a hardware implementation of AES and guaranteeing that your software stack uses the hardware implementation of AES that is available is a nontrivial auditing task.

• Thank you. I've been looking up AES-GCM and NaCl but only been able to find solutions for C# that seem to be either very complex to implement, or very expensive. With my limited knowledge about these things I'd prefer something simple I can understand, like the code I linked to, it's probably safer in this case. – Rado Dec 4 '17 at 19:10
• First hit from a web search for C# libsodium: github.com/adamcaudill/libsodium-net I would be rather surprised if there were not an easy way to use AES-GCM in C# too; that would suggest that pretty much nobody has ever used C# seriously for applications involving cryptography, which is just about any application that uses the internet today. – Squeamish Ossifrage Dec 4 '17 at 21:03
• Maybe there is but I couldn't find anything, besides I've already got AES-CBC working and it appears to be sufficient for my purpose. I appreciate your input though, there is some good information here which may be useful in other contexts. – Rado Dec 5 '17 at 23:40
• If you're not going to take the safe route of using authenticated encryption by default, please at least write down a statement of the most powerful adversary you can conceive of attacking this system, and the security properties you hope to attain against that adversary. Then the auditors will be able to tell, separately, (a) where your imagination of adversaries was limited, and (b) whether AES-CBC actually provides the security you hope against the adversary you imagined and/or the adversary you should have imagined. – Squeamish Ossifrage Dec 6 '17 at 0:05
• Well the only concern on my part is if anyone will be capable of obtaining the key in some way. I've considered everything and in this context this is the only concern. Adversaries are software pirates in particular, but also possible competitors to my apps. NSA and other people or agencies with powerful resources have absolutely no interest in this, just common people with limited resources. – Rado Dec 7 '17 at 4:31