diff --git a/rapidoid-commons/src/main/java/org/rapidoid/crypto/Crypto.java b/rapidoid-commons/src/main/java/org/rapidoid/crypto/Crypto.java index 24d1872e31..54428e3664 100644 --- a/rapidoid-commons/src/main/java/org/rapidoid/crypto/Crypto.java +++ b/rapidoid-commons/src/main/java/org/rapidoid/crypto/Crypto.java @@ -209,7 +209,7 @@ public static String passwordHash(char[] password, int iterations, byte[] salt) return Str.toBase64(hash) + "$" + Str.toBase64(salt) + "$" + iterations; } - public static boolean passwordMatches(String password, String saltedHash) { + public static boolean passwordMatches(char[] password, String saltedHash) { String[] parts = saltedHash.split("\\$"); if (parts.length != 3) { @@ -226,10 +226,14 @@ public static boolean passwordMatches(String password, String saltedHash) { return false; } - byte[] realHash = pbkdf2(password.toCharArray(), salt, iterations, 256); + byte[] realHash = pbkdf2(password, salt, iterations, 256); return Arrays.equals(expectedHash, realHash); } + public static boolean passwordMatches(String password, String saltedHash) { + return passwordMatches(password.toCharArray(), saltedHash); + } + public static byte[] randomBytes(int byteCount) { byte[] bytes = new byte[byteCount]; RANDOM.nextBytes(bytes); diff --git a/rapidoid-commons/src/main/resources/rapidoid-classes.txt b/rapidoid-commons/src/main/resources/rapidoid-classes.txt index ad678920f6..890e9622dc 100644 --- a/rapidoid-commons/src/main/resources/rapidoid-classes.txt +++ b/rapidoid-commons/src/main/resources/rapidoid-classes.txt @@ -644,6 +644,7 @@ org.rapidoid.platform.AppDownloader org.rapidoid.platform.DefaultApp org.rapidoid.platform.Main org.rapidoid.platform.MavenUtil +org.rapidoid.platform.PasswordHashTool org.rapidoid.platform.Platform org.rapidoid.platform.PlatformInDevMode org.rapidoid.plugin.app.AbstractRapidoidMojo diff --git a/rapidoid-platform/src/main/java/org/rapidoid/platform/PasswordHashTool.java b/rapidoid-platform/src/main/java/org/rapidoid/platform/PasswordHashTool.java new file mode 100644 index 0000000000..17e80cc20f --- /dev/null +++ b/rapidoid-platform/src/main/java/org/rapidoid/platform/PasswordHashTool.java @@ -0,0 +1,86 @@ +package org.rapidoid.platform; + +/* + * #%L + * rapidoid-platform + * %% + * Copyright (C) 2014 - 2017 Nikolche Mihajlovski and contributors + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.rapidoid.RapidoidThing; +import org.rapidoid.annotation.Authors; +import org.rapidoid.annotation.Since; +import org.rapidoid.crypto.Crypto; +import org.rapidoid.u.U; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; + +@Authors("Nikolche Mihajlovski") +@Since("5.3.0") +public class PasswordHashTool extends RapidoidThing { + + public static void main(String[] args) { + generatePasswordHash(args); + } + + public static void generatePasswordHash(String[] args) { + U.must(U.isEmpty(args), "Expecting no arguments!"); + + char[] password = readPassword(); + + U.print("\nYour salted password hash is:\n"); + + String hash = Crypto.passwordHash(password); + U.must(Crypto.passwordMatches(password, hash), "Password hash verification error!"); + + U.print(hash); + U.print(""); + } + + private static char[] readPassword() { + char[] password = readPassword("Enter a new password: "); + char[] password2 = readPassword("Enter the same password again: "); + + if (Arrays.equals(password, password2)) { + return password; + } else { + U.print("[ERROR] The passwords don't match!\n"); + return readPassword(); + } + } + + private static char[] readPassword(String msg) { + Console console = System.console(); + + if (console != null) { + return console.readPassword(msg); + + } else { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + U.print(msg); + try { + return reader.readLine().toCharArray(); + } catch (IOException e) { + throw U.rte(e); + } + } + } + +} diff --git a/rapidoid-platform/src/main/java/org/rapidoid/platform/Platform.java b/rapidoid-platform/src/main/java/org/rapidoid/platform/Platform.java index b9041020a8..39f390adc4 100644 --- a/rapidoid-platform/src/main/java/org/rapidoid/platform/Platform.java +++ b/rapidoid-platform/src/main/java/org/rapidoid/platform/Platform.java @@ -96,16 +96,24 @@ private static void interceptSpecialCommands(String[] args) { String cmd = args[0]; String[] cmdArgs = Arr.sub(args, 1, args.length); - // interpret "mvn" command - if (cmd.equals("mvn")) { - int result = MavenUtil.build("/app", "/data/.m2/repository", U.list(cmdArgs)); - System.exit(result); - } - - // interpret "benchmark" command - if (cmd.equals("benchmark")) { - BenchmarkCenter.main(cmdArgs); - System.exit(0); + switch (cmd) { + case "mvn": + // interpret the "mvn" command + int result = MavenUtil.build("/app", "/data/.m2/repository", U.list(cmdArgs)); + System.exit(result); + break; + + case "benchmark": + // interpret the "benchmark" command + BenchmarkCenter.main(cmdArgs); + System.exit(0); + break; + + case "password": + // interpret the "password" command + PasswordHashTool.generatePasswordHash(cmdArgs); + System.exit(0); + break; } }