Client Side Password Encryption 

Client Side Password Encryption RSA

By default Liferay does not encrypt the password at client side  as with SSL already Data will be encrypted but some security audit demand for password to be encrypted before submission . So we will be seeing how to perform client side encryption of password  in liferay.  I will  encrypting  with RSA Algorithm which uses public and private key .Public Key will be used for encryption at client side and private key will be used for decryption at server side. we need to follow below steps

1. Generating the Private and Public Key

2. Encrypting the Password using Public Key

3. Decrypting the Password using Private Key

1. Generating the Private and Public Key

We will be overriding MVC Render Command of Login Module (Refer) and generating the KeyPair for Public and Private Key

    @Override
    public String render(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException {
        ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
        if (!themeDisplay.isSignedIn()) {
            KeyPair keyPair = null;
            if (Validator.isNull(renderRequest.getPortletSession().getAttribute("keyPair"))) {
                _log.info("Creating Fresh Key pair");
                KeyPairGenerator keyPairGenerator = null;
                try {
                    keyPairGenerator = KeyPairGenerator.getInstance("RSA");
                    keyPairGenerator.initialize(1024);
                } catch (NoSuchAlgorithmException e) {
                    _log.error(e.getMessage());
                }
                keyPair = keyPairGenerator.generateKeyPair();
                renderRequest.getPortletSession().setAttribute("keyPair", keyPair);
            } else {
                keyPair = (KeyPair) renderRequest.getPortletSession().getAttribute("keyPair");
            }
            String publicKey = Base64.encode(keyPair.getPublic().getEncoded());
            renderRequest.setAttribute("publicKey", publicKey);
        }
        return mvcRenderCommand.render(renderRequest, renderResponse);
    }

As in above code we have generated Public Key required at client side for encryption.

2. Encrypting the Password using Public Key

We will be  encrypting the password in login.jsp (Hook to Login Module Refer ) before submission  using the public key generator in previous step

if (form) {
                form.addEventListener(
                    'submit',
                    function(event) {
                        
                         var password = form.querySelector('#<portlet:namespace />password');
                            if(password) {
                                var passwordVal = password.getAttribute('value');
                                var encrypt = new JSEncrypt();
                                encrypt.setPublicKey('${publicKey}');
                                var encrypted = encrypt.encrypt(passwordVal);
                               $('#<portlet:namespace />password').val(encrypted);
                            }
                        
                        
                        <c:if test="<%= Validator.isNotNull(redirect) %>">
                            var redirect = form.querySelector('#<portlet:namespace />redirect');

                            if (redirect) {
                                var redirectVal = redirect.getAttribute('value');

                                redirect.setAttribute('value', redirectVal + window.location.hash);
                            }
                        </c:if>

                        submitForm(form);
                    }
                );

In the above highlighted code encryption of password is happening , here we are using  http://travistidwell.com/jsencrypt/ for encryption , there are many other  JavaScript Libraries available for encryption 

https://gist.github.com/jo/8619441

https://github.com/digitalbazaar/forge#rsa

3. Decrypting the Password using Private Key

We will be decrypting the password using the Private Key which we have saved in Session in first step, 

We will be overriding MVC ActionCommand of Login Module (Refer)   and add the below highlighted code

@Override
    protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse) throws Exception {
        
        DynamicActionRequest dynamicActionRequest = new DynamicActionRequest(actionRequest);
        dynamicActionRequest.setParameter("password", decrypt(actionRequest, ParamUtil.getString(actionRequest, "password")));
        mvcActionCommand.processAction(dynamicActionRequest, actionResponse);
    }

    private String  decrypt(PortletRequest portletRequest, String value) {        
        KeyPair keyPair = (KeyPair) portletRequest.getPortletSession().getAttribute("keyPair");

        String decryptedValue  = StringPool.BLANK;
        Cipher cipher = null;
         try {
             cipher = Cipher.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            _log.error(e.getMessage());
        } catch (NoSuchPaddingException e) {
            _log.error(e.getMessage());
        }        
        try {
            cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
        } catch (InvalidKeyException e) {
            _log.error(e.getMessage());
        }
        try {
            decryptedValue = new String(cipher.doFinal(Base64.decode(value)));
        } catch (IllegalBlockSizeException e) {
            _log.error(e.getMessage());
        } catch (BadPaddingException e) {
            _log.error(e.getMessage());
        }
             return decryptedValue;
    }