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
|
mainClass=upassword
|
||||||
compileAndGo
|
compileAndGo
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
@ -17,6 +19,7 @@ import java.util.Random;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.SecretKeyFactory;
|
import javax.crypto.SecretKeyFactory;
|
||||||
import javax.crypto.spec.PBEKeySpec;
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
@ -51,6 +54,7 @@ public class upassword {
|
||||||
|
|
||||||
public static final void println(String text) {
|
public static final void println(String text) {
|
||||||
System.out.println(text);
|
System.out.println(text);
|
||||||
|
System.out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final StringBuilder toHex(StringBuilder sb, byte b) {
|
public static final StringBuilder toHex(StringBuilder sb, byte b) {
|
||||||
|
@ -4556,6 +4560,17 @@ public class upassword {
|
||||||
|
|
||||||
private static final String CIPHER = "AES/ECB/PKCS5Padding";
|
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)
|
public static final byte[] genkey(String password, byte[] salt, int iterations)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
if (salt == null) salt = Salt.getInstance().newBinarySalt();
|
if (salt == null) salt = Salt.getInstance().newBinarySalt();
|
||||||
|
@ -4584,6 +4599,10 @@ public class upassword {
|
||||||
return Base64.decode(skey);
|
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 {
|
public static final byte[] encrypt(byte[] clear, byte[] key) throws Exception {
|
||||||
if (clear == null) return null;
|
if (clear == null) return null;
|
||||||
if (key == null) throw new NullPointerException("key is required");
|
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) {
|
private void run(String[] args) {
|
||||||
if (args.length == 1 && strEquals(args[0], "--help")) {
|
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);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAction action = EAction.HASH_PASSWORD;
|
||||||
String aeskeyfile = null;
|
String aeskeyfile = null;
|
||||||
if (args.length > 0 && args[0].substring(0, 2).equals("-f")) {
|
int i = 0, max = args.length;
|
||||||
String opt = args[0];
|
while (i < args.length) {
|
||||||
int shift = 1;
|
String arg = args[i];
|
||||||
if (opt.equals("-f")) {
|
if (arg.equals("-p")) {
|
||||||
if (args.length > 1) {
|
action = EAction.HASH_PASSWORD;
|
||||||
aeskeyfile = args[1];
|
i++;
|
||||||
shift = 2;
|
} else if (arg.equals("-G")) {
|
||||||
}
|
action = EAction.GEN_AESKEY;
|
||||||
} else {
|
i++;
|
||||||
aeskeyfile = args[0].substring(2);
|
} else if (arg.equals("-s")) {
|
||||||
}
|
action = EAction.SHOW_AESKEY;
|
||||||
String[] newargs = new String[args.length - shift];
|
i++;
|
||||||
System.arraycopy(args, shift, newargs, 0, newargs.length);
|
} else if (arg.equals("-e")) {
|
||||||
args = newargs;
|
action = EAction.AES_ENCRYPT;
|
||||||
}
|
i++;
|
||||||
byte[] aeskey = null;
|
} else if (arg.equals("-d")) {
|
||||||
if (aeskeyfile != null) {
|
action = EAction.AES_DECRYPT;
|
||||||
try {
|
i++;
|
||||||
FileInputStream fis = new FileInputStream(aeskeyfile);
|
} else if (arg.substring(0, 2).equals("-f")) {
|
||||||
try {
|
int shift = 1;
|
||||||
aeskey = new byte[16];
|
if (arg.equals("-f")) {
|
||||||
fis.read(aeskey);
|
if (args.length > i + 1) {
|
||||||
} finally {
|
aeskeyfile = args[i + 1];
|
||||||
fis.close();
|
shift = 2;
|
||||||
}
|
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String cryptSalt = Salt.getCryptSalt(salt);
|
aeskeyfile = arg.substring(2);
|
||||||
String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt).getNormalized();
|
|
||||||
println("salt: " + cryptSalt);
|
|
||||||
println("crypt: " + crypt);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
public static void main(String[] args) {
|
||||||
|
|
Loading…
Reference in New Issue