73 Commits

Author SHA1 Message Date
binsky e9a6d09877 fix merge conflicts 2 years ago
jenkins 380d31bca4 Merge commit 'eb3439281fe93753a321aedcf3baf7e75bd318fc' into HEAD 2 years ago
binsky eb3439281f fix merge conflicts 2 years ago
jenkins 39c7f726d0 Merge commit 'e3a9523d2b558ff27cc604cd8d951aff47d0761d' into HEAD 2 years ago
binsky e3a9523d2b add test and package hints to readme 2 years ago
jenkins c5bf848e4f Merge commit 'e445d046b2e7cdae91a5aba947abc3ead398c78e' into HEAD 2 years ago
binsky fc92c555ad fix vault test encoding to run maven test on linux console 2 years ago
fdai6352 9d255f29f5 debug testcommit 2 years ago
jenkins 1e918d7219 Merge commit '025734043d25ebe75a59b679fe6b4b345ba10fa4' into HEAD 2 years ago
fdai6352 025734043d debug testcommit 2 years ago
fdai6352 92d763d836 refactored edit credential menu and test 2 years ago
fdai6352 b7a44828cf refactored show credential method and test 2 years ago
binsky e445d046b2 refactor password validator tests 2 years ago
fdai6352 c511951af0 refactored show credential method and test 2 years ago
jenkins 9504d2c4a5 Merge commit '312a9046ac859bf82a99be3e6374e99132892268' into HEAD 2 years ago
binsky 312a9046ac shuffle every generated password by default 2 years ago
binsky cbd3124ac2 fix password generator requirement implementation for every configured character 2 years ago
fdai6352 f014afbf83 refactored add credential Method and Test 2 years ago
binsky 00fc1ee00e implement method to shuffle password characters 2 years ago
binsky fd4e570204 implement requiring every configured character type in password generator 2 years ago
binsky 4c458fb710 implement generating passwords with special characters 2 years ago
binsky 408d189ac4 make password generator requirements configurable 2 years ago
binsky 5eb63ea2b3 implement generating passwords with digits 2 years ago
binsky 7e9f3d179f implement generating passwords with uppercase letters 2 years ago
binsky bb0e14c26f refactor PasswordGeneratorTest 2 years ago
binsky 963c58967d implement generating lowercase passwords with a customizable length 2 years ago
binsky 6b13284a52 add PasswordGenerator class 2 years ago
jenkins 699e0ee815 Merge commit '15fe9b78c371ad7b8fe66d496bf85273a16e561e' into HEAD 2 years ago
jenkins a059cec5c1 Merge commit 'a18ebb743871694e4c56ad5403a5b5894ed1495b' into HEAD 2 years ago
jenkins 5a9eb32422 Merge commit '8fe5cec4110e84885910952cae72fcd55d883650' into HEAD 2 years ago
jenkins 87da40c570 Merge commit 'df02d33f556a100e23ac92a56e444797fd193db2' into HEAD 2 years ago
jenkins e08b8f478a Merge commit 'feea89c7188bb3ab1c968d3a806c2112f92a140c' into HEAD 2 years ago
binsky feea89c718 implement menu navigation to select a vault operation 2 years ago
binsky 02a62e789b refactor list vaults 2 years ago
binsky f8ab3d1a06 implement menu navigation to create a new vault 2 years ago
binsky dc97162cbe refactor createNewVault test 2 years ago
binsky 278f120b04 implement creating a new vault 2 years ago
jenkins 452685583b Merge commit '8cfd7481978d77f5c5823248d77b9f5132fb4566' into HEAD 2 years ago
binsky 8cfd748197 add password wordlist check to password validator 2 years ago
binsky 64d311038b refactor isInWordlist test and implementation 2 years ago
binsky 7588794f5f implement method to test if a password is part of the german wordlist 2 years ago
binsky a3bb841632 implement getting resource file as String 2 years ago
binsky 238bad93f0 implement getting InputStream as String 2 years ago
binsky bed0764835 implement getting resource file as input stream 2 years ago
binsky 01aeaa20d5 implement check for existing special character in password 2 years ago
jenkins 9b3fed46fa Merge commit '469af0b96cffa3f5a42b2a1bb28bdc2a15028e19' into HEAD 2 years ago
binsky 469af0b96c implement checking pwned password in password validator 2 years ago
binsky 3ba0dd6158 refactor method to check if a password has been pwned 2 years ago
binsky c8c871c6c2 implement method to check if a password has been pwned 2 years ago
binsky 1d591771f4 implement sha1 hash generation 2 years ago
binsky 16d309e1e5 implement simple http api to make get requests 2 years ago
jenkins fb4678c3ce Merge commit 'bf3945cef3878e1b69cc3bc2ad595d34b97630e6' into HEAD 2 years ago
jenkins 02f4655625 Merge commit 'e5b8d493969786f7a0bf31bec92fd6797c3e8556' into HEAD 2 years ago
binsky e5b8d49396 implement check for existing digit in password 2 years ago
binsky 660844010e implement check for existing lowercase character in password 2 years ago
binsky 2720667310 implement check for existing uppercase character in password 2 years ago
binsky 5de9fadc40 refactor minimum password length tests and add getter/setter 2 years ago
binsky 1a037c1927 implement check for minimum password length 2 years ago
binsky 1634188b76 add PasswordValidator class with validate method 2 years ago
jenkins 96ae0514cb Merge commit 'b73a9d9377d993114359067d3aa98d80e163ba8d' into HEAD 2 years ago
jenkins d67e9f419d Merge commit 'a81194074a49eabe723e7ad599411d45545a5b1d' into HEAD 2 years ago
binsky a81194074a fix pom.xml artifact definition 2 years ago
binsky 30b9d3e476 add claudias fdai number to readme 2 years ago
binsky 933252a645 implement readFile storage method 2 years ago
binsky ac48e8f8f6 add build instructions, dependencies and contributors to readme 2 years ago
binsky c652890b04 refactor storage test for windows systems 2 years ago
binsky 6e8aefc25f implement writeFile storage method 2 years ago
binsky c3a4d47d30 add writeFile storage method 2 years ago
binsky 4ab40a8edb add basic storage class and interface 2 years ago
binsky 5182612b76 add jar file configuration to pom.xml 2 years ago
jenkins 10c3e08dc6 Merge commit '9e9f1d5c0c2403cd8b41ff9dc07b73dcb7848bab' into HEAD 2 years ago
jenkins a594f15b36 Merge commit '8bc89ca3ed5ce184ebf7f670c5d4430ecb643d2a' into HEAD 2 years ago
jenkins cfd8192ffd Merge commit '52694b60b603098eba26a49b05032b35eac167bb' into HEAD 2 years ago
  1. 30
      README.md
  2. 27
      pom.xml
  3. 28
      src/main/java/HttpApi.java
  4. 119
      src/main/java/PasswordGenerator.java
  5. 63
      src/main/java/PasswordManager.java
  6. 166
      src/main/java/PasswordValidator.java
  7. 37
      src/main/java/ResourceApi.java
  8. 50
      src/main/java/Storage.java
  9. 4
      src/main/java/StorageInterface.java
  10. 85
      src/main/java/Vault.java
  11. 4
      src/main/java/VaultInterface.java
  12. 137465
      src/main/resources/german_wordlist.txt
  13. 19
      src/test/java/HttpApiTest.java
  14. 72
      src/test/java/PasswordGeneratorTest.java
  15. 55
      src/test/java/PasswordManagerTest.java
  16. 130
      src/test/java/PasswordValidatorTest.java
  17. 48
      src/test/java/ResourceApiTest.java
  18. 62
      src/test/java/StorageTest.java
  19. 51
      src/test/java/VaultTest.java

