This commit is contained in:
2020-11-23 22:30:17 +01:00
parent e0ae2514ba
commit 1d7e61a2d6
3 changed files with 80 additions and 19 deletions

57
j1-Passwoerter/README.md Normal file
View File

@ -0,0 +1,57 @@
# Allgemeine Informationen
Die Grundidee für meinen Passwortgenerator ist das Passwort aus richtigen Wörtern zu bilden.
Als erstes Argument muss man einen Dateipfad zu der Textdatei mit einer Liste von Wörtern, die von einem Zeilenumbruch getrennt sind, verwenden.
Unter wörter.txt ist ein Beispiel dafür ([Quelle](https://www.netzmafia.de/software/wordlists/deutsch.txt)).
Das Passwort wird zu stdout ausgegeben.
# Regeln für das generierte Passwort
1. Zufällige Wörter werden aus der Wörterliste ausgewählt.
2. Am Anfang des Passworts und zwischen den Wörtern steht eine Ziffer.
3. Am Ende steht ein Satzzeichen.
# Funktionsweise
Als erstes wird die angebene Textdatei mit der Wörterliste ausgelesen.
Alle Zeilenumbrüche werden durch \0 ersetzt und Pointer zu jedem Wort in einem Array gespeichert.
```
for(char *i = woerterText; (uintptr_t)i < dest; ++i) {
if(*i == '\n') {
char *nextWord = i + 1;
woerter = acl_arraylist_append(woerter, &nextWord);
pointerCheck(woerter);
*i = '\0';
}
}
```
Danach werden Bytes mit zufälligen Werten von `/dev/random` ausgelesen.<br>
` fread(randomInt, sizeof *randomInt, randomInt_len, randomFile);`<br>
Dafür habe ich mich entschieden, da dieser ein krypografisch sicherer Zufallszahlengenerator ist.
Passwörter, die mit Pseudozufallszahlengeneratoren generiert werden, sind einfach zu knacken, da bei diesen jede Zufallszahl von der vorherigen abhängt.
Oft wird als Startwert auch noch die aktuelle Zeit benutzt, was das Ganze noch unsicherer macht.
Auf Basis der Zufahlszahlen wird dann das Passwort aus Wörtern und Ziffern zusammengesetzt.
```
for(uint32_t i = wordsForPass_len; i < randomInt_len; ++i, ++j) {
char buf[2];
buf[1] = '\0';
sprintf(buf, "%" PRIu32, randomInt[i] % 10);
strcat(password, buf);
strcat(password, wordsForPass[j]);
}
```
Zum Schluss wird noch ein zufälliges Satzzeichen angehängt.
```
const char specialCharacter[] = {'?', '.', ',', '!', ';'};
char randomSpecialCharacter[] = {specialCharacter[randomInt[randomInt_len - 1]
% (sizeof specialCharacter - 1)], '\0'};
```
Dann wird das Passwort wird schließlich ausgegeben.
# Beispiel
Beipielausgabe: `0zaehneknirschend8verraeterischem6veranstaltet,`<br>
Die Textdatei in diesem Fall wörter.txt wurde ausgelesen, \\n durch \0 ersetzt um das Ende vom String zu markieren.
Danach wurden Pointer zu jedem Wort der Textdatei erstellt.
Anschließend wurden die Wörter zaehneknischend, verraeterischem, veranstaltet, die Ziffern 0, 8, 6 ausgewählt und zusammengesetzt.
Ein Komma wurde angehängt und das Passwort schließlich ausgegeben.

Binary file not shown.

View File

@ -1,13 +1,3 @@
/* Die Grundidee für meinen Passwortgenrator ist richtigen Wörtern zu bilden.
* Als erstes Argument muss man den Programm einen Dateipfad zu der Textdatei mit Liste von Wörtern, die mit \n getrennt sind.
* Unter wörter.txt ist ein Beispiel dafür. Quelle: https://www.netzmafia.de/software/wordlists/deutsch.txt
* Das Passwort wird zu stdout ausgegeben.
*
* Regeln für das generierte Passwort:
* 1. zufäfflige Wörter werden aus der Wörterliste ausgewählt.
* 2. Am Anfang des Passworts und zwischen den Wörtern steht eine Ziffer.
* 3. Am Ende steht ein Satzzeichen.
*/
#include <stdio.h>
#include <acl/file.h>
#include <string.h>
@ -19,7 +9,7 @@
#define wordCount 3 // Anzahl der Wörter des Passworts
#define randomInt_len (2 * wordCount)
#define wordsForPass_len randomInt_len / 2
void pointerCheck(void *pointer) {
void pointerCheck(void *pointer) { // Funktion um auf NULL Pointer zu checken und den Fehler auszugeben.
if(pointer == NULL) {
perror("Error: ");
exit(-1);
@ -27,33 +17,45 @@ void pointerCheck(void *pointer) {
}
int main(int argc, char *argv[]) {
if(argc != 2) printf("file argument required");
if(argc != 2) {
printf("file argument required"); // checkt ob der Nutzer die richtige Anzahl von Argumenten verwendet hat.
exit(-1);
}
bool sucess;
FILE *fp = fopen(argv[1], "rb"); // im binären Modus zu lesen ist deutlich schneller als im Textmodus, da man dort jede Zeile einzeln lesen muss. So wurde aus mehreren Sekunden Wartezeit keine bemerkbare Verzögerung.
/* im binären Modus zu lesen ist deutlich schneller als im Textmodus, da man dort jede Zeile einzeln lesen muss.
* So wurde aus mehreren Sekunden Wartezeit eine nicht bemerkbare Verzögerung. */
FILE *fp = fopen(argv[1], "rb");
char *woerterText = acl_ReadTextFile(fp, &sucess);
if(!sucess) perror("Error: ");
fclose(fp);
unsigned len = strlen(woerterText);
uintptr_t dest = (uintptr_t)woerterText + len;
char **woerter = acl_arraylist_create(1, sizeof *woerter);
/* erstellt ein Array für die Pointer zu den Wörtern.
* Man könnte auch erst die Zeilenumbrüche zählen, um den Arbeitsspeicher auf einmal anzufragen.
* Dies würde das Programm vermutlich etwas schneller machen.
* Jedoch ist das Programm so einfacher zu verstehen und im Vergleich zum Auslesen der Textdatei wäre die Geschwindigkeitsverbesserung sehr gering. */
char **woerter = acl_arraylist_create(1, sizeof *woerter);
pointerCheck(woerter);
woerter[0] = woerterText;
for(char *i = woerterText; (uintptr_t)i < dest; ++i) {
if(*i == '\n') {
char *nextWord = i + 1;
woerter = acl_arraylist_append(woerter, &nextWord); // Pointer werden zu Begin jedes Wortes erstellt.
woerter = acl_arraylist_append(woerter, &nextWord); // Pointer werden am Anfang jedes Wortes erstellt.
pointerCheck(woerter);
*i = '\0'; // \n wird mit \0 ersetzt um das Ende des Strings markieren.
*i = '\0'; // \n wird durch \0 ersetzt um das Ende des Strings markieren.
// diesen Weg habe ich gewählt um viele memory allocations zu vermeiden.
}
}
FILE *randomFile = fopen("/dev/random", "rb");
FILE *randomFile = fopen("/dev/random", "rb"); // /dev/random ist ein kryptografisch sicherer Zufallszahlengenerator.
uint32_t randomInt[randomInt_len];
fread(randomInt, sizeof *randomInt, randomInt_len, randomFile);
size_t passLen = wordsForPass_len + 1; // weil Ziffern im Passwort gleich oft vorkommen wie Wörter. + 1 für ein Satzzeichen am Ende
char *wordsForPass[wordsForPass_len];
// Die Länge des Passwortes wird berechnet.
for(uint32_t i = 0; i < wordsForPass_len; ++i) {
wordsForPass[i] = woerter[randomInt[i] % acl_arraylist_len(woerter)]; // der modulo operator wird verwendet um die Zahlfallszahl auf den gewünschten Zahlenbereich zu reduzieren.
wordsForPass[i] = woerter[randomInt[i] % acl_arraylist_len(woerter)]; // der modulo Operator wird verwendet um die Zufallszahl auf den gewünschten Zahlenbereich zu reduzieren.
passLen += strlen(wordsForPass[i]);
}
char *password = malloc(passLen + 1);
@ -66,7 +68,9 @@ int main(int argc, char *argv[]) {
strcat(password, buf);
strcat(password, wordsForPass[j]);
}
free(woerterText);
// ein zufälliges Sonderzeichen wird angehängt.
const char specialCharacter[] = {'?', '.', ',', '!', ';'};
char randomSpecialCharacter[] = {specialCharacter[randomInt[randomInt_len - 1] % (sizeof specialCharacter - 1)], '\0'};
printf("%s", strcat(password, randomSpecialCharacter));
printf("%s\n", strcat(password, randomSpecialCharacter));
}