Reputation: 1
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
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:
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