18

I have implemented an authentication system which works like this:

  1. Upon successful login, the server takes the username of client and encrypts it with AES-256.

  2. This ciphertext is stored in the client's browser and when the client wants to do something which requires login, this ciphertext is sent to the server. The server decrypts the ciphertext and obtains the username of the client who is logged in.

An attacker cannot breach a client's account because he/she doesn't know the encryption key, so it doesn't matter if the attacker knows the username. However, I'm worried if client's browser is exposed, the attacker will access both the ciphertext and plain text (username). Does this allow the attacker to "calculate" the encryption key given that both the ciphertext and plaintext are known? Because that key is used for all clients, so if it's exposed the entire system is ruined.

12
  • 6
    Not an answer... but I feel a bit weird here. Perhaps I miss some details. Why do we need to encrypt username? Why not just send the username plain-text? – Hoàng Long Apr 15 at 3:55
  • 5
    Possible duplicate of: Does symmetric encryption provide data integrity?. Known plaintext-ciphertext pairs don't help you get the key, so they don't help you decrypt other ciphertexts; but they often do make it possible to encrypt other plaintexts, which would completely break your scheme. You need integrity, not encryption. – ruakh Apr 15 at 7:11
  • 7
    Normally a JWT is a signed token that contains username in plaintext. It is used worldwide and accepted as best practice. Why reinveting the wheel then? – usr-local-ΕΨΗΕΛΩΝ Apr 15 at 8:58
  • 3
    Why not use a randomly-generated session key, like is commonplace? Are you using deterministic encryption? In other words, is the encrypted username always the same ciphertext? If so, that would be very questionable. – marcelm Apr 15 at 19:34
  • 6
    I have implemented authentication system This is nearly always a bad sign. I have been programming for 30 years, and I avoid writing security code as much as possible because it's always better to use tested, verified libraries when available. – chrylis -cautiouslyoptimistic- Apr 16 at 16:21
25

In answer to your main question, AES256 is secure as far as we know into the foreseeable future. However your authentication scheme has several drawbacks.

First, if any request where the token is sent is compromised, or if a the user installs a malicious addon that can grab the encrypted user name from their browser, that account is forever unusable. You are essentially creating a token to use for authentication that cannot ever be changed and that is a 1:1 relationship with the user name. The only way to deny access if it is compromised is to shut down the account and force the user to create a new account with a different username.

A much better way would be to generate a random token when the user authenticates and store that in the database, or generate a random value and encrypt that as the token. Then if the account is compromised or if the user wishes to 'log out', you can remove that token and generate a new one.

If your encryption key is ever compromised or if it is ever cracked somehow, the attacker can do anything as any user in your system. With a random token based approach, they would have to know the random part used to generate the token for each user. The attacker would have to have access to your database and your encryption key.

2
  • 1
    This is a good answer. One solution could be to add login date to username string and encrypt both. If date is too old token could be set to expired. – Mr. Engineer Apr 15 at 14:00
  • 8
    @Mr.Engineer That solution isn't very good either (though it's better); there aren't all that many dates to try. – wizzwizz4 Apr 15 at 14:53
24

No. The attacker cannot obtain the encryption key from the plaintext and the encrypted text, because AES is resistant to known-plaintext attacks. See details in the answer on Crypto SE.

I'd suggest you to review your design. Making user name secret can lead to many problems. For instance, if user needs to report a problem, how can user tell user name if it is secret? Of if an administrator needs to change user permissions, how can the responsible person tell administrator what user needs to be changed, if the user name is secret? And so on. I'd suggest not to encrypt the user name.

So actually we have an XY problem here. Actually, an authentication token should be used to know who the user actually is. In such case encryption of user name is not needed and thus the question about AES and known-plaintext attack is not needed.

