Shared encrypted file but using different key to decrypt - security

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.

Related

How to do 1-of-X or Y-of-X public key based encrypt/ decrypt in NodeJs?

I would like to be able to encrypt data using public keys, and decrypt the encrypted data using private keys.
Encryption essentially needs to accept inputs:
Clear data to be encrypted
A list of several public keys
The minimum number of private keys corresponding to those public keys that are needed to decrypt the encrypted
How can this be done in NodeJs?
Scenarios
By way of concrete scenarios, where there are 5 users (A - E) with crypto key pairs in the system.
A 1-of-X scenario:
encrypted = crypto_encrypt(clearText, [A.publicKey, B.publicKey], 1) (1-of-2)
decrypted = crypto_decrypt(encrypted, [A.privateKey])
success: decrypted === clearText
because A.publicKey was used in encryption
decrypted = crypto_decrypt(encrypted, [C.privateKey])
failure: unable to decrypt
because C.publicKey was not used in encryption
A Y-of-X scenario:
encrypted = crypto_encrypt(clearText, [A.publicKey, B.publicKey, C.publicKey], 2) (2-of-3)
decrypted = crypto_decrypt(encrypted, [A.privateKey, C.privateKey])
success: decrypted === clearText
because both A.publicKey and C.publicKey was used in encryption
decrypted = crypto_decrypt(encrypted, [C.privateKey, E.privateKey])
failure: unable to decrypt
because while C.publicKey was used in encryption, E.publicKey was not
Ideally...
At minimum I need to be able to support the 1-of-X scenario, but if Y-of-X is also possible, that would be better
What the actual key pairs are is not so important here, could be RSA, could be any of the elliptic curves. If the method supports a number of different ones, and allows one to pick, that would be better
Preferably not tied to the use of any particular toolset or framework
PGP can do this.
Specifically for node, openpgpjs has a section in the README - https://github.com/openpgpjs/openpgpjs#encrypt-and-decrypt-string-data-with-pgp-keys - which could be condensed into:
const encryptedText = await openpgp.encrypt({ message: clearText, publicKeys });
const decryptedText = await openpgp.decrypt({ message: encryptedText, privateKeys });
However:
for number of keys required to decrypt, it only supports the 1 of many scenario, not the more general some of many scenario you'd ideally want
supports both RSA and many elliptic curve based keys, but the key format is designed for use by PGP, as the name of the library implies (so it is specific to the PGP toolchain)
As noted by Luke Joshua Park in the comments, this sounds like a textbook use case for a secret sharing scheme. Specifically, I would recommend that you:
Generate a random AES (or other symmetric cipher) key. Make sure to use a cryptographically secure RNG (such as Crypto.randomBytes()) for this, since an attacker who can guess this key can also break the entire scheme!
Encrypt the data with this key, using an authenticated encryption mode such as AES-SIV (as provided e.g. by miscreant).
Split the AES key into multiple shares using Shamir's secret sharing scheme with the desired reconstruction threshold. (Some JS implementations I found with a quick Google search include secrets.js, jsss and ThresholdJS.)
Encrypt each share using a different user's public key.
Send each user their encrypted share and a copy of the AES-encrypted data.
Disclaimer: I have not reviewed the security or correctness of any of the APIs or libraries linked above. The cryptographic techniques they claim to use appear to be sound and suitable for this task, but I cannot guarantee that they have been implemented safely and correctly. Caveat emptor.
To decrypt the data, each user can first decrypt their share of the AES key using their private key, and a sufficient number of the decrypted shares can then be combined (using the same implementation of Shamir's secret sharing as used to create them) to reconstruct the original AES key, which can then be used to decrypt (and verify the integrity of) the data.
Note that Shamir's secret sharing implicitly assumes that the users who combine their shares to reconstruct the secret will trust each other and not lie about their shares or otherwise misbehave. If that's not necessarily true, there are various ways for a malicious user to trick the others — perhaps most simply by waiting for everyone else to reveal their share to them and then refusing to reveal their own share to the others. In general, preventing such attacks is all but impossible without the help of some kind of a mutually trusted party.
At the very least, though, using an encryption mode like AES-SIV with built-in authentication should ensure that users will detect if the reconstructed AES key is incorrect, since the decryption will then fail. If you want to be extra sure of this, you may wish to also send each of the users a secure cryptographic hash (e.g. SHA-512) of the AES key, so that they can verify its correctness before attempting decryption.

Encryption using multiple keys

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.

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).

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.

How does two party encryption work?

