upassword: nouvelles options -m et -n pour la gestion des salts

This commit is contained in:
Jephté Clain 2017-05-15 14:43:46 +04:00
parent 084b96a65b
commit 5d3f576994
1 changed files with 81 additions and 4 deletions

View File

@ -4766,6 +4766,10 @@ public class upassword {
HASH_PASSWORD, GEN_AESKEY, SHOW_AESKEY, AES_ENCRYPT, AES_DECRYPT; HASH_PASSWORD, GEN_AESKEY, SHOW_AESKEY, AES_ENCRYPT, AES_DECRYPT;
} }
private static enum EHashAction {
AUTO, CHECK_MATCH, SAME_OR_NEW, NEW;
}
private static final void checkExisting(String aeskeyfile) { private static final void checkExisting(String aeskeyfile) {
if (aeskeyfile == null) die("Vous devez spécifier l'option -f", null); if (aeskeyfile == null) die("Vous devez spécifier l'option -f", null);
if (!new File(aeskeyfile).exists()) die(aeskeyfile + ": Fichier introuvable", null); if (!new File(aeskeyfile).exists()) die(aeskeyfile + ": Fichier introuvable", null);
@ -4873,6 +4877,16 @@ public class upassword {
+ "\n -p, --hash-password" + "\n -p, --hash-password"
+ "\n Crypter un mot de passe (option par défaut). Si le mot de passe en clair" + "\n Crypter un mot de passe (option par défaut). Si le mot de passe en clair"
+ "\n et/ou le salt ne sont pas spécifiés, ils sont choisis au hasard." + "\n et/ou le salt ne sont pas spécifiés, ils sont choisis au hasard."
+ "\n -m, --salt-check-match-hash"
+ "\n -n, --salt-same-or-new-hash"
+ "\n Spécifier le comportement à adopter si les salts qui sont spécifiés sont"
+ "\n des hashes normalisés."
+ "\n Avec l'option -m (par défaut), pour chacun des hashes, le salt est"
+ "\n extrait et le mot de passe en clair est hashé avec ce salt et le scheme"
+ "\n spécifiés. Si le hash résultant est le même, afficher 'match: true'"
+ "\n Avec l'option -n, si l'un des hashes correspond au mot de passe en"
+ "\n clair, alors afficher ce hash. Sinon, faire comme si le mot de passe en"
+ "\n clair avait été spécifié sans salt et choisir un nouveau salt au hasard."
+ "\n -j, --clear-is-codetu JKEY" + "\n -j, --clear-is-codetu JKEY"
+ "\n Indiquer que l'argument clear est un numéro d'étudiant, à partir duquel" + "\n Indiquer que l'argument clear est un numéro d'étudiant, à partir duquel"
+ "\n il faut générer le mot de passe. Cette option n'est valide qu'avec -p" + "\n il faut générer le mot de passe. Cette option n'est valide qu'avec -p"
@ -4921,6 +4935,7 @@ public class upassword {
} }
EAction action = EAction.HASH_PASSWORD; EAction action = EAction.HASH_PASSWORD;
EHashAction hashAction = EHashAction.AUTO;
boolean codEtu = false, crypted = false, shell = false; boolean codEtu = false, crypted = false, shell = false;
String codEtuKey = null; String codEtuKey = null;
String aeskeyfile = null; String aeskeyfile = null;
@ -4946,6 +4961,12 @@ public class upassword {
} else if (arg.equals("-k") || args.equals("--clear-is-crypted")) { } else if (arg.equals("-k") || args.equals("--clear-is-crypted")) {
crypted = true; crypted = true;
i++; i++;
} else if (arg.equals("-m") || args.equals("--salt-check-match-hash")) {
hashAction = EHashAction.CHECK_MATCH;
i++;
} else if (arg.equals("-n") || args.equals("--salt-same-or-new-hash")) {
hashAction = EHashAction.SAME_OR_NEW;
i++;
} else if (arg.equals("-G") || arg.equals("--aes-genkey")) { } else if (arg.equals("-G") || arg.equals("--aes-genkey")) {
action = EAction.GEN_AESKEY; action = EAction.GEN_AESKEY;
i++; i++;
@ -5014,7 +5035,58 @@ public class upassword {
clear = pg.generate(); clear = pg.generate();
} }
String newCryptSalt = null;
byte[] newBinarySalt = null;
if (args.length <= 1) { if (args.length <= 1) {
hashAction = EHashAction.NEW;
} else if (hashAction == EHashAction.AUTO) {
hashAction = EHashAction.CHECK_MATCH;
} else if (hashAction == EHashAction.SAME_OR_NEW) {
i = 1;
max = args.length;
while (i < max) {
String salt = args[i++];
if (Password.isNormalizedFormat(salt)) {
if (Password.isCryptScheme(salt)) {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt)
.getNormalized();
if (salt.equals(crypt)) newCryptSalt = cryptSalt;
} else if (Password.isSshaScheme(salt)) {
byte[] sshaSalt = Salt.getSshaSalt(salt);
String ssha = getPasswordBinarySalt(clear, Password.SSHA, sshaSalt)
.getNormalized();
if (salt.equals(ssha)) newBinarySalt = sshaSalt;
} else if (Password.isSmd5Scheme(salt)) {
byte[] smd5Salt = Salt.getSmd5Salt(salt);
String smd5 = getPasswordBinarySalt(clear, Password.SMD5, smd5Salt)
.getNormalized();
if (salt.equals(smd5)) newBinarySalt = smd5Salt;
}
} else if (isHex(salt)) {
byte[] binarySalt = fromHex(salt);
String ssha = getPasswordBinarySalt(clear, Password.SSHA, binarySalt)
.getNormalized();
String smd5 = getPasswordBinarySalt(clear, Password.SMD5, binarySalt)
.getNormalized();
if (salt.length() >= 2) {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt)
.getNormalized();
if (salt.equals(crypt)) newCryptSalt = cryptSalt;
}
if (salt.equals(ssha) || salt.equals(smd5)) newBinarySalt = binarySalt;
} else {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt)
.getNormalized();
if (salt.equals(crypt)) newCryptSalt = cryptSalt;
}
}
hashAction = EHashAction.NEW;
}
if (hashAction == EHashAction.NEW) {
// Pas de salt, afficher simplement les versions cryptées des mots // Pas de salt, afficher simplement les versions cryptées des mots
// de passe pour tous les schemes. Le salt est choisi au hasard pour // de passe pour tous les schemes. Le salt est choisi au hasard pour
// chaque mot de passe. Il est donc différent à chaque fois. // chaque mot de passe. Il est donc différent à chaque fois.
@ -5026,12 +5098,15 @@ public class upassword {
ntlm = p.getNtlmHash(); ntlm = p.getNtlmHash();
} catch (Password.NotAvailableException e) { } catch (Password.NotAvailableException e) {
} }
String crypt = getPasswordAnySalt(clear, Password.CRYPT, null).getNormalized(); String crypt = getPasswordCryptSalt(clear, Password.CRYPT, newCryptSalt)
.getNormalized();
String sha = getPasswordAnySalt(clear, Password.SHA, null).getNormalized(); String sha = getPasswordAnySalt(clear, Password.SHA, null).getNormalized();
String xsha = getPasswordAnySalt(clear, Password.XSHA, null).getNormalized(); String xsha = getPasswordAnySalt(clear, Password.XSHA, null).getNormalized();
String ssha = getPasswordAnySalt(clear, Password.SSHA, null).getNormalized(); String ssha = getPasswordBinarySalt(clear, Password.SSHA, newBinarySalt)
.getNormalized();
String md5 = getPasswordAnySalt(clear, Password.MD5, null).getNormalized(); String md5 = getPasswordAnySalt(clear, Password.MD5, null).getNormalized();
String smd5 = getPasswordAnySalt(clear, Password.SMD5, null).getNormalized(); String smd5 = getPasswordBinarySalt(clear, Password.SMD5, newBinarySalt)
.getNormalized();
String aes = null; String aes = null;
if (aeskey != null) { if (aeskey != null) {
try { try {
@ -5051,7 +5126,7 @@ public class upassword {
printvar("md5", md5, shell); printvar("md5", md5, shell);
printvar("smd5", smd5, shell); printvar("smd5", smd5, shell);
if (aes != null) printvar("aes", aes, shell); if (aes != null) printvar("aes", aes, shell);
} else { } else if (hashAction == EHashAction.CHECK_MATCH) {
// Afficher uniquement les versions cryptées des mots de passe avec // Afficher uniquement les versions cryptées des mots de passe avec
// les schemes correspondant aux salts spécifiés, pour chacun des // les schemes correspondant aux salts spécifiés, pour chacun des
// salts spécifiés. // salts spécifiés.
@ -5113,6 +5188,8 @@ public class upassword {
if (salt.equals(crypt)) printvar("match", "true", shell); if (salt.equals(crypt)) printvar("match", "true", shell);
} }
} }
} else {
throw new Error("bug: hashAction==" + hashAction);
} }
break; break;
} }