1

I'm trying to do a login method that keeps the client password secure and encrypted in my server.

The library I'm using from Angular, is https://github.com/middleout/angular-cryptography

The idea is, to follow these steps:

  1. I set a salt in my module.config:

    app.config(['$cryptoProvider', function($cryptoProvider){
        $cryptoProvider.setCryptographyKey('thisismysalt');
    }]);
    
  2. I encrypt the password with itself:

    user.pw = $crypto.encrypt(user.pw, user.pw);
    
  3. If I'm registering an user, I re-encrypt the password with itself (repeat step 2) and save it in the DB. If I'm logging, I just send the result from the last step, to the server.

  4. When you decypher the double-encrypted string with the single-encrypted one, you get the single encrypted string again. So if your password was correct, you just compare the result with the single-encrypted string, and you validate the user.


Ok, this method should work (I already did it in Node some time ago), works great with SSL to protect user's passwords even in your server!

But I can't find any library or snippet in Java that can do it. I tried many of them, but they are hard to understand and when I adapt them to my procedure, they just won't work. I tried the following method:

static String IV = "AAAAAAAAAAAAAAAA";
static String plaintext = "test text 123\0\0\0"; /*Note null padding*/
static String encryptionKey = "0123456789abcdef";

public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    return new String(cipher.doFinal(cipherText),"UTF-8");
}

I passed it as first argument, the double-encrypted password from the DB, and as second argument, the single-encrypted password from the frontend:

java.security.InvalidKeyException: Invalid AES key length: 44 bytes

Am I doing something wrong? Should I use a different algorithm?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Zerok
  • 227
  • 4
  • 19

1 Answers1

1

middleout/angular-cryptography uses CryptoJS 3.1.2 under the hood with the least effort possible.

So

return $crypto.encrypt(plaintext, password);

is the same as

$cryptoProvider.setCryptographyKey(password); 
return $crypto.encrypt(plaintext, password);

and the same as

return CryptoJS.AES.encrypt(plaintext, password).toString();

I describe in my answer here how to do the same thing in Java.


If you're using SSL/TLS, there is not much benefit to doing this encryption additionally. The password is already sent in an encrypted way over the internet. Even worse, since the password must be available at the server side, you must store the password in cleartext. That's not how it is done.

You need to use hashing instead with some strong ones being PBKDF2, bcrypt, scrypt and Argon2. Since hash functions are one-way function, you won't be able to "decrypt" the hashes. In order to authenticate your user, you can run the password through the hash function again in order to compare with the hash that is stored in the database. Since you're already using SSL/TLS, the password is already secured during transmission. See more: How to securely hash passwords?

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Don't you think that saving an encrypted password in the server, allows for better security for the user? I mean, you can perfectly verify your password encrypting it in the client side, and comparing it with the same one stored in the server, so the user can do everything, but gets a new advantage: if the DB gets hacked, his real password won't be leaked. Why you say this isn't a good practice? – Zerok Sep 22 '16 at 07:03
  • No, encryption is not a valid solution for passwords which are directly used for authentication. The code in your question encrypts the password with the password on the client side. The problem is that you need to have the cleartext password on the server to do anything with this strange way of encryption because you've used the password itself to encrypt the password, so you need the password to decrypt the encrypted password. This is going nowhere. – Artjom B. Sep 22 '16 at 19:27
  • You really should use hashing. If you don't want to sent the password directly over TLS, you can of course hash (e.g. PBKDF2) the password on the client, sent the hash to the server, let the server hash it again and store it/compare it to the stored hash. This would be much better than whatever you're doing here. – Artjom B. Sep 22 '16 at 19:29
  • Thank you for your help! Anyways, my method was: when registering, store the password encrypted with itself, and you repeat the process (so the password is double-encrypted with itself). Later on, when you log in, you send the password encrypted again with itself to the server, so the server can try to decrypt the double-encrypted with the simple-encrypted, and then, check if the simple-encrypted and the result, are equal. It worked for me once in a little project. What would be the benefits of hashing, against this? Thank you! – Zerok Sep 29 '16 at 07:30
  • I see. So, yes this sort of double encryption would work, but a block cipher is usually not used in this way, so there might be additional vulnerabilities there that nobody is looking for. It's better to use hashing in this case, because many people have looked at it and haven't found something seriously wrong with it. – Artjom B. Sep 29 '16 at 20:46
  • Well, I think that a good point of using the double-encryption method is that the password won't be recognizable if someone dumps the DB, which protects user's privacy, don't you think? I think that hashing doesn't have this feature (although I may be wrong!). – Zerok Oct 03 '16 at 11:28
  • I don't know what you mean by "recognizable", but hashing is supposed to produce output that is indistinguishable from random noise. Block ciphers actually have the same property. – Artjom B. Oct 04 '16 at 18:42