I am able, with pidgin otr for example, capable of communicating with anyone and it is secure.
We haven't exchanged a secret passkey or anything else, the program just sets up the encryption and everyone assures me it is secure.
So what I have is this:
Person1 talking to Person2 (Assuming people really are who they say they are)
Since no info was ever exchanged between person1 and person2, what's to stop a badperson3 from intercepting all the traffic and deciphering all the messages?
I read about PGP, about how each machine has a private key and a public key that is shared between the two computers, but I don't fully get how this can work. It's not like person2 can encode messages using person1's private key, and if it uses the public key, anyone listening can decipher.
I'm a bit confused.
Without getting into technical details, the whole idea of public key cryptography like RSA is that the public key can be used to encrypt data, but cannot be used to decrypt what it just encrypted (without breaking the encryption, of course -- in the case of RSA that normally means factoring the product of two large primes).
There is, of course, still some data exchanged: you still need to get a person's public key before you can encrypt data using that public key. It's also worth noting that public key cryptography is generally a lot slower than symmetric cryptography. That being the case, most protocols that use public key cryptography try to minimize the amount of data encrypted using the public key algorithm. Typically, the sender will pick a random number of the right size to use as a key with a symmetric algorithm, encrypt it with the public-key algorithm, and send it to the receiver. The rest of the data is encrypted with the symmetric algorithm, using that key.
As such, in a typical case you're retrieving a public key, then generating, encrypting, and sending a private key, then sending data encrypted with that private key.
There is a good description written up on wikipedia: http://en.wikipedia.org/wiki/Public-key_cryptography
Messages encoded with someone's private key can only be decoded using the matching public key. Likewise, messages encoded with someone's public key can only be decoded with that person's private key.
If I encode a message with my private key and your public key, then you know that the message is guaranteed to be from me and only you can read it. You would decode it using my public key (to prove that the message came from me) and your private key (proving that only you can read it).
Here are the rules for public key encryption:
A public key may be used to encrypt a message that only the corresponding private key can decrypt.
A private key may be used to encrypt a message that only the corresponding public key can decrypt.
So, it works both ways. The public key being public isn't a problem.
The reason it works is a lot more complicated and involves some interesting math.
Now, OTR doesn't exactly use standard public key encryption. Their algorithms are based on public key encryption but have a small twist in them to allow either party to convincingly deny the conversation ever happened.
Also, OTR isn't secure if you don't actually talk to the person. It's susceptible to a man-in-the-middle attack. This isn't because the encryption can be broken or anything like that. No, a man-in-the-middle attack is where someone interposes themselves between you and the party you want to talk to.
If you are A and you are trying to talk to person B and there's a man in the middle, M, then the attack works like this.
You start talking to B, but unbeknownst to you, you start talking to M who is pretending to be B. When you start talking to M, M initiates a conversation with B pretending to be you. You encrypt all of your stuff to M (who you think is B). M decrypts it, and re-encrypts it to B (who thinks M is you).
If M can always stay in the middle, none of your conversations with B will be secure. If you can ever talk to B without M in the middle, OTR will complain that Bs public key has changed (which is basically because you were really using Ms public key and are just now getting Bs real public key). Of course, OTR might also be complaining because M is trying to interpose (him/her)self and the key you think is the right one really is.
The way to defeat a man-in-the-middle attack is for you and B to talk in some way where you can be certain for other reasons that you're talking to B. Then you can share information about your public key with B, and B can share information about h(is/er) public key with you. You can do this in a coffee shop or over the phone. It doesn't matter if anyone overhears the details, just that you know that it's the person you expect giving them to you.
There is also a fancier way to do this involving secrets that only you and B know. OTR has a mode for asking a question design to elicit a secret in such a way that M cannot provide the proper answer for you, only B can. M will be able to overhear the answer B provides, but will not be able to give it to you.
OTR does exchange information. You have to accept the other person's key and verify it's trusted. Then it all just goes back to normal asymmetric encryption. Which ... boils down to verifying that the one giving you the key and the one you want to talk to are the same person. Nothing magically happening here.
You can encode with a public key, but you have to have the private key to decode.
So if two people have public keys and share these with each other, then they can share information that can only be decoded with the receiver's private key.
Public key encryption works like this: You freely give out your public key. People use your public key to encrypt messages that can only be decrypted with your private key (which you do not share). Your private key acts like "the missing piece" that is used when decrypting the information insofar as it is the only part of the equation that can actually decrypt anything. If someone encrypts something with your public key, you cannot use your public key to decrypt the data afterwards. This is accomplished by using very large prime numbers and some very specific equations.
You have asked two questions:
There are ways to exchange keys securely, e.g. with the Diffie Hellman protocol. It's safe even if an attacker is listening to all the messages.
With public key cryptography each key has a public and a secret component. With the public component you can encrypt or verify a signature, with the secret component you can decrypt or create a signature. There's a lot of number theory to see how this works, but it's worth to learn it.

Resources