nouvelles options pour upassword
This commit is contained in:
parent
704f34029b
commit
6d2d02c22c
395
upassword
395
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) {
|
||||
|
|
Loading…
Reference in New Issue