-4

I have a scenario where I have to match the password/sensitive information and check for the validation. Now there are two ways here I can come up with.

1) We can compare the password/sensitive field in the encrypted form by fetching the right password from DB which is stored there in encrypted form.

2) Or we can decrypt the passwords first in to the plain text form and then compare them. Now in this scenario there is an extra call to decrypt utility, which sort of an overhead.

I have looked at the "equals()" method of String class which runs in amortized constant time. So if the encrypted string is insanely long string then it will have impact on the performance of the "equals()" method. But here in my case encrypted strings are not so long.

But my main concern is what is the standard generally followed. UPDATE 1:

public static String encrypt(String text, String algo, byte[] bytes)     throws NoSuchPaddingException, NoSuchAlgorithmException,
            IllegalBlockSizeException, BadPaddingException,     InvalidKeyException {
        if (text == null || algo == null || bytes == null) {
            //log properly
            System.out.println("Please provide a valid text, algo or key bytes");
            return null;
        }
       Key key = generateKey(bytes, algo);
        Cipher c = Cipher.getInstance(algo);
         c.init(Cipher.ENCRYPT_MODE, key);
        byte[] envValue = c.doFinal(text.getBytes());
        String encVal2 = new BASE64Encoder().encode(envValue);
        return encVal2;
    }`

Update 2:

 while (i < 300000) {
            String value = KeyValidator.getSystemLicKey(KEY_);
            if (!value.equals(value1))
                System.out.println("--- : false");
            value1 = value;
            i++;
        }
Ankit_ceo2
  • 317
  • 1
  • 6
  • 14
  • The typical way would be to compare both encrypted passwords. With the right algorithm, there are very little chances the strings will be "insanely long". – Mena Jul 07 '16 at 08:52

3 Answers3

2

If you are using hashing algorithm (e.g. SHA1, SHA256, etc.), you need to run the same algorithm on the input and compare the result.

If you are using encryption algorithm (e.g. AES), normally you must to decrypt first. Pay attention that when encrypting something, a good algorithm will use some salt, meaning that you will receive different result when applying the same algorithm on the same string, so decrypting is your only option.

Passwords are normally stored hashed, since you don't need to know the real password, while other sensitive data (e.g. credit card number) is stored encrypted.

And one last point: both hashing and encryption algorithm provide a byte array, not string. So you are supposed to store and compare the byte arrays and not the strings. If you need to store/compare string, you can encode the result using some encoding algorithm, e.g. BASE64.

Update: OWASP have a very good Cheat Sheet about the password storage.

Update 2: Regarding encryption, small example that uses Apache Shiro. Run it, and you can see that no two lines are alike.

    Key key = new AesCipherService().generateNewKey(128);
    AesCipherService cipher = new AesCipherService();
    for (int i = 0; i <20; ++i) {
        System.out.println(Hex.encode(cipher.encrypt("abcde".getBytes(StandardCharsets.UTF_8), key.getEncoded()).getBytes()));
    }
Tarlog
  • 10,024
  • 2
  • 43
  • 67
  • I used the AES implementation in JCA java and tried to encrypt the same string for 300000 times but I got the same string each time. Did I miss anything. @Tarlog – Ankit_ceo2 Jul 07 '16 at 10:18
  • Yes, you missed something. Unless you post your code here, I cannot say what exactly, but you must not get the same result even when encrypting the same text with the same key. – Tarlog Jul 07 '16 at 10:25
  • See Update 2 with AES example. – Tarlog Jul 07 '16 at 10:36
  • public static String getSystemLicKey(String deviceId) { final String algo = "AES"; final byte[] BYTE_KEY = new byte[]{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P'}; try { return AESEncryptExample.encrypt(deviceId, algo, BYTE_KEY); } catch (Exception ex) { //log exception occured return null; } } – Ankit_ceo2 Jul 07 '16 at 12:10
  • ` public static String encrypt(String text, String algo, byte[] bytes) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { if (text == null || algo == null || bytes == null) { //log properly System.out.println("Please provide a valid text, algo or key bytes"); ` – Ankit_ceo2 Jul 07 '16 at 12:17
  • ` return null; } Key key = generateKey(bytes, algo); Cipher c = Cipher.getInstance(algo); c.init(Cipher.ENCRYPT_MODE, key); byte[] envValue = c.doFinal(text.getBytes()); String encVal2 = new BASE64Encoder().encode(envValue); return encVal2; }` – Ankit_ceo2 Jul 07 '16 at 12:17
  • Please update your question. The code in comments is not readable. – Tarlog Jul 07 '16 at 12:20
  • Hi @Tarlog I have updated the code. please have a look. – Ankit_ceo2 Jul 07 '16 at 12:27
  • Your code is still pretty much unreadable. What is KeyValidator? Where do you call to encrypt in your loop? – Tarlog Jul 07 '16 at 12:35
  • I am calling getSystemLicKey method of KeyValidator class which is just calling the encrypt method with two additional parameters called algo which is "AES" and byte array of some 128 key. – Ankit_ceo2 Jul 07 '16 at 12:47
  • You are using the default of JDK operational mode called ECB. It's more secure to use CBC with an initialization vector. See https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation – Tarlog Jul 07 '16 at 13:38
  • Never encrypt passwords, use a one-way function that includes a work factor such as password_hash, PBKDF2, Bcrypt, etc. – zaph Jul 08 '16 at 12:32
  • @zaph Consider that you need to store password for another system. If you store hash, you won't be able to use it. Just pay attention that the question was not only about passwords, but about sensitive data. – Tarlog Jul 08 '16 at 16:58
  • @Tarlog pay attention that the question, it was about "match the password/sensitive information and check for the validation", not storing password for another system. Also pay attention to the comment: "Never encrypt **passwords**". What is the problem? – zaph Jul 08 '16 at 17:15
  • 1
    this answer provides much weaker security than what is otherwise easily achievable using best practices. – dandavis Jul 10 '16 at 04:29
0

NEVER ENCRYPT YOUR PASSWORD ALWAYS HASH IT!!! Reference: https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet (Rule - Store a one-way and salted value of passwords)

For shiro to use salt and hash

check How to stock and use a shiro's salt from database for storing salt and password in db.

Community
  • 1
  • 1
Dev
  • 6,628
  • 2
  • 25
  • 34
0

Do not encrypt password. Iterate over an HMAC with a random salt for about a 100ms duration (the salt needs to be saved with the hash). Use functions such as password_hash, PBKDF2, Bcrypt and similar functions. The point is to make the attacker spend a lot of time finding passwords by brute force.

See OWASP (Open Web Application Security Project) Password Storage Cheat Sheet.

See How to securely hash passwords, The Theory on Security Stackexchange.

To see how hashed passwords are attacked see:
Password list at SecLists.
Infosec password-cracking-tools
Arstechnica How I became a password cracker.

Community
  • 1
  • 1
zaph
  • 111,848
  • 21
  • 189
  • 228
  • with "an HMAC", which messages and keys are you referring to? i'm confused because a password is just one piece, and hmac is for authenticating encrypted messages with certain keys, or am i missing something? (judging from rep, i'm missing something...) – dandavis Jul 10 '16 at 04:31
  • Two things are supplied to the HMAC, the password and a random salt. The random salt is stored along with the hashed password, it does not need to be secret. The purpose of the salt, which is essentially different for each password, is so that if more than one user has the same password the hashes will be different. If the hashes were not different discovering one user's password would also disclose all other users with the same password. The salt also prevents use of [rainbow tables](https://en.wikipedia.org/wiki/Rainbow_table). – zaph Jul 10 '16 at 13:11
  • @dandavis While an HMAC is used for authenticating encrypted messages that is not it's only usage, many cryptographic functions have multiple uses , uses other than the original intent when designed, PBKDF2 is another example that is well fitted for password security. When using a salt just concatenation it to the password and hashing is not secure, an HMAC avoids this insecurity by using two hash operations. See [HAMC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code). – zaph Jul 10 '16 at 13:20
  • thanks very much for the info; makes sense. I kept seeing lots of folks talk about HMAC in a context i thought didn't make sense, since most of the readings out there only talk about how it's a way to authenticate a message and key w/o revealing the key. – dandavis Jul 10 '16 at 21:34