From 6d2d02c22c1aca4426203484527ca56b005f6e18 Mon Sep 17 00:00:00 2001 From: Jephte CLAIN Date: Fri, 14 Feb 2014 16:41:12 +0400 Subject: [PATCH] nouvelles options pour upassword --- upassword | 395 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 275 insertions(+), 120 deletions(-) diff --git a/upassword b/upassword index 8395718..44faf34 100755 --- a/upassword +++ b/upassword @@ -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) {