Encryption using multiple keys - security

Encryption using multiple keys
Let's say I have a file f that needs to be encrypted. I encrypt the file using a randomly generated key (using any encryption standard, say AES-256) and store this key in a key file k1. Now I encrypt k1 using another (different) randomly generated key and put this in file k2. I repeat this process to get kn-1 files. Now when I encrypt the file kn-1, I put the key (randomly generated) into file kn. So in kn, key to decrypt kn-1 is stored without any encryption and can be directly used to decrypt kn-1.
The decryption process is the opposite. The key file kn is used to decrypt kn-1, which is used to decrypt kn-2 and so on till k1 is decrypted. Key in k1 is used to decrypt the starting file f.
I am very new to encryptions so forgive me if this is a lame question but I had read somewhere about the merits and demerits of encrypting the same file multiple times and I thought of this. I have a few questions. What is this type of encryption called? I presume it could be used in a situation where there is file that is shared by n number of participants and should be opened only if all n participants are present at the same time, in which case, each of these n participants could be given a key and since the keys can only be opened sequentially, keys of each one would have to be present. Any other situations it can be used in?
Also, a major question is this - Can the decryption chain be bypassed somewhere? I mean to decrypt the kn file, you need the kn+1 file, so is there a way that I am missing that an attacker could access kn file without having kn+1 file? (I am assuming a strong encryption algorithm is used and brute forcing is not an option).
I am new to Stackoverflow so I apologize in advance if I have made a mistake somewhere.

Related

Review: Protocol for encryption/decryption of big files with authentication

I've been trying to figure out the best way to accomplish the task of encrypting big (several GB) files into the file system for later access.
I've been experimenting with several modes of AES (particularly CBC and GCM) and there are some pros and cons I've found on each approach.
After researching and asking around, I come to the conclusion that at least at this moment, using AES+GCM is not feasible for me, mostly because of the issues it has in Java and the fact that I can't use BouncyCastle.
So I am writing this to talk about the protocol I'm going to be implementing to complete the task. Please provide feedback as you see fit.
Encryption
Using AES/CBC/PKCS5Padding with 256 bit keys
The file will be encrypted using a custom CipherOutputStream. This output stream will take care of writing a custom header at the beginning of the file which will consist of at least the following:
First few bytes to easyly tell that the file is encrypted
IV
Algorithm, mode and padding used
Size of the key
The length of the header itself
While the file is being encrypted, it will be also digested to calculate its authentication tag.
When the encryption ends, the tag will be appended at the end of the file. The tag is of a know size, so this makes it easy to later recover it.
Decryption
A custom CipherInputStream will be used. This stream knows how to read the header.
It will then read the authentication tag, and will digest the whole file (without encrypting it) to validate it has not been tampered (I haven't actually measure how this will perform, however it's the only way I can think of to safely start decryption wihtout the risk of knowing too late the file should not have been decrypted in the first place).
If the validation of the tag is ok, then the header will provide all the information needed to initialize the cipher and make the input stream decrypt the file. Otherwise it will fail.
Is this something that seems ok to you in order to handle encryption/decryption of big files?
Some points:
A) Hashing of the encrypted data, with the hash not encrypted itself.
One of the possible things a malicious human M could do without any hash: Overwrite the encrypted file with something else. M doesn´t know key, the plaintext before and/or the plaintext after this action, but he can change the plaintext to something different (usually, it becomes garbage data). Destruction is also a valid purpose for some people.
The "good" user with the key can still decrypt it without problems, but it won´t be the original plaintext. So far no problems if it´s garbage data if (and only if) you know for sure what´s inside, ie. how to recognize if it is unchanged. But do you know that in every case? And there´s a small chance that the "gargabe" data actually makes sense, but is not the real one anyways.
So, to recognize if the file was changed, you add a SHA hash of the encrypted data.
And if the evil user M overwrites the encrypted file part, he will do what with the hash? Right, he can recalculate it so that it matches the new encrypted data. Once again, you can´t recognize changes.
If the plaintext is hashed and then everything is encrypted, it´s pretty much impossible to get it right. Remember, M doesn´t know the key or anything. M can change the plaintext inside to "something", but can´t change the hash to the correct value for this something.
B) CBC
CBC is fine if you decrypt the whole file or nothing everytime.
If you want to access parts of it without decrypting the unused parts, look at XTS.
C) Processing twice
It will then read the authentication tag, and will digest the whole
file (without encrypting it) to validate it has not been tampered (I
haven't actually measure how this will perform, however it's the only
way I can think of to safely start decryption wihtout the risk of
knowing too late the file should not have been decrypted in the first
place).
Depending on how the files are used, this in indeed necessary. Especially if you want to use the data during the final step already, before it has finished.
I don´t know details about the Java CipherOutputStream,
but besides that and the mentioned points, it looks fine to me.