30
README.md

@ -1,2 +1,30 @@
# ciip-gruppe8-password-manager
# ciip-grp8-password-manager
## Dependencies
- productive
- java 11
- development
- java 11
- maven
## Build jar file artifact
- requires development dependencies
`mvn package`
## Run jar file artifact
- requires productive dependencies
- requires a built jar file to run
`java -jar target/ciip-grp8-password-manager-1.0-SNAPSHOT.jar`
## Contributors
- binsky - Timo Triebensky
- fdai6352 - Pascal Schubert
- fdai5728 - Claudia Metzler
## Beim Testen beachten!
- zwischen den Commits `d1652f044327f4845e11db0cce6ef6c4fb392113` und `a81194074a49eabe723e7ad599411d45545a5b1d` werden die Maven Tests auf Grund einer fehlerhaften Änderung in der pom.xml nicht ausgeführt. Die JUnit Tests sollten aber dennoch funktionieren. Maven sagt lediglich, dass alles in Ordnung ist, auch wenn keine Tests ausgeführt werden. Daher ist das Problem erst etwas später aufgefallen.
- ab dem Commit `a81194074a49eabe723e7ad599411d45545a5b1d` kann auf die oben beschriebene Weise ein Artefakt erfolgreich gebaut und ausgeführt werden. Bauen hat auch vorher schon funktioniert, aber die jar Datei konnte nicht ausgeführt werden.
- für die Tests ist eine Netzwerkverbindung, sowie funktionierendes DNS nötig, da eine Verbindung zu api.pwnedpasswords.com aufgebaut wird.
- da für ein erstes Release noch nicht genug Funktionalität implementiert ist, gab es bisher noch keinen Merge/Pull Request auf den main Branch.

27
pom.xml

@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.ciip-gruppe8-password-manager</groupId>
<artifactId>ciip-gruppe8-password-manager</artifactId>
<groupId>org.ciip-grp8-password-manager</groupId>
<artifactId>ciip-grp8-password-manager</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
@ -70,9 +70,26 @@
<version>5.7.0</version>
</dependency>
</dependencies>
<!-- <configuration>
<argLine>${argLine}</argLine>
</configuration> -->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
</dependency>
</dependencies>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>PasswordManager</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>

28
src/main/java/HttpApi.java

@ -0,0 +1,28 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpApi {
public static String sendHttpGETRequest(String url) throws IOException {
URL obj = new URL(url);
HttpURLConnection httpURLConnection = (HttpURLConnection) obj.openConnection();
httpURLConnection.setRequestMethod("GET");
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine + "\n");
}
in.close();
return response.toString();
}
return null;
}
}

119
src/main/java/PasswordGenerator.java

