This website uses cookies to ensure you get the best experience. Learn More.
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
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.
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
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; }