nouvelles options pour upassword

This commit is contained in:
Jephté Clain 2014-02-14 16:41:12 +04:00
parent 704f34029b
commit 6d2d02c22c
1 changed files with 275 additions and 120 deletions

395
upassword
View File

@ -4,7 +4,9 @@ compiler=javac
mainClass=upassword
compileAndGo
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
@ -17,6 +19,7 @@ import java.util.Random;
import java.util.regex.Pattern;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
@ -51,6 +54,7 @@ public class upassword {
public static final void println(String text) {
System.out.println(text);
System.out.flush();
}
public static final StringBuilder toHex(StringBuilder sb, byte b) {
@ -4556,6 +4560,17 @@ public class upassword {
private static final String CIPHER = "AES/ECB/PKCS5Padding";
public static final byte[] genkey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(AES);
kg.init(new SecureRandom());
SecretKey key = kg.generateKey();
return key.getEncoded();
}
public static final String genskey() throws Exception {
return Base64.encodeBytes(genkey());
}
public static final byte[] genkey(String password, byte[] salt, int iterations)
throws Exception {
if (salt == null) salt = Salt.getInstance().newBinarySalt();
@ -4584,6 +4599,10 @@ public class upassword {
return Base64.decode(skey);
}
public static final String getSkey(byte[] key) {
return Base64.encodeBytes(key, Base64.DONT_BREAK_LINES);
}
public static final byte[] encrypt(byte[] clear, byte[] key) throws Exception {
if (clear == null) return null;
if (key == null) throw new NullPointerException("key is required");
@ -4669,137 +4688,273 @@ public class upassword {
};
}
private static final void die(String msg, Exception e) {
if (msg != null) System.err.println(msg);
if (e != null) e.printStackTrace(System.err);
System.err.flush();
System.exit(1);
}
// actions
private static enum EAction {
HASH_PASSWORD, GEN_AESKEY, SHOW_AESKEY, AES_ENCRYPT, AES_DECRYPT;
}
private static final void checkExisting(String aeskeyfile) {
if (aeskeyfile == null) die("Vous devez spécifier l'option -f", null);
if (!new File(aeskeyfile).exists()) die(aeskeyfile + ": Fichier introuvable", null);
}
private static final byte[] readAeskeyfile(String aeskeyfile) {
if (aeskeyfile == null) return null;
byte[] aeskey = null;
try {
FileInputStream fis = new FileInputStream(aeskeyfile);
try {
aeskey = new byte[16];
fis.read(aeskey);
} finally {
fis.close();
}
} catch (Exception e) {
die(null, e);
}
return aeskey;
}
private static final void writeAeskeyfile(String aeskeyfile, byte[] key) {
if (aeskeyfile == null) return;
try {
FileOutputStream fis = new FileOutputStream(aeskeyfile);
try {
fis.write(key);
} finally {
fis.close();
}
} catch (Exception e) {
die(null, e);
}
}
private void run(String[] args) {
if (args.length == 1 && strEquals(args[0], "--help")) {
println("USAGE: upassword [-f aeskeyfile] [clear [salts...]]");
println("USAGE:" //
+ "\n upassword -p [-f aeskeyfile] [clear [salts...]]"
+ "\n upassword -f aeskeyfile -G [password [salt]]"
+ "\n upassword -f aeskeyfile -s"
+ "\n upassword -f aeskeyfile -e clear"
+ "\n upassword -f aeskeyfile -d crypted");
System.exit(0);
}
EAction action = EAction.HASH_PASSWORD;
String aeskeyfile = null;
if (args.length > 0 && args[0].substring(0, 2).equals("-f")) {
String opt = args[0];
int shift = 1;
if (opt.equals("-f")) {
if (args.length > 1) {
aeskeyfile = args[1];
shift = 2;
}
} else {
aeskeyfile = args[0].substring(2);
}
String[] newargs = new String[args.length - shift];
System.arraycopy(args, shift, newargs, 0, newargs.length);
args = newargs;
}
byte[] aeskey = null;
if (aeskeyfile != null) {
try {
FileInputStream fis = new FileInputStream(aeskeyfile);
try {
aeskey = new byte[16];
fis.read(aeskey);
} finally {
fis.close();
}
} catch (Exception e) {
e.printStackTrace(System.err);
System.exit(1);
}
}
String clear = null;
if (args.length > 0) clear = args[0];
String salt = null;
if (args.length > 1) salt = args[1];
if (clear == null) {
PasswordGenerator pg = new PasswordGenerator();
clear = pg.generate();
}
if (salt == null) {
// Pas de salt, afficher simplement les versions cryptées des mots
// de passe pour tous les schemes. Le salt est choisi au hasard pour
// chaque mot de passe. Il est donc différent à chaque fois.
Password p = getPasswordAnySalt(clear, null, null);
String lm = null;
String ntlm = null;
try {
lm = p.getLmHash();
ntlm = p.getNtlmHash();
} catch (Password.NotAvailableException e) {
}
String crypt = getPasswordAnySalt(clear, Password.CRYPT, salt).getNormalized();
String sha = getPasswordAnySalt(clear, Password.SHA, salt).getNormalized();
String ssha = getPasswordAnySalt(clear, Password.SSHA, salt).getNormalized();
String md5 = getPasswordAnySalt(clear, Password.MD5, salt).getNormalized();
String smd5 = getPasswordAnySalt(clear, Password.SMD5, salt).getNormalized();
String aes = null;
if (aeskey != null) {
try {
aes = AESEnc.sencrypt(clear, aeskey);
} catch (Exception e) {
}
}
println("clear: " + clear);
println("lm: " + lm);
println("ntlm: " + ntlm);
println("crypt: " + crypt);
println("sha: " + sha);
println("ssha: " + ssha);
println("md5: " + md5);
println("smd5: " + smd5);
if (aes != null) println("aes: " + aes);
} else {
// Afficher uniquement les versions cryptées des mots de passe avec
// les schemes correspondant aux salts spécifiés, pour chacun des
// salts spécifiés.
println("clear: " + clear);
int i = 1, max = args.length;
while (i < max) {
salt = args[i++];
if (Password.isNormalizedFormat(salt)) {
if (Password.isCryptScheme(salt)) {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt).getNormalized();
println("salt: " + cryptSalt);
println("crypt: " + crypt);
} else if (Password.isSshaScheme(salt)) {
byte[] sshaSalt = Salt.getSshaSalt(salt);
String ssha = getPasswordBinarySalt(clear, Password.SSHA, sshaSalt).getNormalized();
println("salt: " + toHex(sshaSalt));
println("ssha: " + ssha);
} else if (Password.isSmd5Scheme(salt)) {
byte[] smd5Salt = Salt.getSmd5Salt(salt);
String smd5 = getPasswordBinarySalt(clear, Password.SMD5, smd5Salt).getNormalized();
println("salt: " + toHex(smd5Salt));
println("smd5: " + smd5);
} else {
println("salt: " + salt + " !not supported");
}
} else if (isHex(salt)) {
byte[] binarySalt = fromHex(salt);
String ssha = getPasswordBinarySalt(clear, Password.SSHA, binarySalt).getNormalized();
String smd5 = getPasswordBinarySalt(clear, Password.SMD5, binarySalt).getNormalized();
println("salt: " + toHex(binarySalt));
println("ssha: " + ssha);
println("smd5: " + smd5);
if (salt.length() >= 2) {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt).getNormalized();
if (!salt.equals(cryptSalt)) println("salt: " + cryptSalt);
println("crypt: " + crypt);
int i = 0, max = args.length;
while (i < args.length) {
String arg = args[i];
if (arg.equals("-p")) {
action = EAction.HASH_PASSWORD;
i++;
} else if (arg.equals("-G")) {
action = EAction.GEN_AESKEY;
i++;
} else if (arg.equals("-s")) {
action = EAction.SHOW_AESKEY;
i++;
} else if (arg.equals("-e")) {
action = EAction.AES_ENCRYPT;
i++;
} else if (arg.equals("-d")) {
action = EAction.AES_DECRYPT;
i++;
} else if (arg.substring(0, 2).equals("-f")) {
int shift = 1;
if (arg.equals("-f")) {
if (args.length > i + 1) {
aeskeyfile = args[i + 1];
shift = 2;
}
} else {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt).getNormalized();
println("salt: " + cryptSalt);
println("crypt: " + crypt);
aeskeyfile = arg.substring(2);
}
i += shift;
} else {
String[] newargs = new String[args.length - i];
System.arraycopy(args, i, newargs, 0, newargs.length);
args = newargs;
break;
}
}
System.out.flush();
switch (action) {
case HASH_PASSWORD: {
byte[] aeskey = readAeskeyfile(aeskeyfile);
String clear = null;
if (args.length > 0) clear = args[0];
if (clear == null) {
PasswordGenerator pg = new PasswordGenerator();
clear = pg.generate();
}
if (args.length <= 1) {
// Pas de salt, afficher simplement les versions cryptées des mots
// de passe pour tous les schemes. Le salt est choisi au hasard pour
// chaque mot de passe. Il est donc différent à chaque fois.
Password p = getPasswordAnySalt(clear, null, null);
String lm = null;
String ntlm = null;
try {
lm = p.getLmHash();
ntlm = p.getNtlmHash();
} catch (Password.NotAvailableException e) {
}
String crypt = getPasswordAnySalt(clear, Password.CRYPT, null).getNormalized();
String sha = getPasswordAnySalt(clear, Password.SHA, null).getNormalized();
String ssha = getPasswordAnySalt(clear, Password.SSHA, null).getNormalized();
String md5 = getPasswordAnySalt(clear, Password.MD5, null).getNormalized();
String smd5 = getPasswordAnySalt(clear, Password.SMD5, null).getNormalized();
String aes = null;
if (aeskey != null) {
try {
aes = AESEnc.sencrypt(clear, aeskey);
} catch (Exception e) {
die("Impossible de crypter avec AES", e);
}
}
println("clear: " + clear);
println("lm: " + lm);
println("ntlm: " + ntlm);
println("crypt: " + crypt);
println("sha: " + sha);
println("ssha: " + ssha);
println("md5: " + md5);
println("smd5: " + smd5);
if (aes != null) println("aes: " + aes);
} else {
// Afficher uniquement les versions cryptées des mots de passe avec
// les schemes correspondant aux salts spécifiés, pour chacun des
// salts spécifiés.
println("clear: " + clear);
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();
println("salt: " + cryptSalt);
println("crypt: " + crypt);
} else if (Password.isSshaScheme(salt)) {
byte[] sshaSalt = Salt.getSshaSalt(salt);
String ssha = getPasswordBinarySalt(clear, Password.SSHA, sshaSalt)
.getNormalized();
println("salt: " + toHex(sshaSalt));
println("ssha: " + ssha);
} else if (Password.isSmd5Scheme(salt)) {
byte[] smd5Salt = Salt.getSmd5Salt(salt);
String smd5 = getPasswordBinarySalt(clear, Password.SMD5, smd5Salt)
.getNormalized();
println("salt: " + toHex(smd5Salt));
println("smd5: " + smd5);
} else {
println("salt: " + salt + " !not supported");
}
} else if (isHex(salt)) {
byte[] binarySalt = fromHex(salt);
String ssha = getPasswordBinarySalt(clear, Password.SSHA, binarySalt)
.getNormalized();
String smd5 = getPasswordBinarySalt(clear, Password.SMD5, binarySalt)
.getNormalized();
println("salt: " + toHex(binarySalt));
println("ssha: " + ssha);
println("smd5: " + smd5);
if (salt.length() >= 2) {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt)
.getNormalized();
if (!salt.equals(cryptSalt)) println("salt: " + cryptSalt);
println("crypt: " + crypt);
}
} else {
String cryptSalt = Salt.getCryptSalt(salt);
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt)
.getNormalized();
println("salt: " + cryptSalt);
println("crypt: " + crypt);
}
}
}
break;
}
case GEN_AESKEY: {
if (aeskeyfile == null) die("Vous devez spécifier l'option -f", null);
if (new File(aeskeyfile).exists()) {
die(aeskeyfile + ": Refus d'écraser un fichier existant", null);
}
String password = null;
if (args.length > 0) password = args[0];
String salt = null;
if (args.length > 1) salt = args[1];
byte[] key = null;
try {
if (password != null && salt != null) {
key = AESEnc.genkey();
} else {
key = AESEnc.genkey(password, salt.getBytes(UTF_8), -1);
}
} catch (Exception e) {
die(null, e);
}
writeAeskeyfile(aeskeyfile, key);
break;
}
case SHOW_AESKEY: {
checkExisting(aeskeyfile);
byte[] key = readAeskeyfile(aeskeyfile);
println(AESEnc.getSkey(key));
break;
}
case AES_ENCRYPT: {
checkExisting(aeskeyfile);
byte[] key = readAeskeyfile(aeskeyfile);
String sclear = null;
if (args.length > 0) sclear = args[0];
if (sclear != null) {
try {
println(AESEnc.sencrypt(sclear, key));
} catch (Exception e) {
die(null, e);
}
}
break;
}
case AES_DECRYPT: {
checkExisting(aeskeyfile);
byte[] key = readAeskeyfile(aeskeyfile);
String scrypted = null;
if (args.length > 0) scrypted = args[0];
if (scrypted != null) {
try {
println(AESEnc.sdecrypt(scrypted, key));
} catch (Exception e) {
die(null, e);
}
}
break;
}
}
}
public static void main(String[] args) {