@ -0,0 +1,119 @@
import java.security.SecureRandom;
public class PasswordGenerator {
final String lowercaseCharacters = "abcdefghjkmnpqrstuvwxyz";
final String uppercaseCharacters = "ABCDEFGHJKMNPQRSTUVWXYZ";
final String digits = "0123456789";
final String specialCharacters = ".!?=@#$()%^&/*_-+";
final SecureRandom rand = new SecureRandom();
private int length = 12;
private boolean useUppercase = true;
private boolean useLowercase = true;
private boolean useDigits = true;
private boolean useSpecialCharacters = true;
private boolean requireEveryConfiguredCharacterType = true;
public String generateRandomPassword() {
StringBuilder generatedPassword = new StringBuilder();
String characterPool = "";
if (isUseLowercase()) {
characterPool += lowercaseCharacters;
}
if (isUseUppercase()) {
characterPool += uppercaseCharacters;
}
if (isUseDigits()) {
characterPool += digits;
}
if (isUseSpecialCharacters()) {
characterPool += specialCharacters;
}
for (int generatorPosition = 0; generatorPosition < getLength(); generatorPosition++) {
String customCharacterPool = characterPool;
if (isRequireEveryConfiguredCharacterType()) {
if (generatorPosition == 0 && isUseLowercase()) {
customCharacterPool = lowercaseCharacters;
} else if (generatorPosition == 1 && isUseUppercase()) {
customCharacterPool = uppercaseCharacters;
} else if (generatorPosition == 2 && isUseDigits()) {
customCharacterPool = digits;
} else if (generatorPosition == 3 && isUseSpecialCharacters()) {
customCharacterPool = specialCharacters;
} else {
customCharacterPool = characterPool;
}
}
generatedPassword.append(customCharacterPool.charAt(rand.nextInt(customCharacterPool.length())));
}
return shufflePassword(generatedPassword.toString());
}
public String shufflePassword(String password) {
StringBuilder shuffledPassword = new StringBuilder();
StringBuilder passwordCopy = new StringBuilder(password);
while (passwordCopy.length() != 0) {
int index = rand.nextInt(passwordCopy.length());
char c = passwordCopy.charAt(index);
shuffledPassword.append(c);
passwordCopy.deleteCharAt(index);
}
return shuffledPassword.toString();
}
public boolean isUseUppercase() {
return useUppercase;
}
public void setUseUppercase(boolean useUppercase) {
this.useUppercase = useUppercase;
}
public boolean isUseLowercase() {
return useLowercase;
}
public void setUseLowercase(boolean useLowercase) {
this.useLowercase = useLowercase;
}
public boolean isUseDigits() {
return useDigits;
}
public void setUseDigits(boolean useDigits) {
this.useDigits = useDigits;
}
public boolean isUseSpecialCharacters() {
return useSpecialCharacters;
}
public void setUseSpecialCharacters(boolean useSpecialCharacters) {
this.useSpecialCharacters = useSpecialCharacters;
}
public boolean isRequireEveryConfiguredCharacterType() {
return requireEveryConfiguredCharacterType;
}
public void setRequireEveryConfiguredCharacterType(boolean requireEveryConfiguredCharacterType) {
this.requireEveryConfiguredCharacterType = requireEveryConfiguredCharacterType;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
}

63
src/main/java/PasswordManager.java

@ -1,6 +1,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
@ -12,6 +13,9 @@ public class PasswordManager implements PasswordManagerInterface {
boolean running = true;
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
ArrayList<Vault> vaults = new ArrayList<>();
int selectedVaultId = -1;
ArrayList<String> vaultOperationOptions = new ArrayList<>();
public static void main(String[] args) {
PasswordManager pm = new PasswordManager();
@ -26,11 +30,6 @@ public class PasswordManager implements PasswordManagerInterface {
println("Hello World");
}
@Override
public void listVaults() {
println("Vaults:");
}
private void println(String output) {
try {
outputStream.write((output + "\n").getBytes(StandardCharsets.UTF_8));
@ -39,6 +38,18 @@ public class PasswordManager implements PasswordManagerInterface {
}
}
@Override
public void listVaults() {
println("Vaults:");
for (int i = 0; i < vaults.size(); i++) {
println("- vault id: " + i);
}
}
public void createNewVault() {
vaults.add(new Vault());
}
@Override
public void openVault() {
@ -53,8 +64,10 @@ public class PasswordManager implements PasswordManagerInterface {
sb.append("\nciip Gruppe 8 - Password Manager\n\n");
sb.append("Menu:\n");
sb.append("- list vaults: l:\n");
sb.append("- select vault: v x (replace x with vault id)\n");
sb.append("- list vaults: l\n");
sb.append("- create new vault: v\n");
sb.append("- select vault and show operations: v x (replace x with vault id)\n");
sb.append("- select vault operation: o x (replace o with a operation id for the selected vault)\n");
sb.append("- exit: e\n");
println(sb.toString());
@ -65,7 +78,9 @@ public class PasswordManager implements PasswordManagerInterface {
running = false;
} else if (input.equals("l")) {
listVaults();
} else if (input.startsWith("v")) {
} else if (input.equals("v")) {
createNewVault();
} else if (input.startsWith("v")) {
String vaultAction = (input.replace('v', ' ')).trim();
int vaultId = -1;
@ -76,14 +91,16 @@ public class PasswordManager implements PasswordManagerInterface {
}
if (vaultId >= 0) {
selectedVaultId = vaultId;
println("\nVault " + vaultId + " selected.");
try {
int internalOptionCounter = 0;
ArrayList<String> options = new ArrayList<>();
println("\nAvailable vault operations:");
for (Method m : Class.forName("Vault").getDeclaredMethods()) { // returns all declared methods including private or protected
try {
if (Modifier.isPublic(this.getClass().getDeclaredMethod(m.getName()).getModifiers())) { // filter out methods that are not public (using Modifier) or have arguments (using getDeclaredMethod)
options.add(m.getName());
if (Modifier.isPublic(Class.forName("Vault").getDeclaredMethod(m.getName()).getModifiers())) { // filter out methods that are not public (using Modifier) or have arguments (using getDeclaredMethod)
vaultOperationOptions.add(m.getName());
println(internalOptionCounter + " - " + m.getName());
internalOptionCounter++;
}
@ -95,6 +112,30 @@ public class PasswordManager implements PasswordManagerInterface {
println("-- vaults not implemented yet");
}
}
} else if (input.startsWith("o")) {
String operation = (input.replace('o', ' ')).trim();
int operationId = -1;
try {
operationId = Integer.parseInt(operation);
} catch (NumberFormatException e) {
println("-- please enter a valid operation id");
}
if (selectedVaultId < 0) {
println("-- a vault needs to be selected");
} else if (operationId >= 0 && operationId < vaultOperationOptions.size()) {
Vault vault = vaults.get(selectedVaultId);
try {
println("Run selected operation '" + vaultOperationOptions.get(operationId) + "':");
vault.getClass().getDeclaredMethod(vaultOperationOptions.get(operationId)).invoke(vault);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
println("-- selected operation failed");
}
} else {
println("-- please enter a valid operation id");
}
}
}
}

166
src/main/java/PasswordValidator.java

@ -0,0 +1,166 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
import java.util.regex.Pattern;
public class PasswordValidator {
int minLength = 6;
boolean requireUppercase = true;
boolean requireLowercase = true;
boolean requireDigit = true;
boolean requireSpecialChar = true;
boolean checkPwned = true;
boolean checkWordlist = false;
private final Pattern uppercasePattern = Pattern.compile("^(?=.*[A-Z]).+$");
private final Pattern lowercasePattern = Pattern.compile("^(?=.*[a-z]).+$");
private final Pattern digitPattern = Pattern.compile("^(?=.*\\d).+$");
private final Pattern specialCharPattern = Pattern.compile("^(?=.*[.!?=@#$()%^&/*_\\-+]).+$");
private static final String pwnedPasswordsApiUrl = "https://api.pwnedpasswords.com/range/";
public boolean validate(String password) {
if (password.length() < minLength) {
return false;
} else if (requireUppercase && !uppercasePattern.matcher(password).matches()) {
return false;
} else if (requireLowercase && !lowercasePattern.matcher(password).matches()) {
return false;
} else if (requireDigit && !digitPattern.matcher(password).matches()) {
return false;
} else if (requireSpecialChar && !specialCharPattern.matcher(password).matches()) {
return false;
} else if (checkWordlist && isInWordlist(password)) {
return false;
} else if (checkPwned && isPwned(password)) {
return false;
}
return true;
}
public int getMinLength() {
return minLength;
}
public void setMinLength(int minLength) {
this.minLength = minLength;
}
public boolean isRequireUppercase() {
return requireUppercase;
}
public void setRequireUppercase(boolean requireUppercase) {
this.requireUppercase = requireUppercase;
}
public boolean isRequireLowercase() {
return requireLowercase;
}
public void setRequireLowercase(boolean requireLowercase) {
this.requireLowercase = requireLowercase;
}
public boolean isRequireDigit() {
return requireDigit;
}
public void setRequireDigit(boolean requireDigit) {
this.requireDigit = requireDigit;
}
public boolean isRequireSpecialChar() {
return requireSpecialChar;
}
public void setRequireSpecialChar(boolean requireSpecialChar) {
this.requireSpecialChar = requireSpecialChar;
}
public boolean isCheckPwned() {
return checkPwned;
}
public void setCheckPwned(boolean checkPwned) {
this.checkPwned = checkPwned;
}
public boolean isCheckWordlist() {
return checkWordlist;
}
public void setCheckWordlist(boolean checkWordlist) {
this.checkWordlist = checkWordlist;
}
public static String getSHA1Hash(String input) {
if (input.length() > 0) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] messageDigest = md.digest(input.getBytes());
// Convert byte array into signum representation
BigInteger no = new BigInteger(1, messageDigest);
// Convert message digest into hex value
StringBuilder hashtext = new StringBuilder();
hashtext.append(no.toString(16));
// Add preceding 0s to make it 32 bit
while (hashtext.length() < 32) {
hashtext.insert(0, "0");
}
return hashtext.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
return null;
}
public static boolean isPwned(String password) {
String sha1 = PasswordValidator.getSHA1Hash(password);
if (sha1 != null) {
String url = pwnedPasswordsApiUrl + sha1.substring(0, 5);
try {
String result = HttpApi.sendHttpGETRequest(url);
BufferedReader bufReader = new BufferedReader(new StringReader(result));
String line = null;
while ((line = bufReader.readLine()) != null) {
String[] lineSplit = line.split(":");
if (lineSplit.length > 0 && sha1.toUpperCase().endsWith(lineSplit[0])) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
public static boolean isInWordlist(String password) {
try {
String lowerPassword = password.toLowerCase();
ResourceApi resourceApi = new ResourceApi();
String germanWordlist = resourceApi.getFileFromResourceAsString("german_wordlist.txt");
BufferedReader bufReader = new BufferedReader(new StringReader(germanWordlist));
String line = null;
while ((line = bufReader.readLine()) != null) {
if (lowerPassword.contains(line.trim().toLowerCase())) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}

37
src/main/java/ResourceApi.java

@ -0,0 +1,37 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ResourceApi {
public String getFileFromResourceAsString(String fileName) throws IOException {
InputStream inputStream = getFileFromResourceAsStream(fileName);
return getStringFromInputStream(inputStream);
}
public InputStream getFileFromResourceAsStream(String fileName) {
//ClassLoader classLoader = getClass().getClassLoader();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(fileName);
if (inputStream == null) {
throw new IllegalArgumentException("file not found! " + fileName);
} else {
return inputStream;
}
}
public String getStringFromInputStream(InputStream inputStream) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine + "\n");
}
in.close();
return response.toString();
}
}

50
src/main/java/Storage.java

@ -0,0 +1,50 @@
import java.io.*;
import java.util.Scanner;
public class Storage implements StorageInterface {
@Override
public void export() {
}
@Override
public void load() {
}
public boolean writeFile(String path, String content) {
if (!path.isEmpty() && !content.isEmpty()) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(path, false));
writer.append(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
return false;
}
public String readFile(String path) {
if (!path.isEmpty()) {
StringBuilder data = new StringBuilder();
try {
File f = new File(path);
Scanner myReader = new Scanner(f);
while (myReader.hasNextLine()) {
data.append(myReader.nextLine());
}
myReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return data.toString();
}
return null;
}
}

4
src/main/java/StorageInterface.java

@ -0,0 +1,4 @@
public interface StorageInterface {
public void export();
public void load();
}

85
src/main/java/Vault.java

@ -14,10 +14,22 @@ public class Vault implements VaultInterface {
public boolean credentialM;
public String userName;
public String password;
public int newID;
public String newString;
public boolean decision;
public boolean isInt = false;
InputStream inputS = System.in;
OutputStream outputS = System.out;
private CredentialRepository credentialRepository = new CredentialRepository();
public static void main (String args[]) {
Vault vault = new Vault();
vault.credentialMenu();
}
private void println(String output) {
try {
outputS.write((output + "\n").getBytes(StandardCharsets.UTF_8));
@ -63,7 +75,7 @@ public class Vault implements VaultInterface {
}
}
public void setPWLength(String pwLength){
public void setPWLength(String pwLength) {
try {
PWLength = Integer.parseInt(pwLength);
} catch (NumberFormatException e) {
@ -74,33 +86,22 @@ public class Vault implements VaultInterface {
}
public void addCredential(){
Scanner scan = new Scanner(inputS);
println("Type in username");
userName = scan.nextLine();
println("Type in password");
password = scan.nextLine();
//createNewCredential(userName, password);
public void addCredential(String userName, String password){
credentialRepository.createNewCredential(userName, password);
}
public void showCredential(){
Scanner scan = new Scanner(inputS);
println("Type in ID or username");
String str = scan.nextLine();
public void showCredential(String str) {
if(str.matches("[0-9]+")) {
isInt = true;
//getCredentialsViaId(Integer.parseInt(str));
println("Getting credential via ID");
credentialRepository.getCredentialsViaId(Integer.parseInt(str));
} else {
isInt = false;
//getCredentialsViaName(str);
}
println("Getting credential via name");
credentialRepository.getCredentialsViaName(str);
}
}
public void getAsJson(){
}
@ -116,7 +117,7 @@ public class Vault implements VaultInterface {
println("Your PWs contain now capitals.");
}else if(input.equals("no")){
haveCapitals = false;
println("Your PWs don´t have capitals anymore.");
println("Your PWs don't have capitals anymore.");
}
}
@ -128,7 +129,7 @@ public class Vault implements VaultInterface {
println("Your PWs contain now special characters.");
}else if(input.equals("no")){
hasSpecialChars = false;
println("Your PWs don´t have special characters anymore.");
println("Your PWs don't have special characters anymore.");
}
}
@ -139,7 +140,7 @@ public class Vault implements VaultInterface {
println("Your PWs contains now numbers.");
}else if(input.equals("no")){
hasNumbers = false;
println("Your PWs don´t have numbers anymore.");
println("Your PWs don't have numbers anymore.");
}
}
@ -158,14 +159,40 @@ public class Vault implements VaultInterface {
String input = scan.nextLine();
if (input.equals("e")) {
credentialM = false;
} else if (input.equals("a")) {
println("Type username:");
} else if (input.equals("c")) {
println("Type username or ID to show credential:");
}
if (input.equals("a")) {
println("Type in username");
userName = scan.nextLine();
println("Type in password");
password = scan.nextLine();
addCredential(userName, password);
}
if (input.equals("c")) {
println("Type in ID or username");
String str = scan.nextLine();
showCredential(str);
} else if (input.equals("l")) {
println("Type username or ID to select credential:");
println("Type ID to select credential:");
newID = Integer.parseInt(scan.nextLine());
println("-change username: u\n-change password: p");
input = scan.nextLine();
if (input.equals("u")) {
decision = true;
}else{
decision = false;
}
println("Type new:");
newString = scan.nextLine();
//editCredential(newID, newString, decision);
}
}
}

4
src/main/java/VaultInterface.java

@ -3,8 +3,8 @@
public interface VaultInterface {
void configure();
void addCredential();
void showCredential();
void addCredential(String userName, String password);
void showCredential(String str);
void getAsJson();
void loadFromJson();
}

137465
src/main/resources/german_wordlist.txt
File diff suppressed because it is too large
View File

19
src/test/java/HttpApiTest.java

@ -0,0 +1,19 @@
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.*;
class HttpApiTest {
@Test
void sendHttpGETRequest() {
assertDoesNotThrow(() -> HttpApi.sendHttpGETRequest("https://httpbin.org/get"));
try {
assertTrue(Objects.requireNonNull(HttpApi.sendHttpGETRequest("https://httpbin.org/get")).contains("args"));
} catch (IOException e) {
e.printStackTrace();
}
}
}

72
src/test/java/PasswordGeneratorTest.java

@ -0,0 +1,72 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.*;
class PasswordGeneratorTest {
static PasswordGenerator passwordGenerator;
@BeforeAll
static void init() {
passwordGenerator = new PasswordGenerator();
}
@Test
void testGeneratedPasswordLength() {
assertNotSame("", passwordGenerator.generateRandomPassword());
assertEquals(passwordGenerator.generateRandomPassword().length(), passwordGenerator.getLength());
passwordGenerator.setLength(33);
assertEquals(passwordGenerator.getLength(), 33);
assertEquals(passwordGenerator.generateRandomPassword().length(), passwordGenerator.getLength());
}
@Test
void testPasswordLowercaseRequirement() {
passwordGenerator.setUseLowercase(false);
assertFalse(Pattern.compile("^(?=.*[a-z]).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
passwordGenerator.setUseLowercase(true);
assertTrue(Pattern.compile("^(?=.*[a-z]).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
}
@Test
void testPasswordUppercaseRequirement() {
passwordGenerator.setUseUppercase(false);
assertFalse(Pattern.compile("^(?=.*[A-Z]).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
passwordGenerator.setUseUppercase(true);
assertTrue(Pattern.compile("^(?=.*[A-Z]).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
}
@Test
void testPasswordDigitsRequirement() {
passwordGenerator.setUseDigits(false);
assertFalse(Pattern.compile("^(?=.*\\d).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
passwordGenerator.setUseDigits(true);
assertTrue(Pattern.compile("^(?=.*\\d).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
}
@Test
void testPasswordSpecialCharactersRequirement() {
passwordGenerator.setUseSpecialCharacters(false);
assertFalse(Pattern.compile("^(?=.*[.!?=@#$()%^&/*_\\-+]).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
passwordGenerator.setUseSpecialCharacters(true);
assertTrue(Pattern.compile("^(?=.*[.!?=@#$()%^&/*_\\-+]).+$").matcher(passwordGenerator.generateRandomPassword()).matches());
}
@Test
void testPasswordForEveryRequiredCharacter() {
passwordGenerator.setRequireEveryConfiguredCharacterType(true);
PasswordValidator passwordValidator = new PasswordValidator();
assertTrue(passwordValidator.validate(passwordGenerator.generateRandomPassword()));
}
@Test
void testShufflePassword() {
String testInput = "ABcdefgh123";
assertNotEquals(passwordGenerator.shufflePassword(testInput), testInput);
assertEquals(passwordGenerator.shufflePassword(testInput).length(), testInput.length());
}
}

55
src/test/java/PasswordManagerTest.java

@ -46,7 +46,18 @@ class PasswordManagerTest {
pm.inputStream = new ByteArrayInputStream("l\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = outputStream;
pm.showMenu();
assertTrue(outputStream.toString().endsWith("Vaults:\n"));
pm.createNewVault();
assertTrue(outputStream.toString().contains("Vaults:\n- vault id: 0\n"));
}
@Test
void menuNavigationCreateNewVault() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pm.inputStream = new ByteArrayInputStream("v\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = outputStream;
int vaultCount = pm.vaults.size();
pm.showMenu();
assertEquals(vaultCount + 1, pm.vaults.size());
}
@Test
@ -58,6 +69,41 @@ class PasswordManagerTest {
assertFalse(outputStream.toString().endsWith("-- vaults not implemented yet\n"));
}
@Test
void menuNavigationSelectVaultOperation() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pm.inputStream = new ByteArrayInputStream("v\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = new ByteArrayOutputStream();
pm.showMenu();
pm.inputStream = new ByteArrayInputStream("v 0\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = new ByteArrayOutputStream();
pm.showMenu();
System.out.println(pm.outputStream.toString());
pm.inputStream = new ByteArrayInputStream("o 0\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = outputStream;
pm.vaults.get(0).inputS = new ByteArrayInputStream("e\n".getBytes(StandardCharsets.UTF_8));
pm.showMenu();
assertTrue(outputStream.toString().contains("Run selected operation"));
outputStream = new ByteArrayOutputStream();
pm.inputStream = new ByteArrayInputStream("o foobert\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = outputStream;
pm.showMenu();
assertTrue(outputStream.toString().endsWith("-- please enter a valid operation id\n"));
outputStream = new ByteArrayOutputStream();
pm.inputStream = new ByteArrayInputStream("o 1000\n".getBytes(StandardCharsets.UTF_8));
pm.outputStream = outputStream;
pm.showMenu();
System.out.println(outputStream);
assertTrue(outputStream.toString().endsWith("-- please enter a valid operation id\n"));
}
@Test
void showMenu() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
@ -88,6 +134,13 @@ class PasswordManagerTest {
assertTrue(outputStream.toString().startsWith("\nciip Gruppe 8"));
}
@Test
void createNewVault() {
int vaultCount = pm.vaults.size();
pm.createNewVault();
assertEquals(vaultCount + 1, pm.vaults.size());
}
private ByteArrayInputStream getEmptyStringInputStream() {
return new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
}

130
src/test/java/PasswordValidatorTest.java

@ -0,0 +1,130 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PasswordValidatorTest {
static PasswordValidator passwordValidator = new PasswordValidator();
@BeforeAll
static void init() {
passwordValidator = new PasswordValidator();
}
@Test
void testMinimumPasswordLength() {
assertFalse(passwordValidator.validate(""));
passwordValidator.setMinLength(6);
passwordValidator.setRequireUppercase(false);
passwordValidator.setRequireLowercase(false);
passwordValidator.setRequireDigit(false);
passwordValidator.setCheckPwned(false);
passwordValidator.setRequireSpecialChar(false);
assertFalse(passwordValidator.validate("abcde"));
assertTrue(passwordValidator.validate("abcdef"));
assertTrue(passwordValidator.validate("abcdefg"));
}
@Test
void testUppercasePasswordRequirement() {
passwordValidator.setRequireUppercase(true);
passwordValidator.setRequireLowercase(false);
passwordValidator.setRequireDigit(false);
passwordValidator.setCheckPwned(false);
passwordValidator.setRequireSpecialChar(false);
assertFalse(passwordValidator.validate("abcdef"));
assertTrue(passwordValidator.validate("abCdef"));
assertTrue(passwordValidator.validate("ABCDEF"));
}
@Test
void testLowercasePasswordRequirement() {
passwordValidator.setRequireUppercase(true);
passwordValidator.setRequireLowercase(true);
passwordValidator.setRequireDigit(false);
passwordValidator.setCheckPwned(false);
passwordValidator.setRequireSpecialChar(false);
assertFalse(passwordValidator.validate("abcdef"));
assertTrue(passwordValidator.validate("abCdef"));
assertFalse(passwordValidator.validate("ABCDEF"));
}
@Test
void testDigitsPasswordRequirement() {
passwordValidator.setRequireUppercase(true);
passwordValidator.setRequireLowercase(true);
passwordValidator.setRequireDigit(true);
passwordValidator.setCheckPwned(false);
passwordValidator.setRequireSpecialChar(false);
assertFalse(passwordValidator.validate("8"));
assertFalse(passwordValidator.validate("12345678"));
assertFalse(passwordValidator.validate("abcdef"));
assertFalse(passwordValidator.validate("abcdef8"));
assertFalse(passwordValidator.validate("abCdef"));
assertFalse(passwordValidator.validate("ABCDEF"));
assertFalse(passwordValidator.validate("ABCDEF8"));
assertTrue(passwordValidator.validate("abCDE8F"));
}
@Test
void testSpecialCharsPasswordRequirement() {
passwordValidator.setRequireUppercase(true);
passwordValidator.setRequireLowercase(true);
passwordValidator.setRequireDigit(true);
passwordValidator.setCheckPwned(false);
passwordValidator.setRequireSpecialChar(true);
assertFalse(passwordValidator.validate("*"));
assertFalse(passwordValidator.validate("abCDE8F"));
assertTrue(passwordValidator.validate("abCDE8_F"));
assertTrue(passwordValidator.validate("abCDE*/8_F"));
}
/**
* Requires a network connection and DNS to be set up.
*/
@Test
void testPasswordPwnedCheck() {
passwordValidator.setRequireUppercase(true);
passwordValidator.setRequireLowercase(true);
passwordValidator.setRequireDigit(true);
passwordValidator.setCheckPwned(true);
assertFalse(passwordValidator.validate("8"));
assertFalse(passwordValidator.validate("asdf12"));
assertTrue(passwordValidator.validate("=phan0johB4aisae6Mie0jeip9Saejahc0iuvuth7ahv9uoni6o*_.+"));
}
@Test
void testPasswordWordlistCheck() {
passwordValidator.setRequireUppercase(true);
passwordValidator.setRequireLowercase(true);
passwordValidator.setRequireDigit(true);
passwordValidator.setCheckPwned(true);
passwordValidator.setCheckWordlist(true);
assertFalse(passwordValidator.validate("8"));
assertFalse(passwordValidator.validate("_Sonnenblume123"));
assertTrue(passwordValidator.validate("=phan0johB4aisae6Mie0jeip9Saejahc0iuvuth7ahv9uoni6o*_.+"));
}
@Test
void getSHA1Hash() {
assertEquals("356A192B7913B04C54574D18C28D46E6395428AB".toLowerCase(), PasswordValidator.getSHA1Hash("1"));
assertEquals("A233F0E898ED0661D6D47ED0958F16B52E537231".toLowerCase(), PasswordValidator.getSHA1Hash("asdf12"));
assertNull(PasswordValidator.getSHA1Hash(""));
}
@Test
void isPwned() {
assertTrue(PasswordValidator.isPwned("asdf12"));
assertFalse(PasswordValidator.isPwned("=phan0johB4aisae6Mie0jeip9Saejahc0iuvuth7ahv9uoni6o*_.+"));
assertFalse(PasswordValidator.isPwned(""));
}
@Test
void isInWordlist() {
assertTrue(PasswordValidator.isInWordlist("Sonnenblume"));
assertTrue(PasswordValidator.isInWordlist("_Sonnenblume123"));
assertFalse(PasswordValidator.isInWordlist("=phan0johB4aisae6Mie0jeip9Saejahc0iuvuth7ahv9uoni6o*_.+"));
}
}

48
src/test/java/ResourceApiTest.java

@ -0,0 +1,48 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.*;
class ResourceApiTest {
private static ResourceApi resourceApi;
@BeforeAll
static void init() {
resourceApi = new ResourceApi();
}
@Test
void getFileFromResourceAsStream() throws IOException {
assertThrowsExactly(IllegalArgumentException.class,
() -> resourceApi.getFileFromResourceAsStream("does_not_exist"));
InputStream is = resourceApi.getFileFromResourceAsStream("german_wordlist.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine + "\n");
}
in.close();
assertTrue(response.toString().contains("Alleinherrschaft"));
}
@Test
void getStringFromInputStream() throws IOException {
String testString = "I am a test string!\nAnother test line.\n";
InputStream is = new ByteArrayInputStream(testString.getBytes(StandardCharsets.UTF_8));
assertEquals(resourceApi.getStringFromInputStream(is), testString);
}
@Test
void getFileFromResourceAsString() throws IOException {
assertTrue(resourceApi.getFileFromResourceAsString("german_wordlist.txt").contains("Alleinherrschaft"));
}
}

62
src/test/java/StorageTest.java

@ -0,0 +1,62 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.File;
import static org.junit.jupiter.api.Assertions.*;
class StorageTest {
static Storage storage;
static String testFilePath = "/tmp/test.txt";
@BeforeAll
static void init() {
storage = new Storage();
if (System.getProperty("os.name").toLowerCase().contains("win")) {
testFilePath = "C:\\test.txt";
}
}
@AfterAll
static void clear() {
File myObj = new File(testFilePath);
myObj.delete();
}
@Test
void constructor() {
assertInstanceOf(Storage.class, storage);
}
@Test
void export() {
}
@Test
void load() {
}
@Test
void writeFile() {
String content = "test";
assertTrue(storage.writeFile(testFilePath, content));
File f = new File(testFilePath);
assertTrue(f.isFile());
}
@Test
void readFile() {
String content = "test";
File f = new File(testFilePath);
if (!f.isFile()) {
assertTrue(storage.writeFile(testFilePath, content));
}
assertEquals(content, storage.readFile(testFilePath));
}
}

51
src/test/java/VaultTest.java

@ -24,7 +24,7 @@ public class VaultTest {
@BeforeEach
void reset() {
vlt.outputS = System.out;
vlt.inputS = System.in;
vlt.inputS = getEmptyStringInputStream();
}
@Test
@ -47,16 +47,20 @@ public class VaultTest {
@Test
void openAddCredentialMenuItem() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.inputS = new ByteArrayInputStream("a".getBytes(StandardCharsets.UTF_8));
vlt.inputS = new ByteArrayInputStream("a\npeter\npassword".getBytes(StandardCharsets.UTF_8));
vlt.outputS = outputStream;
vlt.credentialMenu();
assertTrue(outputStream.toString().contains("Type"));
assertTrue(outputStream.toString().contains("username"));
assertEquals("peter", vlt.userName);
assertTrue(outputStream.toString().contains("password"));
assertEquals("password",vlt.password);
}
@Test
void openShowCredentialMenuItem() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.inputS = new ByteArrayInputStream("c".getBytes(StandardCharsets.UTF_8));
vlt.inputS = new ByteArrayInputStream("c\n1".getBytes(StandardCharsets.UTF_8));
vlt.outputS = outputStream;
vlt.credentialMenu();
assertTrue(outputStream.toString().contains("Type"));
@ -65,13 +69,21 @@ public class VaultTest {
@Test
void openEditCredentialMenuItem() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.inputS = new ByteArrayInputStream("l".getBytes(StandardCharsets.UTF_8));
vlt.inputS = new ByteArrayInputStream("l\n1\nu\npeter".getBytes(StandardCharsets.UTF_8));
vlt.outputS = outputStream;
vlt.credentialMenu();
assertTrue(outputStream.toString().contains("Type"));
assertEquals(1,vlt.newID);
assertEquals(true,vlt.decision);
assertEquals("peter",vlt.newString);
}
@Test
/*@Test
void editCredentialTest() {
}*/
/*@Test
void addCredentialTest() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.outputS = outputStream;
@ -86,21 +98,16 @@ public class VaultTest {
@Test
void showCredentialTest() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.outputS = outputStream;
vlt.inputS = new ByteArrayInputStream("1".getBytes(StandardCharsets.UTF_8));
vlt.showCredential();
vlt.inputS = new ByteArrayInputStream("l\n1".getBytes(StandardCharsets.UTF_8));
vlt.credentialMenu();
assertTrue(outputStream.toString().contains("Type"));
assertTrue(vlt.isInt);
vlt.outputS = outputStream;
vlt.inputS = new ByteArrayInputStream("peter".getBytes(StandardCharsets.UTF_8));
vlt.showCredential();
vlt.inputS = new ByteArrayInputStream("l\npeter".getBytes(StandardCharsets.UTF_8));
vlt.credentialMenu();
assertTrue(outputStream.toString().contains("Type"));
assertFalse(vlt.isInt);
}
}*/
@Test
void getAsJson() {vlt.getAsJson();}
@ -108,7 +115,7 @@ public class VaultTest {
@Test
void loadFromJson() {vlt.loadFromJson();}
@Test
@Test
void openConfigureMenu() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.inputS = new ByteArrayInputStream("__\n".getBytes(StandardCharsets.UTF_8));
@ -124,7 +131,7 @@ public class VaultTest {
assertFalse(vlt.config);
}
@Test
@Test
void doNotExitConfigAfterWrongInput() {
vlt.inputS = new ByteArrayInputStream("__\n".getBytes(StandardCharsets.UTF_8));
vlt.configure();
@ -138,7 +145,7 @@ public class VaultTest {
assertTrue(outputStream.toString().startsWith("Configure:"));
}
@Test
@Test
void openSetPWLengthMenuItem() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
vlt.inputS = new ByteArrayInputStream("l\n7".getBytes(StandardCharsets.UTF_8));
@ -180,7 +187,7 @@ public class VaultTest {
vlt.setCapital("no");
assertFalse(vlt.haveCapitals = false);
assertTrue(outputStream.toString().contains("don´t"));
assertTrue(outputStream.toString().contains("don't"));
}
@Test
@ -204,7 +211,7 @@ public class VaultTest {
vlt.setSpecialChar("no");
assertFalse(vlt.hasSpecialChars = false);
assertTrue(outputStream.toString().contains("don´t"));
assertTrue(outputStream.toString().contains("don't"));
}
@Test
@ -229,7 +236,7 @@ public class VaultTest {
vlt.setNumbers("no");
assertFalse(vlt.hasNumbers = false);
assertTrue(outputStream.toString().contains("don´t"));
assertTrue(outputStream.toString().contains("don't"));
}
private ByteArrayInputStream getEmptyStringInputStream() {

Loading…
Cancel
Save