Forums

Home » Liferay Portal » English » 3. Development

Combination View Flat View Tree View
Threads [ Previous | Next ]
toggle
Mansi Mistry
Liferay authentication and Password encryption
January 6, 2016 8:15 AM
Answer

Mansi Mistry

Rank: Junior Member

Posts: 31

Join Date: September 30, 2014

Recent Posts

Hi,

We are trying to emulate the password encryption algorithm used by Liferay, but we are unable to do so. We need to provide authentication of user against the Liferay credentials saved in LIferay db.

We are trying to use CAS for authorization and need an authentication source which in our case is Liferay. We want to write custom code that authenticates using the username/password stored in Liferay DB through a JDBC call.

Currently, when we try to emulate the password encryption and try to match it against the existing entry in DB, but its a failure. The encrypted passwords do not match. What is correct way to achieve this? We tried to dig into the Liferay code and understand the steps followed to achieve encryption but seems we might have missed out on something.

Our end goal is to use the Liferay authentication mechanism.

Any help or pointers on this would be helpful. Thanks in advance!
Olaf Kock
RE: Liferay authentication and Password encryption
January 6, 2016 12:59 PM
Answer

Olaf Kock

LIFERAY STAFF

Rank: Liferay Legend

Posts: 4352

Join Date: September 23, 2008

Recent Posts

  • Which version?
  • Can you show the code that you wrote? Which code did you base it on?
  • Did you configure the password encryption/hashing algorithm to something other than the default?
  • Did you honor the "legacy" algorithm? There might be two different hash algorithms in use at the same time if you upgraded from an older version that used another password hashing algorithm
Mansi Mistry
RE: Liferay authentication and Password encryption
January 7, 2016 4:42 AM
Answer

Mansi Mistry

Rank: Junior Member

Posts: 31

Join Date: September 30, 2014

Recent Posts

Olaf Kock:
  • Which version?
  • Can you show the code that you wrote? Which code did you base it on?
  • Did you configure the password encryption/hashing algorithm to something other than the default?
  • Did you honor the "legacy" algorithm? There might be two different hash algorithms in use at the same time if you upgraded from an older version that used another password hashing algorithm




Which version?
WE are using liferay_6.2.x_CE version

Can you show the code that you wrote? Which code did you base it on?
We are using liferay '6.2.1' jar files.
- util-java-6.2.1.jar
- portal-impl-6.2.1.jar
- portal-service-6.2.1.jar
We are using com.liferay.portal.security.pwd.PBKDF2PasswordEncryptor class code to encrypt our password
Method_Name = doEncrypt(String algorithm, String plainTextPassword,String encryptedPassword)
Did you configure the password encryption/hashing algorithm to something other than the default?
We are using default algorithm "PBKDF2WITHHMACSHA1/160/128000" in liferay. We have not customized any encryption/hashing algo.

Did you honor the "legacy" algorithm? There might be two different hash algorithms in use at the same time if you upgraded from an older version that used another password hashing algorithm
There is no upgrade scenario.


Problem we are facing:

