2017-07-14 3 views
0

J'ai une application qui peut nécessiter un mot de passe pour l'authentification.
Cette application ne gère pas les données sensibles, car ce "mot de passe" est choisi par l'hôte et dit aux "clients" via un autre canal (WhatsApp ou autre). Ainsi, lorsqu'un client veut s'authentifier, l'hôte génère une chaîne aléatoire qui est envoyée au client.
Le client crypte ensuite cette chaîne aléatoire avec le mot de passe saisi par l'utilisateur.
La chaîne aléatoire cryptée est l'expéditeur de l'hôte.
L'hôte déchiffre cette chaîne chiffrée avec la clé générée par le même mot de passe.
Si le match de chaîne non cryptée et originale, l'utilisateur est connecté
C'est ce que je suis venu avec jusqu'à présent.Générer une clé AES basée sur le mot de passe seulement

String base64; 
char[] password = "password".toCharArray(); 
String randomString = new BigInteger(130, new SecureRandom()).toString(32); 
try { 
    //Encrypt Client Side 
    SecretKey key = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512").generateSecret(new PBEKeySpec(password)).getEncoded(), "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.ENCRYPT_MODE, key); 
    base64 = Base64.getEncoder().encodeToString(cipher.doFinal(randomString.getBytes(StandardCharsets.UTF_8))); 
} catch (GeneralSecurityException e) { 
    throw new IllegalStateException(e); 
} 
try { 
    //Decrypt Server Side 
    SecretKey key = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512").generateSecret(new PBEKeySpec(password)).getEncoded(), "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.DECRYPT_MODE, key); 
    //Check if both strings match 
    System.out.println(Arrays.equals(cipher.doFinal(Base64.getDecoder().decode(base64)), randomString.getBytes(StandardCharsets.UTF_8))); 
} catch (GeneralSecurityException e) { 
    throw new IllegalStateException(e); 
} 

Malheureusement, ce code va lancer une exception: java.security.spec.InvalidKeySpecException: Salt not found
Dois-je utiliser un autre algorithme, ou devrais-je générer un sel en hachant le mot de passe lui-même, ou une approche complètement différente? Je voudrais éviter d'avoir à envoyer un sel généré avec la chaîne aléatoire

Répondre

1

Vous devez donner PBEKeySpec ce dont il a besoin pour générer assez de bits pour une clé AES. Vous avez besoin du même sel sur les deux côtés, pour que vous puissiez faire:

byte[] salt = new byte[8]; 
System.arraycopy(randomString.getBytes("UTF-8"), 0, salt, 0, 8); 

Remplacez votre PBEKeySpec avec new PBEKeySpec(password, salt, 10, 128) et tout devrait fonctionner.