Mejore la seguridad de las contraseñas :3
This commit is contained in:
@@ -360,7 +360,8 @@ create table usuario
|
|||||||
(
|
(
|
||||||
id int unsigned primary key auto_increment,
|
id int unsigned primary key auto_increment,
|
||||||
nombre varchar(255) not null,
|
nombre varchar(255) not null,
|
||||||
password varchar(255) not null,
|
password binary(32) not null,
|
||||||
|
salt binary(16) not null,
|
||||||
trabajador_id int unsigned not null,
|
trabajador_id int unsigned not null,
|
||||||
foreign key (trabajador_id) references trabajador (id) on delete cascade on update cascade,
|
foreign key (trabajador_id) references trabajador (id) on delete cascade on update cascade,
|
||||||
inserted_at timestamp default current_timestamp
|
inserted_at timestamp default current_timestamp
|
||||||
@@ -444,6 +445,3 @@ values (1, 2),
|
|||||||
|
|
||||||
INSERT INTO trabajador
|
INSERT INTO trabajador
|
||||||
VALUES (1, '197638990', 'Daniel', 'Cortes', 'Pincheira', '2019-06-04', '2019-06-04 18:12:55');
|
VALUES (1, '197638990', 'Daniel', 'Cortes', 'Pincheira', '2019-06-04', '2019-06-04 18:12:55');
|
||||||
|
|
||||||
INSERT INTO usuario
|
|
||||||
VALUES (1, 'admin', 'IF7nbMo9zxGOH++0op8eE+obeILVzsZCguAqPVydL/0=', 1, '2019-06-05 00:08:50');
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package xyz.danielcortes.controllers.mantenedores.trabajador.usuario;
|
package xyz.danielcortes.controllers.mantenedores.trabajador.usuario;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import xyz.danielcortes.controllers.LaunchController;
|
import xyz.danielcortes.controllers.LaunchController;
|
||||||
import xyz.danielcortes.controllers.mantenedores.trabajador.TrabajadorViewController;
|
import xyz.danielcortes.controllers.mantenedores.trabajador.TrabajadorViewController;
|
||||||
import xyz.danielcortes.framework.BaseController;
|
import xyz.danielcortes.framework.BaseController;
|
||||||
import xyz.danielcortes.framework.BasePanel;
|
import xyz.danielcortes.framework.BasePanel;
|
||||||
import xyz.danielcortes.framework.Hash;
|
|
||||||
import xyz.danielcortes.framework.PanelName;
|
import xyz.danielcortes.framework.PanelName;
|
||||||
|
import xyz.danielcortes.framework.Passwords;
|
||||||
import xyz.danielcortes.framework.ValidationResult;
|
import xyz.danielcortes.framework.ValidationResult;
|
||||||
import xyz.danielcortes.models.Trabajador;
|
import xyz.danielcortes.models.Trabajador;
|
||||||
import xyz.danielcortes.models.Usuario;
|
import xyz.danielcortes.models.Usuario;
|
||||||
@@ -68,7 +67,8 @@ public class UsuarioCreateController extends BaseController {
|
|||||||
|
|
||||||
Usuario usuario = new Usuario();
|
Usuario usuario = new Usuario();
|
||||||
usuario.setNombre(user);
|
usuario.setNombre(user);
|
||||||
usuario.setPassword(Hash.sha256(new String(pass).getBytes(StandardCharsets.UTF_8)));
|
usuario.setSalt(Passwords.getNextSalt());
|
||||||
|
usuario.setPassword(Passwords.hash(pass, usuario.getSalt()));
|
||||||
usuario.setTrabajador(trabajador);
|
usuario.setTrabajador(trabajador);
|
||||||
|
|
||||||
this.repository.save(usuario);
|
this.repository.save(usuario);
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package xyz.danielcortes.controllers.mantenedores.trabajador.usuario;
|
package xyz.danielcortes.controllers.mantenedores.trabajador.usuario;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import xyz.danielcortes.controllers.LaunchController;
|
import xyz.danielcortes.controllers.LaunchController;
|
||||||
import xyz.danielcortes.controllers.mantenedores.trabajador.TrabajadorViewController;
|
import xyz.danielcortes.controllers.mantenedores.trabajador.TrabajadorViewController;
|
||||||
import xyz.danielcortes.framework.BaseController;
|
import xyz.danielcortes.framework.BaseController;
|
||||||
import xyz.danielcortes.framework.BasePanel;
|
import xyz.danielcortes.framework.BasePanel;
|
||||||
import xyz.danielcortes.framework.Hash;
|
|
||||||
import xyz.danielcortes.framework.PanelName;
|
import xyz.danielcortes.framework.PanelName;
|
||||||
|
import xyz.danielcortes.framework.Passwords;
|
||||||
import xyz.danielcortes.framework.ValidationResult;
|
import xyz.danielcortes.framework.ValidationResult;
|
||||||
import xyz.danielcortes.models.Trabajador;
|
import xyz.danielcortes.models.Trabajador;
|
||||||
import xyz.danielcortes.repository.UsuarioRepository;
|
import xyz.danielcortes.repository.UsuarioRepository;
|
||||||
@@ -77,7 +76,8 @@ public class UsuarioUpdateController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trabajador.getUsuario().setNombre(user);
|
trabajador.getUsuario().setNombre(user);
|
||||||
trabajador.getUsuario().setPassword(Hash.sha256(new String(pass).getBytes(StandardCharsets.UTF_8)));
|
trabajador.getUsuario().setSalt(Passwords.getNextSalt());
|
||||||
|
trabajador.getUsuario().setPassword(Passwords.hash(pass, trabajador.getUsuario().getSalt()));
|
||||||
|
|
||||||
this.repository.update(trabajador.getUsuario());
|
this.repository.update(trabajador.getUsuario());
|
||||||
this.volver();
|
this.volver();
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package xyz.danielcortes.framework;
|
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
public class Hash {
|
|
||||||
|
|
||||||
private static MessageDigest sha;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
sha = MessageDigest.getInstance("SHA-256");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String sha256(byte[] toHash) {
|
|
||||||
return Base64.getEncoder().encodeToString(sha.digest(toHash));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
46
src/main/java/xyz/danielcortes/framework/Passwords.java
Normal file
46
src/main/java/xyz/danielcortes/framework/Passwords.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package xyz.danielcortes.framework;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
|
||||||
|
public class Passwords {
|
||||||
|
private static final Random RANDOM = new SecureRandom();
|
||||||
|
private static final int ITERATIONS = 10000;
|
||||||
|
private static final int KEY_LENGHT = 256;
|
||||||
|
|
||||||
|
private Passwords(){}
|
||||||
|
|
||||||
|
public static byte[] getNextSalt() {
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
RANDOM.nextBytes(salt);
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] hash(char[] password, byte[] salt){
|
||||||
|
PBEKeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_LENGHT);
|
||||||
|
Arrays.fill(password, Character.MIN_VALUE);
|
||||||
|
try{
|
||||||
|
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||||
|
return skf.generateSecret(spec).getEncoded();
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||||
|
throw new AssertionError("Error while hashing a password: " + e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
spec.clearPassword();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isExpectedPassword(char[] password, byte[] salt, byte[] expectedHash){
|
||||||
|
byte[] pwdHash = hash(password, salt);
|
||||||
|
Arrays.fill(password, Character.MIN_VALUE);
|
||||||
|
if(pwdHash.length != expectedHash.length) return false;
|
||||||
|
for(int i = 0; i < pwdHash.length; i++){
|
||||||
|
if(pwdHash[i] != expectedHash[i]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
package xyz.danielcortes.login;
|
package xyz.danielcortes.login;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.WindowConstants;
|
import javax.swing.WindowConstants;
|
||||||
import xyz.danielcortes.framework.Hash;
|
|
||||||
import xyz.danielcortes.framework.LoggedEvent;
|
import xyz.danielcortes.framework.LoggedEvent;
|
||||||
import xyz.danielcortes.framework.LoggedListener;
|
import xyz.danielcortes.framework.LoggedListener;
|
||||||
|
import xyz.danielcortes.framework.Passwords;
|
||||||
import xyz.danielcortes.models.Usuario;
|
import xyz.danielcortes.models.Usuario;
|
||||||
import xyz.danielcortes.repository.UsuarioRepository;
|
import xyz.danielcortes.repository.UsuarioRepository;
|
||||||
|
|
||||||
@@ -46,8 +45,8 @@ public class LoginController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Usuario user = optionalUser.get();
|
Usuario user = optionalUser.get();
|
||||||
String pass = Hash.sha256(new String(this.view.getPassField().getPassword()).getBytes(StandardCharsets.UTF_8));
|
char[] pass = this.view.getPassField().getPassword();
|
||||||
if (pass.equals(user.getPassword())) {
|
if (Passwords.isExpectedPassword(pass, user.getSalt(), user.getPassword())) {
|
||||||
this.frame.dispose();
|
this.frame.dispose();
|
||||||
loggedListener.loginTry(new LoggedEvent(this, user));
|
loggedListener.loginTry(new LoggedEvent(this, user));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package xyz.danielcortes.models;
|
package xyz.danielcortes.models;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
@@ -21,8 +20,11 @@ public class Usuario {
|
|||||||
@Column(name = "nombre")
|
@Column(name = "nombre")
|
||||||
private String nombre;
|
private String nombre;
|
||||||
|
|
||||||
@Column(name = "password")
|
@Column(name = "password", columnDefinition = "BINARY(32) NOT NULL")
|
||||||
private String password;
|
private byte[] password;
|
||||||
|
|
||||||
|
@Column(name = "salt", columnDefinition = "BINARY(16) NOT NULL")
|
||||||
|
private byte[] salt;
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "trabajador_id", referencedColumnName = "id")
|
@JoinColumn(name = "trabajador_id", referencedColumnName = "id")
|
||||||
@@ -44,14 +46,22 @@ public class Usuario {
|
|||||||
this.nombre = nombre;
|
this.nombre = nombre;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public byte[] getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassword(String password) {
|
public void setPassword(byte[] password) {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] getSalt() {
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalt(byte[] salt) {
|
||||||
|
this.salt = salt;
|
||||||
|
}
|
||||||
|
|
||||||
public Trabajador getTrabajador() {
|
public Trabajador getTrabajador() {
|
||||||
return trabajador;
|
return trabajador;
|
||||||
}
|
}
|
||||||
@@ -59,22 +69,4 @@ public class Usuario {
|
|||||||
public void setTrabajador(Trabajador trabajador) {
|
public void setTrabajador(Trabajador trabajador) {
|
||||||
this.trabajador = trabajador;
|
this.trabajador = trabajador;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o)
|
|
||||||
return true;
|
|
||||||
if (!(o instanceof Usuario))
|
|
||||||
return false;
|
|
||||||
Usuario usuario = (Usuario) o;
|
|
||||||
return Objects.equals(id, usuario.id) &&
|
|
||||||
Objects.equals(nombre, usuario.nombre) &&
|
|
||||||
Objects.equals(password, usuario.password) &&
|
|
||||||
Objects.equals(trabajador, usuario.trabajador);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(id, nombre, password, trabajador);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user