We have a requirement from customer to write payment transaction information to a text file. Of many lines of data per transaction, only one line contains cardholder information, which needs encryption to be PCI-Compliant.

My thought is to encrypt only the sensitive line and write to the text file while writing the rest unencrypted -- I believe this avoids encryption and decryption overhead when dealt with a large number of transactions at a go.

(FYI, we have customized encryption and decryption tools where we are trying to encrypt the line using AES-256 using a random key first and then encrypt this random key using RSA - 15360 public key). So the encrypted line will contain some header info, RSA encrypted AES Key and the AES encrypted cardholder line)

So is this a decent practice -- mixing plain text and cipher text? (OR) will this pose any PCI compliance issues or result in any vulnerabilities?

  • 1
    Can you elaborate on why you want to avoid overhead? Does your system have strict performance requirements? Why don't you simply encrypt the whole thing?
    – Sjoerd
    May 13, 2019 at 13:46
  • 3
    The Linux passwd or shadow file is an example of a text file with hashed and plaintext text. You can do the same thing with cypher texts.
    – schroeder
    May 13, 2019 at 13:48
  • This is looking more like a programming design problem than a security problem. Your requirements are not security-related but performance- and overhead-related. Your PCI question is another matter entirely and on another layer of the problem.
    – schroeder
    May 13, 2019 at 13:50
  • I read this as purely security / PCI related, which is why I migrated it here. The performance issue seems to be solved, Ashwin is just concerned if it secure / compliant. May 13, 2019 at 13:53
  • Hard to say... Sensitivity generally has 3 main concerns, Confidentiality (encryption is good here), Integrity (digital signature can help help) and Availability (alternative access or storage for the information). Beside saying that data with no confidentiality concern does not need encryption little can be said. If nothing in the encrypted data can be deduced from the clear text data, there should not be any problem. If something (be it the actual length or format) can be deduced from the clear text data, that could be used for side channel attacks. May 13, 2019 at 13:54

1 Answer 1


Yes, you can mix encrypted and unencrypted data in the same file. The real question is whether you really want to, or whether it's easier to just encrypt the whole file.

In particular, regarding performance concerns, the general rule of thumb is that public-key encryption schemes like RSA are slow (especially with such a large modulus as you're using), while symmetric ciphers like AES are blazingly fast, especially on modern CPUs that have hardware support for them. Since you're using a hybrid cryptosystem where you encrypt the data with AES and then encrypt the AES key with RSA, the total time needed to encrypt or decrypt a transaction is almost certainly dominated by the slow RSA part of the system, which does not depend on the amount of encrypted data.

So, in practice, there is almost certainly no noticeable performance gain from encrypting only part of the data, and so you might as well encrypt all of it. The main exception being, of course, if your transactions include some (meta)data that you need to store unencrypted. (Even if so, you should still include those unencrypted fields when signing the transactions, so that they cannot be tampered with. Assuming that you are signing the transactions, that is. If you're not, consider whether you should.)

OK, so let's assume that you do want to store encrypted and unencrypted data in the same text file. How should you do it?

The output of pretty much all modern encryption schemes is a stream of random-looking binary data. You can't directly include that in a plain text file (or, if you do, it will no longer be plain text), but you can e.g. base64 encode it into (mostly) alphanumeric ASCII text.

Depending on the mode of operation that you're using AES with, each piece of AES-encrypted data will typically be a few bytes longer than the unencrypted input. (You don't say what mode of operation you're using; generally I'd recommend a misuse-resistant authenticated encryption mode like AES-SIV or AES-GCM-SIV, although that's not strictly necessary if you're signing the full transactions anyway.) The base64 encoding will further elongate the ciphertext by a factor of 4/3 ≈ 1.33, but even so, it will still be of comparable length to the unencrypted input. So it's perfectly reasonable to, say, replace a string in a text file with the AES-encrypted and base64-encoded version of the same data.

On the other hand, while AES keys are only 16 to 32 bytes long, encrypting them with RSA will produce a ciphertext of the same size as the RSA modulus. With a 15360 bit modulus, that works out to 2.5 kilobytes of base64-encoded ciphertext for each transaction. You can probably just append that blob to the end of each transaction, but it's worth noting that its size (base64-encoded or not) will probably dominate your storage requirements.

If you want to reduce that storage overhead, you need to either use a smaller RSA modulus (but not too small, or it won't be secure) or switch to some other public-key encryption scheme such as ECIES with less overhead than RSA.

(Or, if you want to keep it simple and safe, consider just ditching your custom RSA+AES based scheme and replacing it with e.g. NaCl crypto_box or any of its various compatible implementations. That way, as long as you fulfill the crypto_box contract of choosing a random secret key and never using the same nonce for two transactions, you won't need to worry about any other details. Well, except for base64-encoding the ciphertext, if you want to do that.)

  • Thank you for such a detailed explanation!
    – Ashwin
    May 14, 2019 at 14:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .