What is password hashing?
Password hashing is a one-way cryptographic process of converting passwords into unreadable format(a hash) of fixed length and is irreversible, which makes it ideal for password security. The system stores a hashed password in the database rather than the plain password you type, making it almost impossible to retrieve the plain text password even if someone obtains the hash.
How Password Hashing Works?
- When a user enters a password while registering, the system applies a hashing algorithm which produces a unique hash value for every password.
- The system then stores this hash value in the database, rather than the actual password that the user enters.
- When the user logs in again using his password, the system applies the hashing algorithm again to create the hash.
- Now, the system compares this hash with the hash stored in the database; if they match, the system grants access; otherwise, it denies access.
You may be wondering, what if two people have the same password? Then Salting comes into picture, Hashing on its own does not produce a unique hash, a unique code(called salt) is added to every hashed value. This ensures that even if two users choose the same password, their hashed values will be different.
Why is password hashing important?
- Systems do not store passwords as plain text; they store them in the form of a hash. As storing plain text passwords is a major security risk.
- Even if hackers steal the hash, they cannot easily reverse it to get the original password.
- It is computationally very expensive to crack the original password from its hash.
What is Bcrypt?
Bcrypt is a password hashing algorithm used in modern applications to securely store user passwords. It has built-in salting to prevent cyber attacks, such as brute-force attacks.
- Built in Salting: Each password is hashed with a unique random salt, ensuring even identical passwords produce different hashes.
- Slow by Design – Bcrypt is computationally expensive, which makes brute-force attacks much harder.
Example using Bcrypt in Java (Spring Boot)
Adding Dependencies
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Configure Password Encoding
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // 12 is the cost factor
}
}
User Service
import com.example.assignment2.entity.Users;
import com.example.assignment2.repository.UserRepository;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public Users registerUser(String name, String email, String rawPassword) {
Users user = new Users();
user.setName(name);
user.setEmail(email);
// Hash password before saving
String hashedPassword = passwordEncoder.encode(rawPassword);
user.setPassword(hashedPassword);
return userRepository.save(user);
}
public boolean authenticate(String name, String rawPassword) {
Users user = userRepository.findByName(name);
if (user == null) return false;
// Compare entered password with stored Bcrypt hash
return passwordEncoder.matches(rawPassword, user.getPassword());
}
}
Controller
import com.example.assignment2.service.UserService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/auth")
public class AuthController {
private final UserService userService;
public AuthController(UserService userService) {
this.userService = userService;
}
@PostMapping("/register")
public ResponseEntity<String> register(@RequestParam String name, @RequestParam String email, @RequestParam String password) {
userService.registerUser(name, email, password);
return ResponseEntity.ok("User registered successfully!");
}
@PostMapping("/login")
public ResponseEntity<String> login(@RequestParam String name, @RequestParam String password) {
boolean isAuthenticated = userService.authenticate(name, password);
if (isAuthenticated) {
return ResponseEntity.ok("Login successful!");
} else {
return ResponseEntity.status(401).body("Invalid username or password.");
}
}
}