How the Private keys are distributed safely? - security

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.

Related

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.

AES256 CBC + HMAC SHA256 ensuring confidentiality *and* authentication?

I'm thinking of using AES256 CBC + HMAC SHA-256 as a building block for messages that ensures both confidentiality and authentication.
In particular, consider this scenario:
Alice is possession a public key belonging to Bob (the key exchange and algorithm is outside the scope of this question). Alice has an identifying key K, also shared with Bob, that she can use to identify herself with. Only Alice and Bob knows the key K.
Alice encrypts (nonce || K) using Bob's public key.
Bob decrypts the packet and has now has K and nonce.
Bob uses SHA-256 with SHA256(K || nonce) to yield a K(e) of 256 bits.
Bob uses SHA-256 with SHA256(K || nonce + 1) to yield a K(s) of 256 bits.
Now for every packet Bob wishes to send Alice he performs the following:
Create a new random 128 bit IV
Encrypts the message using the IV and K(e) as the key.
Creates a SHA-256 HMAC with K(s) as key and (IV || Encrypted message) as data.
Finally sends (IV || HMAC || Ciphertext) to Alice
Alice has also calculated K(e) and K(s), and follows the following procedure when receiving data from Bob:
Split the message into IV, ciphertext and HMAC.
Calculate the HMAC using K(s), IV and ciphertext.
Compare HMAC with the HMAC sent. If this matches, Alice considers this message authenticated as a message sent by Bob, otherwise it is discarded.
Alice decrypts the message using K(e)
Does this protocol ensure that Alice only decrypts messages from Bob, assuming that no one other than Bob can read the encrypted message that Alice sends him encrypted using his public key?
I.e. does messages constructed in this manner ensure both confidentiality and authentication?
Note: If the protocol requires Bob to send multiple messages, this scheme needs a slight modification to avoid replay attacks.
P.S. I am aware of AES-GCM/CCM, but this scheme would work with the basic AES, SHA and HMAC algorithms that are found in most crypto packages. This solution might also be slower, but that too is out of the scope for the question.
Basically you are recreating SSL/TLS. This implies the usual caveats about building your own protocol, and you are warmly encouraged to use TLS with an existing library instead of rewriting your own.
That being said, using AES with CBC for encryption, and HMAC for integrity, is sound. There are combined encryption+integrity modes (that you are aware of), and CBC+HMAC is kind of "old school", but it cannot hurt. You are doing things in the "science-approved" way: encrypt, then MAC the encrypted string (and you do not forget the IV: forgetting the IV is the classical mistake).
Your key derivation may be somewhat weak. It is perfect if SHA-256 behaves like a perfect random oracle, but it is known that SHA-256 does not behave like a random oracle (because of the so-called length-extension attack). It is similar to the reason why HMAC is HMAC, with two nested hash function invocations, instead of simple hashing (once) the concatenation of the MAC key and the data. TLS uses a specific key derivation function (which is called "the PRF" in the TLS specification) which should avoid any trouble. That function is built over SHA-256 (actually, over HMAC/SHA-256) and can be implemented around any typical SHA-256 implementation.
(I am not saying that I know how to attack your key derivation process; only that this is a tricky thing to make properly, and that its security may be assessed only after years of scrutiny from hundreds of cryptographers. Which is why reusing functions and protocols which have already been thoroughly examined is basically a good idea.)
In TLS there are two nonces, called the "client random" and the "server random". In your proposal you only have the "client random". What you lose here, security-wise, is kind of unclear. A cautious strategy would be to include a server random (i.e. another nonce chosen by Bob). The kind of things we want to avoid is when Alice and Bob run the protocol in both directions, and an attacker feeds messages from Alice to Alice herself. Complete analysis of what an attacker could do is complex (it is a whole branch of cryptography); generally speaking, nonces in both directions tend to avoid some issues.
If you send several packets, then you may have some issues about lost packets, duplicated packets ("replay attacks"), and packets arriving out of order. In the context of TLS, this should not "normally" happen because TLS is used over a medium which already ensures (under normal conditions, not counting active attacks) that data is transferred in strict order. Thus, TLS includes a sequence number into the data which goes in the MAC. This would detect any alteration from an attacker, include replay, lost records and record reordering. If possible, you should also use a sequence number.
The answer to the question as stated is no, there is no guarantee that Alice only decrypts messages from Bob, but that's only because you didn't stipulate that only Bob knows K. If Alice and Bob are the only two people who know K, then the crux of the question is whether your key generation protocol is sound. (We can ignore the rest, I believe, because you're just using HMAC-SHA256 and AES256 as they are intended to be used.)
The generation protocol isn't bad, but it can be improved. The accepted way to create keys from shared secrets is to use a "key derivation function". These functions use a hash in a similar way to what you have done here, but they are also purposely slow to inhibit brute force attacks. PBKDF2 seems to be what you want, as it a) can derive 512 bits of key data (or more), and b) can be made up of the primitives you have available; namely, SHA256 and HMAC-SHA256.
If you don't want to use PKI, take a look at TLS-PSK. It would seem to solve the exact problem you are solving yourself. See RFC 4279 (and 5487 for additional ciphersuites).

RSA: Encrypting message using multiple keys

Is it possible to get additional security by encrypting a message using 2 or more RSA keys?
EDIT: A few clarifications:
The context I am most interested in doing this for is encrypting a randomly generated symmetric key.
I don't want to limit the question to encrypting twice in a row; the purpose is to avoid the high computational cost of large RSA keys. Using less straightforward tactics such as breaking the message into parts and encrypting them separately should be considered as an option.
It should be assumed that getting only part of the message is acceptable.
If you know of any publications where this is discussed specifically by an expert, or algorithms that use multiple RSA keys, then please contribute.
No.
It is not safe to do thought experiments regarding cryptography. You are advised to keep narrowly to the path trodden by the experts.
And when the experts want to protect something better, they use a bigger key-size (at least 2048 bits is required, smaller certificates are insufficient for any peace of mind) or use elliptic curve certificates in preference to RSA.
Incidentally, you're remember that your message body is typically encrypted with a symmetric cipher and a random key, and that just this random key is encrypted with the public key of the recipient. Double-encrypting this secret key won't make this secret key longer, and won't impact an attacker's ability to brute-force that.
Quantum cryptography - I mention it only as an exciting aside, you need not factor this into your choice - promises interesting things for the keysizes: the RSA keys will be wiped out by Shor's algorithm, but the symmetric keys (Grover's) will be only half-lengthed (128-bits will be equiv to 64-bits, so will be crackable). There is of course debate about whether such quantum machines can be implemented etc etc :)
No.
If Key A is compromised than encrypted with A+B will protect against the compromise, but outside that special case, you get no additional benefit.
Composing ciphers
Say you have an encryption function E(M, K), where M is the plaintext message and K is the key. Say no known vulnerabilities exist in E.
You generate two completely unrelated keys K1 and K2.
It is guaranteed that if you compose them in the form E(E(M, K1), K2), it is impossible to actually lose security this way. If it was possible to lose security from encrypting E(M, K1), be it with K2 or any other key, the is cipher broken, because an attacker could just do E(E(M, K1), KF) where KF is any key the attacker wishes to choose.
For more info see here.
Encrypting every second block with a different key
The implications here are obvious. Assuming you are using properly composed cryptographic primitives with both encryption function:key combinations, if you encrypt every second block with a different key out of the set of two keys, the attacker can only decrypt the blocks he has the key for.
Yes!
But do not use raw encryption. Use RSA encryption schema. Instead of reencrypting the encrypted message with the second key, which might have weakening effet (I don't know), use the shared secret algorithm to split your secret in two. The shared secret algorithm make it possible to split a secret in n pieces and ensures that if an attacker manages to get n-1 pieces he knows nothing of the secret. So don't simply split the secret in two.
You can then have more then 2 RSA keys. Another powerful property of the shared secret algorithm is that it is possible to spread the secret over n pieces and require only m pieces, with m smaller than n, to recover the secret. This makes the secret recovery more robust to loss of pieces.
Look here for more information on shared secret: http://en.wikipedia.org/wiki/Shared_secret
In additional to the answers given, it also simply doesn't work unless you do some patching. Very simply, one of the moduli must be larger than the other. If you perform RSA mod the larger modulus first and mod the smaller last you lose information and cannot guarantee successful decryption. The obvious patch is to always encrypt with the smaller modulus first. Of course, you have to perform decryption in the opposite order. Another simple patch is choose moduli that a very close together in size, so that the probability that you encounter a ciphertext that cannot be uniquely decrypted is vanishingly small.

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