Shah Harsh
Shah Harsh

Reputation: 1

Encrypt and decrypt passwords between browser and Spring MVC backend

I want to securely transmit and handle user passwords between the browser and a Spring MVC backend. The password is encrypted on the client side and decrypted on the server side before validation

Frontend code:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

<script>
  function encryptPassword(password) {
    const encryptedPassword = CryptoJS.AES.encrypt(password, "SecretKey123").toString();
    return encryptedPassword;
  }

  document.getElementById("loginForm").onsubmit = function (e) {
    e.preventDefault();
    const passwordField = document.getElementById("password");
    passwordField.value = encryptPassword(passwordField.value);
    this.submit();
  };
</script>

<form id="loginForm" method="POST" action="/login">
  <input type="text" name="username" required />
  <input type="password" id="password" name="password" required />
  <button type="submit">Login</button>
</form>

Backend code:

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

@Controller
@RequestMapping("/login")
public class LoginController {
    private static final String SECRET_KEY = "SecretKey123"; // Must be 16 chars for AES

    @PostMapping
    public String login(@RequestParam String username, @RequestParam String password, Model model) {
        try {
            String decryptedPassword = decrypt(password);
            // Validate username and decryptedPassword
            // Perform authentication logic
        } catch (Exception e) {
            model.addAttribute("error", "Invalid encryption");
            return "login";
        }
        return "home";
    }

    private String decrypt(String encryptedPassword) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decodedBytes = Base64.getDecoder().decode(encryptedPassword);
        byte[] original = cipher.doFinal(decodedBytes);
        return new String(original);
    }
}

I am not sure if my implementation is secure or if there are better practices for encryption and decryption in this use case.

Upvotes: -1

Views: 83

Answers (1)

Ahmad Alfawwaz Timehin
Ahmad Alfawwaz Timehin

Reputation: 303

Like @luk2302 commented, you should think carefully about why you would want to do this.

In most cases, it is good enough to rely on the security provided by HTTPS. It keeps your application simple and provides a high level of security. A few things to note for the server side:

  • Do not serve application traffic over HTTP - it should all be redirected to HTTPS.
  • Use HSTS to ensure browsers force HTTPS.
  • Do not store user passwords in plain text or encrypted, hash the password and compare the hash.

In cases where you anticipate greater risk, such as cases where users are more vulnerable to social engineering attacks, you should implement an additional layer of protection that significantly increases the complexity of an MitM attack. If a user installs a malicious certificate and sends traffic through a malicious proxy, an attacker could steal the user's credentials via an MitM attack. In such cases, implementing additional encryption may be necessary.

For such situations, negotiating a secure key exchange process and using public key cryptography over HTTPS should solve your needs. You can research ECDH for more information.

Upvotes: 1

Related Questions