How does two party encryption work? - security

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.

Related

How the Private keys are distributed safely?

I am going through RSA Algorithm and I have few questions. The questions can be silly, Please help me.
My understanding of RSA Algorithm.
My Question is, How does a Receiver get his private keys P and Q.
For a particular Public Key, If every receiver has the Same private keys then One malicious Receiver can decrypt any message that is intended to send to other receivers?
The general model is that the the sender generated their own private key, so the key isn't transmitted, it is just manufactured out of whole cloth.
When looking at small numbers there aren't very many prime numbers to choose from, so the risk of collision is high. For example, there are only 25 prime numbers less than 100, so a total of 300 private keys (25 * 24 / 2). The odds that a second party has the same key as you in that constrained space, 1 in 300.
When you get into bigger key-spaces, though, the chance of two parties accidentally having the same private key are vanishingly small. RSA-1024 (which is now "too small") uses 512-bit values for p and q. The prime number theorem says there are approximately 2^511 / ln(2^511) (~1.9e151) 512-bit prime numbers, making about 1.8e302 different private keys. The birthday problem says that there's a 1% chance of two randomly generated RSA-1024 keys being the same after 1.9e150 keys have been generated. That's a lot of keys.
For RSA-2048: 1.3e305 1024-bit primes, 8e609 private keys. 1% chance of collision at 1.3e304 key generations.
You are correct, though, that if two parties have the same private key, they each can decrypt messages intended for the other party (and can sign messages on behalf of the other party).
The solution is: don't share private keys. Generate your own, and do it in a big enough keyspace. (Not just to keep collisions down, but to keep targeted key breaking hard)
In general each "receiver" has its own private key which is never shared. You usually rely on a PKI to sign a different key to each "receiver". In that context key distribution is relatively easy because the "receiver" generate his private key locally and get his public key signed by the CA. It is exactly how HTTPS works so you can look at how let's encrypt do it as a reference.
You should make sure to keep the root key of the PKI and the private signing key secure. E.g use a HSM or a cold storage.

What does it mean to encrypt with a public key? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I've heard lots of public key theory, but I've never really understood how you can encrypt something that can be decrypted with a private key that you don't have.
How does encrypting a message with a public key make it so that only the person with the corresponding private key associated with that key can decrypt it?
Encryption keys come in a public/private pair. The private is closely held by the owner, but the public can be passed around to those who need to encrypt something in order to send it to the owner.
Something that has been encrypted by the public key can only be decrypted with the private key as it contains more details used by the encrypt/decrypt routines.
While this may not provide the technical details you may be looking for, hopefully it helps shed some light on the relationship between the keys.
This video by Youtube channel Art of the Problem does a good job of explaining it conceptually, before getting into the exact details of how the RSA algorithm implements it.
If you think of encryption as use of a lock and key to secure information, then standard shared-key encryption involves both you and your collaborator holding onto the same key. When you send a message, you take your message, shut it inside a locked box by using your key, then send the box to the recipient who opens it with a copy of the key that you have.
In public-private key encryption, you don't give out copies of your key; you keep your key private. Instead, you give out instructions on how to build a lock that only your key can open. You give this out to anyone who asks for it. They are responsible for building the lock and using it to secure their information before sending it back to you. If they do it correctly, then the lock they've built opens perfectly when you put your private key in it.
A different way to think about the encryption step is that you actually hand out copies of your lock to anyone who wants to send you a message. They can take this lock, slap it on their message and no one can open it to read the contents without the key - not even the original sender! This would be very expensive to do with physical locks, but is very easy to do digitally.
Public-private encryption relies on a One-way function (more correctly, a certain type of one-way function called a trapdoor function), a mathematical formula that is easy to compute, but hard to find the inputs if you only have the output. Analogously, you have a lock design such that it is easy to construct from a set of instructions, but hard to reverse engineer without seeing the actual key that fits the lock.
I tend to also think about this part in terms of tying knots. It's very easy to take a series of steps to tie a rope in knots. Even know what you did and in what order, some times it's impossible to reverse the order of the steps to undo the knot. Either you've put in a slip somewhere, or you need to get your secret knot-untying key to release the rope. (Hint: the secret knot untying key is a knife. Count your fingers when you're done.)
Look at it like this:
A message from Person B is being delivered to only Person A. Person A
has the key (Private Key) to open the Chest (Public Key) and read the
message. At this point, Person A can respond to the message and place
it back in the Chest (Public Key) and redeliver to Person B. Person B
can now use their key (Private Key of their own) to read the message in the Chest (Public Key)
Hopefully this analogy will help.

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.

Using asymmetric encryption to secure passwords