We want to use CAS as authentication and lifearay db as auth db for CAS. We have configured CAS to use liferay DB and customized encryption for password. Custom encryption is written using liferay encryption class (PBKDF2PasswordEncryptor) mentioned above.

  1
  2package com.test;
  3
  4import java.nio.ByteBuffer;
  5import java.util.regex.Matcher;
  6import java.util.regex.Pattern;
  7
  8import javax.crypto.SecretKey;
  9import javax.crypto.SecretKeyFactory;
 10import javax.crypto.spec.PBEKeySpec;
 11
 12import com.liferay.portal.PwdEncryptorException;
 13import com.liferay.portal.kernel.io.BigEndianCodec;
 14import com.liferay.portal.kernel.util.Base64;
 15import com.liferay.portal.kernel.util.CharPool;
 16import com.liferay.portal.kernel.util.GetterUtil;
 17import com.liferay.portal.kernel.util.Validator;
 18
 19public class LiferayPasswordUtil {
 20      private static String algorithm = "PBKDF2WITHHMACSHA1/160/128000";
 21      public String doEncrypt(String password) throws Exception {
 22            
 23            return this.doEncrypt(algorithm, password, null);
 24        }
 25      public String[] getSupportedAlgorithmTypes() {
 26         
 27            return new String[] { "PBKDF2WithHmacSHA1/160/128000" };
 28        }
 29
 30        protected  String doEncrypt(String algorithm, String plainTextPassword,
 31                String encryptedPassword) throws PwdEncryptorException {
 32
 33            try {
 34                PBKDF2EncryptionConfiguration pbkdf2EncryptionConfiguration = new PBKDF2EncryptionConfiguration();
 35
 36                pbkdf2EncryptionConfiguration.configure(algorithm,
 37                        encryptedPassword);
 38
 39                byte[] saltBytes = pbkdf2EncryptionConfiguration.getSaltBytes();
 40
 41                PBEKeySpec pbeKeySpec = new PBEKeySpec(
 42                        plainTextPassword.toCharArray(), saltBytes,
 43                        pbkdf2EncryptionConfiguration.getRounds(),
 44                        pbkdf2EncryptionConfiguration.getKeySize());
 45
 46                String algorithmName = algorithm;
 47
 48                int index = algorithm.indexOf(CharPool.SLASH);
 49
 50                if (index > -1) {
 51                    algorithmName = algorithm.substring(0, index);
 52                }
 53
 54                SecretKeyFactory secretKeyFactory = SecretKeyFactory
 55                        .getInstance(algorithmName);
 56
 57                SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);
 58
 59                byte[] secretKeyBytes = secretKey.getEncoded();
 60
 61                ByteBuffer byteBuffer = ByteBuffer.allocate(2 * 4
 62                        + saltBytes.length + secretKeyBytes.length);
 63
 64                byteBuffer.putInt(pbkdf2EncryptionConfiguration.getKeySize());
 65                byteBuffer.putInt(pbkdf2EncryptionConfiguration.getRounds());
 66                byteBuffer.put(saltBytes);
 67                byteBuffer.put(secretKeyBytes);
 68                System.out.println("++++++++++++++++++ encoded ++++++++" + Base64.encode(byteBuffer.array()));
 69                return Base64.encode(byteBuffer.array());
 70            }
 71            catch (Exception e) {
 72                throw new PwdEncryptorException(e.getMessage(), e);
 73            }
 74        }
 75
 76        private static final int _KEY_SIZE = 160;
 77
 78        private static final int _ROUNDS = 128000;
 79
 80        private static final int _SALT_BYTES_LENGTH = 8;
 81
 82        private static Pattern _pattern = Pattern
 83                .compile("^.*/?([0-9]+)?/([0-9]+)$");
 84
 85        private class PBKDF2EncryptionConfiguration {
 86
 87            public void configure(String algorithm, String encryptedPassword)
 88                    throws PwdEncryptorException {
 89
 90                if (Validator.isNull(encryptedPassword)) {
 91                    Matcher matcher = _pattern.matcher(algorithm);
 92
 93                    if (matcher.matches()) {
 94                        _keySize = GetterUtil.getInteger(matcher.group(1),
 95                                _KEY_SIZE);
 96
 97                        _rounds = GetterUtil.getInteger(matcher.group(2), _ROUNDS);
 98                    }
 99
100                    BigEndianCodec.putLong(_saltBytes, 0,
101                            SecureRandomUtil.nextLong());
102                } else {
103                    byte[] bytes = new byte[16];
104
105                    try {
106                        byte[] encryptedPasswordBytes = Base64
107                                .decode(encryptedPassword);
108
109                        System.arraycopy(encryptedPasswordBytes, 0, bytes, 0,
110                                bytes.length);
111                    }
112                    catch (Exception e) {
113                        throw new PwdEncryptorException(
114                                "Unable to extract salt from encrypted password "
115                                        + e.getMessage(), e);
116                    }
117
118                    ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
119
120                    _keySize = byteBuffer.getInt();
121                    _rounds = byteBuffer.getInt();
122
123                    byteBuffer.get(_saltBytes);
124                }
125            }
126
127            public int getKeySize() {
128                return _keySize;
129            }
130
131            public int getRounds() {
132                return _rounds;
133            }
134
135            public byte[] getSaltBytes() {
136                return _saltBytes;
137            }
138
139            private int _keySize = _KEY_SIZE;
140            private int _rounds = _ROUNDS;
141            private byte[] _saltBytes = new byte[_SALT_BYTES_LENGTH];
142
143        }
144       
145}