14
  • 19
    Why you would use the user's username as the session identifier is beyond me. You should be using revoke-able tokens and/or standard session ID's. These need not be encrypted, and you don't have to jump through a bunch of hoops with usernames. @Mr.Engineer – Florian Humblot Apr 15 at 6:55
  • 2
    @Mr.Engineer: To prevent spoofing an authentication token should be used. – mentallurg Apr 15 at 7:04
  • 9
    @Mr.Engineer Yes, indeed. Or you could use JWT, which is a stateless design. – MechMK1 Apr 15 at 8:37
  • 10
    @Mr.Engineer "I have tried with JWT Tokens but I couldn't read the username from token" You didn't try hard enough, the token does contain the name of the authorized party. – Ben Voigt Apr 15 at 15:40
  • 6
    @Mr.Engineer JWT's payload is human readable JSON encoded (not encrypted) in base64. You can paste any JWT token into jwt.io to see the payload. In general, it is recommended that a JWT token include a parameter called "sub" that is supposed to be the user identifier. This can be a user id (integer), user's email or username. In your case you should make it the username. What secures JWT is the signature which is a similar idea to your idea above but proven and designed by crypto experts (not just the algorithm but the entire flow) – slebetman Apr 16 at 5:36
10

Would be bad form to ask "Why?"

There are plenty of free, open source, battle-tested authentication systems in place.

Unless you are expert in crypto engineering (and the fact that we are here shows otherwise), please don't invent your own system.

It's great messing around with code just to teach yourself, but don't take it further.

6
  • 3
    WHile the other answers address the technical details, this is the practical answer. – sleske Apr 16 at 9:17
  • My design makes it easier to obtain the username of those who are logged in and also makes it impossible to forge the identifier, so I wouldn't call it a bad idea, but it's weakness is that if client is exposed, revoking would require to change the encryption key and that would log out all users. Btw, what do you mean by "the fact that we are here shows otherwise"? I think this is the place where experts meet :) – Mr. Engineer Apr 16 at 10:39
  • 8
    It's not. It's the place where amateurs who think they are experts meet, with the token actual expert chiming in from time to time to dole out useful advice like "don't try to implement your own authentication system." – mindcrime Apr 16 at 15:09
  • 2
    This answer would be better if it mentioned a couple of the existing open-source authentication systems -- such as, for example, Flask-Security ( pythonhosted.org/Flask-Security ). – David Cary Apr 16 at 23:13
  • 1
    Basically, this entire thing is saying "Googling 'How to get username from JWT' is too much hassle, and using the language's session system is not hip enough, lets invent my own system" auth0.com/docs/tokens/json-web-tokens/json-web-token-structure – Jan Hertsens Apr 17 at 15:14
8

AES is secure against Known-Plaintext-Attacks (KPA) where an attacker has access to both plaintext and ciphertext. AES withstands attacks for more than 20 years and AES-256 is the golden standard that even AES-256 can beat the Quantum attack of Grover's optimal Search Algorithm. Even AES-128 is secure in the foreseeable future - except the multi-target attack..

Your authentication scheme is insecure as you noticed. You should either use

  • standard password hashing with Scrypt, PBKDF2, or Argon2 with 128-bit random salt per user and users choose dicewire passwords for good strength against password searches.
  • Or, use PAKE if that fits you.
9
  • The purpose of encryption here is to prevent attacker from forging the identifier which is stored in client's browser. Username is a good identifier but it's not secret so encryption is vital here. Can you point out where is the weakness if known-plaintext-attacks do not work? – Mr. Engineer Apr 15 at 6:15
  • To clarify: attacker cannot generate the ciphertext because he doesn't know the key so he cannot forge the identifier. This is how it's supposed to work :) – Mr. Engineer Apr 15 at 6:25
  • 1
    What kind of attacker we are talking about exactly? If the attacker installed a key logger then they can learn everything the user typed. – kelalaka Apr 15 at 6:59
  • 1
    @JonBentley Server needs to know which user is logged in and for that we need to set session identifier to his browser. Username is not secret, but ciphertext is. But as Jason Goemaat pointed out, this system has another weakness which is that those identifiers cannot be revoked if they get exposed. – Mr. Engineer Apr 15 at 14:05
  • 1
    @Mr.Engineer I think you want signing, not encryption. Like with RSA or HMAC – Ray Wu Apr 16 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.