Due to our customer's demands, user passwords must be kept in some "readable" form in order to allow accounts to be converted at a later date. Unfortunately, just saving hash values and comparing them on authentication is not an option here. Storing plain passwords in the database is not an option either of course, but using an encryption scheme like AES might be one. But in that case, the key to decrypt passwords would have to be stored on the system handling authentication and I'm not quite comfortable with that.
Hoping to get "best of both worlds", my implementation is now using RSA asymmetric encryption to secure the passwords. Passwords are salted and encrypted using the public key. I disabled any additional, internal salting or padding mechanisms. The encrypted password will be the same every time, just like a MD5 or SHA1 hashed password would be. This way, the authentication system needs the public key, only. The private key is not required.
The private key is printed out, sealed and stored offline in the company's safe right after it is created. But when the accounts need to be converted later, it will allow access to the passwords.
Before we deploy this solution, I'd like to hear your opinion on this scheme. Any flaws in design? Any serious drawbacks compared to the symmetric encryption? Anything else we are missing?
Thank you very much in advance!
--
Update:
In response to Jack's arguments below, I'd like to add the relevant implementation details for our RSA-based "hashing" function:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher rsa = Cipher.getInstance("RSA/None/NoPadding");
rsa.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cryptRaw = rsa.doFinal(saltedPassword.getBytes());
Having quickly skimmed over the paper mentioned by Jack, I think I somewhat understand the importance of preprocessing such as OAEP. Would it be alright to extend my original question and ask if there is a way to apply the needed preprocessing and still have the function return the same output every time for each input, just as a regular hashing function would? I would accept an answer to that "bonus question" here. (Or should I make that a seperate question on SOF?)
--
Update 2:
I'm having a hard time accepting one of the present answers because I feel that none really does answer my question. But I no longer expect any more answers to come, so I'll accept the one that I feel is most constructive.
I'm adding this as another answer because instead of answering the question asked (as I did in the first response) this is a workaround / alternative suggestion.
Simply put:
Use hashes BUT, whenever a user changes their password, also use your public key as follows:
Generate a random symmetric key and use it to encrypt the timestamp, user identifier, and new password.
The timestamp is to ensure you don't mess up later when trying to find the current / most up-to-date password.
Username so that you know which account you're dealing with.
Password because it is a requirement.
Store the encrypted text.
Encrypt the symmetric key using your public key.
Store the public key encrypted symmetric key with the encrypted text.
Destroy the in-memory plaintext symmetric key, leaving only the public key encrypted key.
When you need to 'convert' the accounts using the current password, you use the private key and go through the password change records. For each one:
Using the private key, decrypt the symmetric key.
Using the symmetric key, decrypt the record.
If you have a record for this user already, compare timestamps, and keep the password that is most recent (discarding the older).
Lather, rinse, repeat.
(Frankly I'm probably overdoing things by encrypting the timestamp and not leaving it plaintext, but I'm paranoid and I have a thing for timestamps. Don't get me started.)
Since you only use the public key when changing passwords, speed isn't critical. Also, you don't have to keep the records / files / data where the plaintext password is encrypted on the server the user uses for authentication. This data can be archived or otherwise moved off regularly, as they aren't required for normal operations (that's what the hash is for).
There is not enough information in the question to give any reasonable answer. Anyway since you disable padding there is a good chance that one of the attacks described in the paper
"Why Textbook ElGamal and RSA Encryption are Insecure" by
D. Boneh, A. Joux, and P. Nguyen is applicable.
That is just a wild guess of course. Your proposal could be susceptible to a number of other attacks.
In terms of answering your specific question, my main concern would have been management of the private key but given it's well and truly not accessible via any computer system breach, you're pretty well covered on that front.
I'd still question the logic of not using hashes though - this sounds like a classic YAGNI. A hashing process is deterministic so even if you decided to migrate systems in the future, so long as you can still use the same algorithm, you'll get the same result. Personally, I'd pick a strong hash algorithm, use a cryptographically strong, unique salt on each account and be done with it.
It seems safe enough in terms of what is online but have you given full consideration to the offline storage. How easy will it be for people within your company to get access to the private key? How would you know if someone within your company had accessed the private key? How easy would it be for the private key to be destroyed (e.g. is the safe fireproof/waterproof, will the printed key become illegible over time etc).
You need to look at things such as split knowledge, dual control, tamper evident envelopes etc. As a minimum I think you need to print out two strings of data which when or'd together create the private key and then have one in your office and one in your customers office,
One serious drawback I've not seen mentioned is the speed.
Symmetric encryption is generally much much faster than asymmetric. That's normally fine because most people account for that in their designs (SSL, for example, only uses asymmetric encryption to share the symmetric key and checking certificates). You're going to be doing asymmetric (slow) for every login, instead of cryptographic hashing (quite fast) or symmetric encryption (pretty snappy). I don't know that it will impact performance, but it could.
As a point of comparison: on my machine an AES symmetric stream cipher encryption (aes-128 cbc) yields up to 188255kB/s. That's a lot of passwords. On the same machine, the peak performance for signatures per second (probably the closest approximation to your intended operation) using DSA with a 512 bit key (no longer used to sign SSL keys) is 8916.2 operations per second. That difference is (roughly) a factor of a thousand assuming the signatures were using MD5 sized checksums. Three orders of magnitude.
This direct comparison is probably not applicable directly to your situation, but my intention was to give you an idea of the comparative algorithmic complexity.
If you have cryptographic algorithms you would prefer to use or compare and you'd like to benchmark them on your system, I suggest the 'openssl speed' command for systems that have openssl builds.
You can also probably mitigate this concern with dedicated hardware designed to accelerate public key cryptographic operations.

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