We are passing plane text and algorithm to doEncrypt method and previous encrypted password as null. Method returns encrypted password but it does not match encrypted/hashed password in db.
Is there any way to get this encrypted pass same as db?

We debugged the deployed liferay code to check its authentication. Algorithm we are using is same as liferay. We are not able to get exact salt for encryption.
Passing null value for encryptedPassword parameter in doEncrypt method leads to random salt generation (which ideally happens when the encryption happens for the first time). But in our case we require the same salt value that was generated for the first time to perform encryption/hashing.
Is there any other way to do the encryption/hashing just as Liferay default?
Olaf Kock
RE: Liferay authentication and Password encryption
January 7, 2016 9:51 AM
Answer

Olaf Kock

LIFERAY STAFF

Rank: Liferay Legend

Posts: 4352

Join Date: September 23, 2008

Recent Posts

How about you debug a login procedure in Liferay and in your CAS implementation? Or just log what goes in&out in the various methods.
It might be the configuration with proper salt that's missing.
Jack Bakker
RE: Liferay authentication and Password encryption
January 7, 2016 2:02 PM
Answer

Jack Bakker

Rank: Liferay Master

Posts: 942

Join Date: January 3, 2010

Recent Posts

Mansi Mistry:

We want to use CAS as authentication and lifearay db as auth db for CAS. We have configured CAS to use liferay DB and customized encryption for password


I have a Liferay v6.2 which uses first CAS against OpenLDAP and if that fails looks to Liferay user_ in db itself (for accounts that might be only in Liferay but not in LDAP)

We chose to go with SHA adding to portal-ext.properties. In my case an upgrade was involved so there were other conveniences in this setting.

passwords.encryption.algorithm.legacy=SHA

but mine doesn't sound like exactly same use case is same as yours where you seem to require PBKDF2

Tomas might have some useful ideas here:
https://www.liferay.com/community/forums/-/message_boards/message/37036189?_19_threadView=tree
Piyush Singh
RE: Liferay authentication and Password encryption
January 30, 2016 7:23 PM
Answer

Piyush Singh

Rank: New Member

Posts: 15

Join Date: February 10, 2014

Recent Posts

Hi Mansi,

I am also facing the same problem. Did you manage to solve it?

Regards,
Piyush SIngh
Mansi Mistry
RE: Liferay authentication and Password encryption
January 31, 2016 9:35 PM
Answer

Mansi Mistry

Rank: Junior Member

Posts: 31

Join Date: September 30, 2014

Recent Posts

Not really. From what I understand we need to somehow query the Liferay database the hash and obtain the salt value. Only once we have the salt value with us we can get the same hash value and the passwords can be matched.
Tomas Polesovsky
RE: Liferay authentication and Password encryption
April 25, 2016 1:54 AM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

Hi guys,

if you want to check the password, you need to provide:
1, plain-text password provided by the user
2, existing hash of the password

The implementation needs data from the hash to correctly initialize PBEKeySpec, like key size, number of iterations and the salt. Only then it can create hash of the password the same way and come to the same result.
lee zach
RE: Liferay authentication and Password encryption
November 21, 2016 6:09 AM
Answer

lee zach

Rank: New Member

Posts: 3

Join Date: July 18, 2015

Recent Posts

excellent! fixed my problem!!

Participate in the State of Liferay Community 2017. Help the community and even win some prizes!