Does a Message authentication code (MAC) ensure authenticity of the key used?

I have to protects confidentiality, integrity and authenticity of a file of records with a password. The number of records can potentially be more then 32^2 and each record can be accessed independently.
One way to implement it is
Generate a 256-bit random salt and store it in the file header.
Generate a derived key from the password and the salt using PBKDF2 with HMAC-SHA256 from PKCS #5.
For each record generate a 96-bit random initialization vector.
Encrypt each record's content using AES-256 in GCM mode using the derived key, the initialization vector, and (as additional authenticated data) the position of the record in a file.
As a result, each record will store an initialization vector, an encrypted content, and a MAC.
But the NIST Special Publication SP800-38D defining GCM and GMAC requires the number of records to be less than 32^2 for the initialization vectors to be unique.
So I devised another solution: create a key for each record with HMAC-SHA256 using the derived key as a key and the position of the record in a file as a message to be authenticated (salt).
So the question is do I need to provide the position of the record in a file to the authenticated encryption algorithm
as an additional authenticated data since I've already taken care of it when generating the key?
Additionally do I really need to use initialization vectors at all since all the records will be encrypted and
authenticated using supposedly different keys generated by HMAC-SHA256(PBKDF2(HMAC-SHA256, password, salt, iterationCount, 256), blockAddress) ?
I don't know what the size of the file will be, so I presume it can be very large.
If I understood you correctly (bit of a disclaimer, sorry) then you should be fine without adding the position within the record in the file.
No you don't need a random IV if you only use a (session) key once. Using an IV consisting of zero's would be enough (deterministic construction, using one device and a counter set to zero, if we keep with the NIST nomenclature).

Keeping Encrypted Strings Safe with Multiple Encrypts

A system I have been working on for a while requires DPA, and asked a question about keeping the data passcodes safe. I have since them come up with an idea to fix that, which involves having the data decrypt password for the database stored on the database, but have that encrypted with validated users password (which is stored as an MD5 key) after a different type of hashing.
The question is that does encrypting the password multiple times with different keys (at least 20 characters long, with possible extension) make it considerably easier to decrypt without prior knowledge or information on the password?
No, in general a good cipher should have the property that you cannot retrieve data even if you know the plaintext. Having the data encrypted should not have much influence, geven a good cipher and a big enough key space.
First off, MD5 is no longer considered a secure encryption algorithm. See http://www.kb.cert.org/vuls/id/836068 for details.
Secondly, the encryption key for the data should not be stored in the database itself. It should be stored separately. That way there are at least two things that have to be obtained (the database file and the key) to decrypt the data. If the key is stored in the database itself, it probably wouldn't take long to find it once someone has the database file.
Find a separate method for storing the key. It should either be coded into the application or stored in a file that is obfuscated in some way.

Hashing vs. Signing Binaries

