Handle user login using asymmetric cryptography - authentication

Is it possible to implement a login protocol with asymetric cryptography instead of the hashed password method?
For example, while creating an account, the client generates a private/public key pair from a hash of the username and password. The public key is then sent to the server with the username, and the server stores the username and the public key. When the user wants to login, he enters his password, the client regenerates the private key, signs a nonce with it, and sends the signed message to the server. The server is then able to authenticate the user as he knows the public key associated with the username.
Is there any flaws in this protocol?
And what would be the advantages over storing the password hash?

There might be a serious flaw with the authentication, yes, depending on the implementation. If Bob is the server and Alice is the client, with Mallory a malicious eavesdropper:
If Alice generates a random number, concatenates this with her username, encrypts with her private key and sends to server. Server decrypts and verifies with Alice's public key. Without the server saving the random number, this is susceptible to replay attacks - Mallory could just listen in, save the blocks that Alice sends to the server and just replay them later. Without saving them, the server would be none the wiser.
To protect the server against this, the server would have to generate the random number. It would also need to be a secure random number, otherwise Mallory could predict, or at least guess what the next number will be.
If Mallory could intercept messages, then he can purport to be Alice - he intercepts all communications and just relays them, even if the server generates the random number.
Alice and Bob both need to be able to prove that it was the other who has cheated. They also need to be able to detect tampering from Mallory - the protocol needs some extra layers to ensure authenticity of the messages.
There is research going into this at the moment, but as far as I know, it is very difficult to authenticate a user without a trusted certificate authority also being used: public keys can be known by all, but any attacker can swap their own public key for that of another without detection, unless there is trust established through a certificate authority.

Related

How can a mail server implement POP3/APOP without the user's passwords in clear-text?

Quoth RFC 1939, the standard that defines basic POP3 without extensions.
Examples:
S: +OK POP3 server ready <1896.697170952#dbc.mtview.ca.us>
C: APOP mrose c4c9334bac560ecc979e58001b3e22fb
S: +OK maildrop has 1 message (369 octets)
In this example, the shared secret is the string `tan-
staaf'. Hence, the MD5 algorithm is applied to the string
<1896.697170952#dbc.mtview.ca.us>tanstaaf
which produces a digest value of
c4c9334bac560ecc979e58001b3e22fb
If I imagine myself as the mail server at the point when the APOP command arrives, I've got the following items:
The challenge string which I randomly generated a moment ago.
The claimed user-name and MD5 hash from the client which may or may not be valid.
The user's password protected by bcrypt, scrypt, PBKDF2, or a similar hashing method.
You'll notice that the user's password in clear-text is not on the list, because we're not meant to do that in this day and age.
I still occasionally see the APOP challenge in the greeting when connecting to POP3 services. Are these services storing their user's passwords in the clear? If not, how are they implementing APOP without them?
There is no plaintext exchange of the user's password in this example. The password is hashed (not encrypted) on the client side, then the hash is sent to the server. The server performs the same hash of the password it has previously stored in the specified user's account, and if the two hashes match then access is granted. At no point is the client made aware of the hash that the server calculates.
Hashes can't be reversed, so there is no way for a MITM attacker to recover the original password from intercepting the submitted hash (the attacker could brute force its own password until a matching hash is submitted, but that takes a long time, and servers tend to implement countermeasures against that kind of thing).
Whether or not the user's password is stored in plaintext or not on the server side is irrelevant to APOP. That is an implementation detail of the server's account storage. One would hope that the server is encrypting the password in storage. But the server is required to have access to the actual password nonetheless.

Backend without traditional Authentication mechanism, use cryptography instead

Context: I have a mobile app, and I don't have, and will not, implement a traditional authentication flow (email/pw, social login). Instead, I would like to leverage asymmetric key encryption.
Requirements: For the sake of simplicity, let's imagine a simple backend with one User model, which only has one field: favorite_number.
a user can CRUD a User model on the backend.
a user cannot CRUD another user's User model.
Potential solution:
Alice generates a private/public key pair on her mobile device. She keeps the private key securely on-device.
Alice makes a network request (let's say a RESTful POST request) to the backend, with the following payload:
{
"public_key": {Alice's public key},
"favorite_number": 42,
"signature": sign_with_private_key(42)
}
where sign_with_private_key(42) is the signature of the message 42, signed with Alice's private key.
The backend receives the above payload, verifies that the signature matches the public key and the favorite_number, and saves the following information in its DB (assume SQL below):
| public_key | favorite_number | signature |
| ---------- | --------------- | --------- |
| 0x... | 42 | 0x.. |
Alice wants to read her favorite number:
Alice sends GET /api/get_nonce?public_key={Alice's public key} to the backend
The backend looks in the DB the row with Alice's public key, and returns its signature column ONLY
Alice decrypts the signature with her local private key, it returns 42.
Bob wants to read Alice's favorite number, he calls the same endpoint GET /api/get_nonce?public_key={Alice's public key}, get's Alice's favorite_number signature, but cannot decrypt it.
Bob wants to modify Alice's favorite number, but cannot, because he can't compute the signature of the favorite_number message.
Caveats (which I can live with):
If Alice loses her phone or uninstalls the app, all her account information on the backend will be lost.
Additional assumptions:
The DB cannot be directly accessed by other party than the backend (and DB administrator) itself. (clarification request by #kelalaka). But that's independent of authentication.
Question: Is this authentication scheme viable? Do you see any big security loopholes?
This feels a bit over-complicated. If Alice has a keypair, then Alice can simply sign requests, and the signature is the authentication. There's no particular reason to sign individual pieces of data. Just sign the requests themselves. For example:
{
"request": {"message_id":123,"public_key":"...","favorite_number":42},
"signature": signature_of('{"message_id":123,"public_key":"...","favorite_number":42}')
}
It is critical that you sign everything that is part of the request.
Note that requests need to be single-use, otherwise this is not secure. By single-use, I mean that a timestamp should be in the request and the same request should not be useable more than once. You can also use a message counter (especially since you only have one device that can connect). So the server always rejects messages ids equal to or smaller than the last id sent for this user.
Your approach is vulnerable to reuse of the value upon another key. For example, I could reuse "42" and assign it to some other thing like "hated_number." Or I could replay this message and reset Alice's favorite number to 42 after she has changed it to something else. Signing the entire request is a much better approach and avoids a number of these problems (as long as a request can't be reused).
If Alice wishes to protect the data from the administrator, then she should encrypt the data with a symmetric key, but that's independent of authentication.
A simpler way to implement this, provided the transport is trusted, is to let Alice generate a random 256-bit identifier, and simply use that as the authentication. A 256-bit identifier will always be sufficiently sparse that it is unguessable (guessing the identifier is precisely the same as guessing an AES-256 key). With that, simply knowing the identifier is sufficient to authenticate a request. This only works if the transport is trusted, but that's the same as any static credential (username+password, token, etc). By a trusted transport, I mean HTTPS with pinned certs, for example, or any similarly encrypted and authenticated transport.

How does the Socialist Millionaire Protocol differ from a simple Challenge-Response like CHAP?

this is a clueluess question, but what does the Socialist Millionaire Protocol, which is typically used in conjunction with OTR-Messaging, that "conventional" Challenge-Response Mechanisms like CHAP can't do?
http://en.wikipedia.org/wiki/Socialist_millionaire
http://en.wikipedia.org/wiki/Challenge-handshake_authentication_protocol
PS: Can someone consider adding the tag "OTR"?
A standard challenge response system works like this:
Bob, the server, sends Alice a random challenge number.
Alice performs a cryptographic operation on the challenge using her secret.
Alice sends the result to Bob.
Bob performs the same operation on the challenge with his secret.
If the result of this calculation matches the response Alice sent him, then Alice must have used the same secret.
The problem with this scheme is that an eavesdropper who gets the challenge and the response can use their supercomputer to bruteforce the secret. They can perform the cryptographic operation repeatedly with many secrets and if they find a secret that produces the observed response they know that that is the shared secret between Alice and Bob.
If the secret is a 128 bit key or a very strong passphrase then bruteforcing the secret will take a very long time and will be impractical but for small secrets like numeric pins or normal passwords bruteforcing is a very real threat.
The socialist millionaire's protocol serves the same purpose but it doesen't reveal any information about the secret. An eavesdropper can't use the messages sent back and forth to learn anything about the secret even if they had an infinitely powerful computer. Even if the attacker pretends to be Bob and can send any messages he wants back to Alice, they still can't get any information about the secret other than whether the guess they made was correct.
In the CHAP protocol the client just proves his identity through showing that he has knowledge of the key. This could also be done with asymmetric cipher. The client just has to encrypt randomly generated challenge and the serve has be able to verify the content.
The Socialist millionaire protocol tells both entities that they have either used to same value or a different value. This could also be used as a login protocol. It will then offer mutual authentication.

Hashing passwords before sending to server

When sending passwords via UTF-8 encoded socket transfer, is it considered to be secure if I hash the password using either MD5 or SHA-1 prior to sending out the data? Keep in mind that I plan to compare the hashed password in a SQL database. I am worried that someone could be able to sniff the hashed password in UTF-8 then decrypt the UTF-8 encoding and could obtain my hashed password which could potentially be used to match the password in my database.
If the client just sends the hashed password, then the hashed password is the "password": a sequence of bytes which the client just needs to show to be authenticated. If the attacker can sniff that then your protocol is doomed.
If the authentication protocol consists in just presenting a piece of secret data (call it a password if you wish), then the exchange should occur within a transport medium which ensures confidentiality (so that the secret data cannot be sniffed) and server authentication (so that an attacker may not mimic a server and convince a client to send him the secret data). This is what you get out of a classic SSL/TLS tunnel (a https:// URL, in a Web context).
If you cannot establish a SSL/TLS tunnel with server authentication (i.e. the server has a certificate which the client can verify), then you may want to resort to an authentication protocol with a challenge: the server sends a sequence of random bytes (the challenge) and the client responds with a hash value computed over the concatenation of the password and the challenge. Do not try this at home! It is very difficult to do it right, especially when the attacker can intercept communications (active attacks).
A more generic answer is password-authenticated key exchange protocols. PAKE combines a cryptographic key agreement protocol (such as Diffie-Hellman) and mutual password authentication between client and server, in a way which defeats both passive and active attackers, even with relatively weak passwords (the attacker cannot get enough data to "try" passwords without interacting with either the client or the server for each guess). Unfortunately, few PAKE algorithms have been standardized beyond mathematical description, and the area is a patent minefield.
Well, if someone can sniff hash - he can fake authorization request and send the hash he already know.
Making up secure system is not easy, you would need to do authorization using asymmetric cryptography with properly signed keys to make it secure.
At least add ~100byte random salt, and use SHA1 - this way it would be way harder to bruteforce.
They could brute-force your passwords if they know the hashing algorithm. The simple (and not perfectly secure) solution is to use a challenge/response instead, the server issues a random string ("nonce") to be hashed along with the password hash. This makes your app invulnerable to the kind of replay attacks you're describing.
For more information, see HTTP's digest access authentication
Hm, if you are talking about 'proper' hashing, that means that it will 'encrypt' your password so it won't be decrypt-able, because hashing is one way function, and to decrypt it - it till take some time, and some kind of great CPU power.
If you are concerned at password sniffers, you can take it to the next level - use PRIVATE/PUBLIC key encryption. Server should send a challenge to the client (public key for encryption), client encrypts with it, and only server know how to decrypt it. For same amount of bits, it offers more protection - ie. more muscle is needed to brute force crack it.
Check this out.
How do you check the password on the database side?
If you store the unsalted hash of the password and just compare it to the input, then the hashed password can be sniffed and reused.
It's exactly as if you were storing the password itself in the database in plain text.
If you are afraid of sniffing, use a challenge-response protocol to authenticate, but in this case the secret will be stored in the database (and will be known to anyone who has access to the database).
Alternatively, you can send a password in plain text over a protected channel (SSL), but you will have to install a certificate which will most probably cost you some money (if you are using an authority from a vendor-provided list, i. e. one your customers' browsers won't complain about)

how does public key cryptography work [duplicate]

This question already has answers here:
Whose key is used to encrypt a HTTPS response?
(3 answers)
Closed 4 years ago.
What I understand about RSA is that Alice can create a public and a private key combination, and then send the public key over to Bob. And then afterward Bob can encrypt something using the public key and Alice will use the public and private key combo to decrypt it.
However, how can Alice encrypt something to be sent over to Bob? How would Bob decrypt it? I ask because I'm curious how when I log onto my banking site, my bank sends me data such as my online statements. How does my browser decrypt that information? I don't have the private key.
Basically, the procedure is:
The client connects to the server and asks for the server's certificate. The certificate contains the public key and information about the server's identity.
Assuming the client is happy with the server's identity, it generates a random number P and encrypts it with the server's public key.
Only the server can decrypt P (with it's private key - not shared with anybody) so when the client sends the encrypted random number to the server, the server decrypts it.
The client and server both use P to generate a symmetric key for use in a symmetric encryption algorithm, safe in the knowledge that only the client and server know the value of P used to generate the key.
Alice will use the public and private key combo to decrypt it
Alice would just decrypt it with her private key.
However, how can Alice encrypt something to be sent over to Bob? How would Bob decrypt it?
Alice would need Bob's public key to send something to him.
Typically, public key encryption is used for authentication, non-repudiation (like signing), and distribution of symmetric keys (which are faster for encrypting/ decrypting long messages).
Simple, you need a key.
SSL/TLS solves this problem by creating a symmetric session key during the connection setup. The public key cryptography is used to establish this session key, which is then used for bi-directional data communication. Read more about TLS
I didn't create this, but someone shared this video with me and it helped the theory make much more sense. As always the devil's in the details (implementation).
http://www.youtube.com/watch?v=YEBfamv-_do
On a general note I struggled to understand Public Key Cryptography for quite a while along with the other elements of PKI such as Digital Signatures and Certificates whilst preparing for Microsoft C# certification.
I came across an explanation in the form of a concise and detailed PDF at cgi.com. I know it's back to good old Alice and Bob! but it really cleared things up for me with its diagrams and notes and also has some thought provoking questions at the end. Definitely recommend it.
Visit http://www.cgi.com/files/white-papers/cgi_whpr_35_pki_e.pdf
However, how can Alice encrypt something to be sent over to Bob? How would Bob decrypt it? I ask because I'm curious how when I log onto my banking site, my bank sends me data such as my online statements. How does my browser decrypt that information? I don't have the private key.
This is where you're wrong; you do have a private key. As part of the handshaking process, each side generates two keys: a public key and a private key. The client sends its public key to the server, who will use it to encrypt all data sent to the client. Likewise, the server generates both keys and sends its public key to the client, which will use it to encrypt all data sent to the server.
In many scenarios, the asymmetric key algorithm is used only to exchange another key, which is for a symmetric algorithm.
In this situation, Alice would use Bob's public key to encrypt the data and Bob would then decrypt it with his private key.
Essentially, a public key encrypts data and a private key decrypts that data. Since every user has both a public and private key, you can securely send data to any other user.
If you connect to the site of your bank it works a lot of cryptographic things. The most important is that you use public key of the bank to send a piece of information to the bank, because in every SSL (https) connection server send to client it's public key packed as a certificate.
Usage of certificate and world wide PKI is important. You want be sure, that if you gives to the bank your bank pin, that on the other side is really your bank and not an other person. This will be solved, because on every computers there are a small number of public keys of well known organisations (like VeriSign) and bank send you not only his server public key, but a certificate. certificate is a message signed by VeriSign for example, which say "this public key is really from the bank XYZ". So because you have public key of VeriSign you can first verify, that server certificate of the bank is correct. So you can be sure, that you communicate really with your bank.