If you want to ensure that a file is valid (untampered and came from the correct/expected source), there are two things you can do: hashing, and signing.
For the purposes of my question, hashing means providing a hash of the file (along with the file) to download. The client downloads the hash and the file, re-computes the hash, and verifies that it matches the downloaded hash; this "proves" that the file was untampered with.
Signing means using a public-private encryption scheme, where you sign the binary with a public key, and the client uses the private key to verify that you really did sign the key.
Based on these definitions, I don't really see what is the main benefit of signing something vs. hashing something. Both of them are supposed to prove that the file was not tampered with.
The only thing I can see is that with hashing, a compromised server could mean someone also compromising the hash and replacing a malicious binary with a matching key; but with a public-private scheme, as long as the private key remains private, there is no way to forge a malicious file.
Or am I missing something?
The difference is as you said: a hacker can update a hash to match the tampered-with file, but cannot generate a valid signature.
Signing is done with the private key, verification with the public key. You said the opposite above. It's also typically done on the hash of the file and not the file itself for practical reasons.
Signing verifies two things -- that the file has not been tampered with, and the identity of the signer. If you can be sure that entity giving you the hash is absolutely the entity that is supposed to be giving you the file, then the two are equivalent. Signing and certificate authorities are a way of ensuring that trust relationship.
Hash is a output with fixed length of characters(or bits if represented in binary) for a specific data that is passed into a function.
Hash is irreversible.The hash value for a particular data is always same. If a single bit in data changes almost entire hash for the altered data is changed. The process of calculating a hash is called hashing.
In Asymmetric cryptography each communicating party has his own key pair (private key and public key). As name suggest , private key is usually kept secret and public key is shared. These keys are as such in nature that if one is used to encrypt then the only other key pair can decrypt.
To achieve non repudiation(sender cannot deny he sent message) and to Authenticate specific entity to receive data , public key is shared to them so that they can decrypt anything that is encrypted by the sender using the corresponding private key that is with the sender(only with sender i.e secret)
But note that confidentiality is week in this example as sender does not know and cannot guarantee if public key was compromised to an unknown.
when private key is used to encrypt a Hash then it becomes a signature and the process is called signing. This achieves Authenticity (that data is coming from a genuine guy as private key is used) and also Integrity is assured because receiver verifies the Hash upon receiving data by decrypting the hash using corresponding public key given to him by sender and then calculating the same hash on his own and matching it.
The big difference between providing some data (an executable a document, whatever) along with a hash and providing the same data with a signature is with the hash, both the data and the hash value come from the same place. So, if someone can compromise one of them, he can probably also compromise the other.
For example, if I can hack into your web server, I can easily replace your executable with my own version and replace the hash value with the correct hash for my executable.
If you sign your executable, I can't just produce another signature for a different executable and replace your original signature. The signature verifies both the hash of the original data (the data has not changed since being signed) and that the signature was generated by your private key.
Of course, this all assumes that people who receive your signed executable have received your public key in some trusted way. If I can trick people into using my public key instead of yours, then I can hack into your website and replace your signed executable with my own. That's why we have certificate authorities.
This page has a high level overview of digital signatures.

Shared encrypted file but using different key to decrypt

I just curious, if there any encryption algorithm that can support this scenario.
A plain text file (T) was shared among two parties, this file was encrypted (let say symmetric AES) to become encrypted file (E). The Encrypted file will be stored in the server, and after encryption takes place, additional party can be added at any time.
When first party wants to get the T file, he/she passes P1K to decrypt E file
when second party wants to get the T file, he/she passed P2K to decrypt E file.
Any idea how to achieve this using pure encryption algorithm only (without using database to store intermediary key) ?
If the sender already has the public key component for the intended recipients of the secret message than this can be done with GnuPG using paired key encrpytion.
The sender needs to encrypt the data to the public key of the intended recipients (maybe the senders own key as well) and only those people will be able to use their private key to decrypt the secret message.
Not sure if the requirement to preawareness of or access to the receivers public keys is an issue or disqualifies the answer as a type of database of info that the sender must have.
All users get to keep their private bits to themselves though as opposed to if they all had to have shared the same password, in this case no user has access to the private key any of their contacts.
http://www.gnupg.org/
The plain text (T) can be encrypted with a secret key (Ks) using a symmetric cipher like AES.
Ks is encrypted with as many public keys that is allowed to know the symmetric cipher and added as part of the encrypted message packet.
Decryption just means iterating through the list of encrypted Ks against the private key of a user.
Who passes what key to whom? (Also, traditionally P for plaintext and C for ciphertext.)
And there's an easy answer (unless I'm misunderstanding you, which is an obvious possibility since your question isn't very clear): Give each recipient "half" of the key in the first place, and the other half when you want them to be able to decrypt the message.
How do you split a key in half? A decent way is to XOR it with a nonce: give person 1 K⊕N1 and person 2 K⊕N2. When you want them to decrypt the message, give them N1 or N2 respectively.
Another easy answer is to just give each person the key encrypted with the recipient's public key when you want them to decrypt the message.

Resources