Commit dd5818d2 authored by Jean-Yves's avatar Jean-Yves

added saving to a file

parent a0749461
......@@ -16,7 +16,7 @@ Well, if so, this generator is exactly what you are looking for.
# Warning
Be aware that if you run this utility on any machine you don't have fully control on, someone could be spying on you and thus get the generated password and salt. Run this **only** on environments you fully trust!
Be aware that if you run this utility on any machine you don't have fully control on, someone could be spying on you and thus get the generated password and salt. Run this **only** on environments you fully trust! Ideally, this should be run on a live CD after disconnecting the internet, and write down everything on paper.
# Requirements
......@@ -49,7 +49,9 @@ The program searches for regular expressions (regex) that you provide. The regex
On a decent machine, you can expect to search for 200 addresses per second. If you generate from seeds, you can reach 50k addresses per second, but you won't be able to log into Duniter clients, except Silkaj at the moment. This is very slow. So if the percentage of finding your regex is, say, 0.000001%, you would be ready to wait at least a month to get a result. That's a long time. So before thinking about what regex you want to search for, it is wise to get an estimate of the complexity of the search. You don't want to search for something if it will take 500 years to find it.
Public addresses are using 58 different characters. So, if you search for a word of 5 letters (case sensitive) at the beginning of the string, the probability of finding one is: (1/58)^5=.000000002. Which, at 200 keys a second, gives you roughly a 20 days time frame to find what you want. If you don't require it to be at the beginning of the key, then you multiply by the length of the string minus 5 (keys are 43 characters in length), which is roughly a day. But then your "beautiful string" may be in the very middle of the key, and people will not notice it.
Public addresses are using 62 different characters. So, if you search for a word of 5 letters (case sensitive) at the beginning of the string, the probability of finding one is: (1/62)^5=.000000001. Which, at 200 keys a second, gives you roughly a 50 days time frame to find what you want. If you don't require it to be at the beginning of the key, then you multiply by the length of the string minus 5 (keys are 43 characters in length), which is less than a day. But then your "beautiful string" may be in the very middle of the key, and people will not notice it.
In reality, things are a little more complex since characters are not used in a uniform distribution (try searching for "^a" and "^A"), but it gives some rough estimates of the time you'll have to wait before getting a result.
You can also get better odds by allowing non case sensitive matches, and even "hacker-style" characters (1 for l, 3 for E, etc.).
......@@ -59,12 +61,14 @@ If you're uncomfortable with statistics, you can just try out "easy" regex, such
# Usage
Usage: [-s][-n min max][-w wordfile [-f filler_type][-c]] regexfile
Usage: [-s][-n min max][-r|-R resultfile][-w wordfile [-f filler_type][-c]] regexfile
-n min max (optional): minimum and maximum number of characters/words to use to generate passwords.
-w wordfile (optional): generate passwords/salt using a list of words contained in the file "wordfile", rather than simply random characters.
-f type (optional) filler type between words: 0=spaces (default), 1=special characters and numbers, 2=none.
-c (optional): capitalize words (non capitalized by default - you can also capitalize the words in the given file).
-c (optional): capitalize the first character of words (non capitalized by default - you can also capitalize the words in the given file).
-r resultfile (optional): a file to which the results should be written to.
-R resultfile (optional): same as -r, but do not show the results found on the standard output.
-s (optional): Do not generate password/salt, but only a seed (!!!WARNING!!! You will not be able to connect with Sakia or Cesium with this).
regexfile (required): a file containing a list of regex (one per line). Lines beginning by a tab are ignored.
......
......@@ -16,7 +16,7 @@ Si c'est le cas, alors ce générateur est exactement ce qu'il vous faut!
# Avertissement
Si vous faites tourner cet utilitaire sur une machine dont vous n'avez pas le contrôle total, quelqu'un pourrait espionner votre terminal et s'emparer des mots de passe et sel générés. N'utilisez ce logiciel **que** sur des environnements dont vous êtes sûrs à 100%!
Si vous faites tourner cet utilitaire sur une machine dont vous n'avez pas le contrôle total, quelqu'un pourrait espionner votre terminal et s'emparer des mots de passe et sel générés. N'utilisez ce logiciel **que** sur des environnements dont vous êtes sûrs à 100%! Idéalement, vous devriez utiliser ceci sur un live CD (cédérom autonome) déconnecté de l'internet et noter les résultats sur un papier.
# Prérequis
- Un compilateur gcc, éventuellement l'outil make. Aucune librairie n'est nécessaire.
......@@ -48,7 +48,9 @@ Le programme cherche en fonction des expressions régulières (regex en anglais)
Sur une machine correcte, vous pouvez espérer atteindre 200 addresses par seconde. Si vous générez des clés à partir d'un noyau, vous pouvez atteindre 50k addresses par seconde, mais vous ne pourrez pas vous logger dans les clients classiques duniter (Cesium et Sakia), seul Silkaj (en ligne de commande) le supporte pour le moment. C'est dans tous les cas très lent. Si le pourcentage de chances de trouver une clé correspondant à votre expression régulière est de 0,000001%, vous devriez être prêt à attendre au moins un mois. C'est long. Alors, avant de vous jeter sur des expressions régulières, il est sage d'estimer le temps moyen pour trouver une adresse correspondante. Inutile de chercher une expression régulière s'il faut attendre 500 ans pour avoir un résultat.
Les adresses publiques utilisent 58 caractères différents. Alors, si vous cherchez un mot de 5 lettres (sensible à la casse) au tout début de la chaîne, la probabilité d'en trouver une est de : (1/58)^5=0,000000002. Ce qui fait, à 200 clés par seconde, un temps de recherche moyen de 20 jours. Si en revanche, vous cherchez votre chaîne n'importe où dans la clé publique, alors vous multipliez vos chances par la taille de la clé moins 5 (les clés font 43 caractères), ce qui ramène à peu près à un jour de recherche. Mais dans ce cas, votre magnifique nom ou expression risque d'être noyé en plein milieu de la clé, et ne sera pas visible.
Les adresses publiques utilisent 62 caractères différents. Alors, si vous cherchez un mot de 5 lettres (sensible à la casse) au tout début de la chaîne, la probabilité d'en trouver une est de : (1/62)^5=0,000000001. Ce qui fait, à 200 clés par seconde, un temps de recherche moyen d'environ 50 jours. Si en revanche, vous cherchez votre chaîne n'importe où dans la clé publique, alors vous multipliez vos chances par la taille de la clé moins 5 (les clés font 43 caractères), ce qui ramène à moins d'un jour de recherche. Mais dans ce cas, votre magnifique nom ou expression risque d'être noyé en plein milieu de la clé, et ne sera pas visible.
Dans la réalité c'est un peu plus complexe car les caractères ne sont pas utilisés uniformément (recherchez "^a" et "^A" par exemple) mais cela donne déjà un bon ordre de grandeur de la durée qu'il faudra attendre avant d'avoir un résultat.
Vous pouvez aussi améliorer vos chances (et donc raccourcir statistiquement le temps de recherche) en recherchant sans être sensible à la casse, voire même en utilisant le style « hackeur » (1 pour l, 3 pour E, etc.).
......@@ -58,12 +60,14 @@ Si vous n'êtes pas à l'aise avec les statistiques, vous pouvez commencer par r
# Usage
Usage: [-s][-n min max][-w fichiermots [-f typeremplissage][-c]] fichierexpressions
Usage: [-s][-n min max][-r|-R fichierresultat][-w fichiermots [-f typeremplissage][-c]] fichierexpressions
-n min max (optionnel): nombre minimum et maximum de caractères/mots à utiliser pour générer des mots de passe.
-w fichiermots (optionnel): générer des mots de passe/sel avec une liste de mots contenue dans le fichier « fichiermots », plutôt que générer à partir de caractères aléatoires.
-f typeremplissage (optionnel) type de remplissage entre les mots: 0=espaces (défaut), 1=caractères spéciaux et chiffres, 2=aucun.
-c (optionnel): met en majuscule le premier caractère de chaque mot (vous pouvez aussi mettre des mots avec majuscules dans le fichier de mots).
-r fichierresultat (optionnel): fichier dans lequel doivent être enregistrés les résultats.
-R fichierresultat (optionnel): même chose que -r, mais sans montrer les résultats sur la sortie standard.
-s (optionnel): Générer uniquement à partir d'un noyau, sans mot de passe/sel (!!!ATTENTION!!! Vous ne pourrez pas vous logger dans Sakia ou Cesium avec un noyau).
fichierexpressions (requis): un fichier contenant une liste d'expressions régulières (une par ligne). Les lignes commençant par une tabulation sont ignorées.
......
......@@ -6,6 +6,7 @@
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <time.h>
/*************************************************************/
/********************TRANSFORM SEED TO PK/SK *****************/
......@@ -4093,6 +4094,8 @@ unsigned char ** thread_signals;
int nb_threads = 0;
// Nb of explored combinations
int nb_explored = 0;
// Nb found
int nb_found = 0;
// To make sure we don't write in "nb_explored" simultaneously
pthread_mutex_t mutex_lock_explored;
// To make sure we don't write on stdout simultaneously
......@@ -4115,6 +4118,11 @@ int maxWordsSalt = 10;
#define BETWEEN_SPECIAL 1
#define BETWEEN_NONE 2
// The file to which results should be written to. If null, only write to stdout
FILE * resultfile;
// Show to stdout. If this is 0, then only a "found" will be shown (with a timestamp).
char resultStdout = 1;
int betweenWords = BETWEEN_SPACES;
// If 0 no capitalizing, if 1 capitalize all words
char capitalize = 0;
......@@ -4170,6 +4178,24 @@ int generateSentence(int minWords, int maxWords, char * result)
return pos;
}
// Shows the current time, along with statistics on number of keys found vs searched
void showTimeAndDateFound()
{
time_t timer;
char buffer[26];
struct tm* tm_info;
time(&timer);
tm_info = localtime(&timer);
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
pthread_mutex_lock(&mutex_lock_explored);
int explored = nb_explored;
pthread_mutex_unlock(&mutex_lock_explored);
fprintf(stdout, "\r%s - %d found %d tried, %f %% total\n", buffer, nb_found, explored, (100.0 * nb_found) / explored);
}
// Find some nice public keys. Stop the process when "active" becomes false
void findSome(unsigned char *active)
{
......@@ -4244,7 +4270,6 @@ void findSome(unsigned char *active)
if (!reti)
{
// One match found!
// Transform pk/sk into hex for humans - not really needed but keeping it in case
// char hexsk[crypto_sign_ed25519_SECRETKEYBYTES * 2 + 1];
// sodium_bin2hex(hexsk, crypto_sign_ed25519_SECRETKEYBYTES * 2 + 1, sk, crypto_sign_ed25519_SECRETKEYBYTES);
......@@ -4253,16 +4278,32 @@ void findSome(unsigned char *active)
// Make sure we don't write at the same time than someone else
pthread_mutex_lock(&mutex_lock_stdout);
nb_found++;
if (generatePwdSalt)
fprintf(stdout, "\r\"%s\" \"%s\" \"%s\" \"%s\"\n", allregexs[i], b58pk, pass, salt);
{
if (resultStdout == 1)
fprintf(stdout, "\r\"%s\" \"%s\" \"%s\" \"%s\"\n", allregexs[i], b58pk, pass, salt);
else
showTimeAndDateFound();
if (resultfile != NULL)
fprintf(resultfile, "\"%s\" \"%s\" \"%s\" \"%s\"\n", allregexs[i], b58pk, pass, salt);
}
else
{
// Need to transform the seed to hex for readability
char hexseed[SEED_SIZE * 2 + 1];
sodium_bin2hex(hexseed, sizeof hexseed, seed, SEED_SIZE);
fprintf(stdout, "\r\"%s\" \"%s\" \"%s\"\n", allregexs[i], b58pk, hexseed);
if (resultStdout == 1)
fprintf(stdout, "\r\"%s\" \"%s\" \"%s\"\n", allregexs[i], b58pk, hexseed);
else
showTimeAndDateFound();
if (resultfile != NULL)
fprintf(resultfile, "\"%s\" \"%s\" \"%s\"\n", allregexs[i], b58pk, hexseed);
}
fflush(stdout);
if (resultfile != NULL)
fflush(resultfile);
// Release stdout for others
pthread_mutex_unlock(&mutex_lock_stdout);
}
......@@ -4444,12 +4485,14 @@ void remove_thread()
void usage()
{
fprintf(stdout, "Usage: [-s][-n min max][-w wordfile [-f filler_type][-c]] regexfile\n\n");
fprintf(stdout, "Usage: [-s][-n min max][-r|-R resultfile][-w wordfile [-f filler_type][-c]] regexfile\n\n");
fprintf(stdout, "\t-n min max (optional): minimum and maximum number of characters/words to use to generate passwords.\n");
fprintf(stdout, "\t-w wordfile (optional): generate passwords/salt using a list of words contained in the file \"wordfile\", rather than simply random characters.\n");
fprintf(stdout, "\t\t-f type (optional) filler type between words: 0=spaces (default), 1=special characters and numbers, 2=none.\n");
fprintf(stdout, "\t\t-c (optional): capitalize words (non capitalized by default - you can also capitalize the words in the given file).\n");
fprintf(stdout, "\t-t threads (optional): start with \"threads\" parallel threads (the default is half the number of cores found).\n");
fprintf(stdout, "\t-r resultfile (optional): a file to which the results should be written to.\n");
fprintf(stdout, "\t-R resultfile (optional): same as -r, but do not show the results found on the standard output.\n");
fprintf(stdout, "\t-s (optional): Do not generate password/salt, but only a seed (!!!WARNING!!! You will not be able to connect with Sakia or Cesium with this).\n");
fprintf(stdout, "\tregexfile (required): a file containing a list of regex (one per line). Lines beginning by a tab are ignored.\n");
fprintf(stdout, "\nRegex examples:\n");
......@@ -4620,6 +4663,28 @@ int main(int argc, char *argv[])
}
curArg++;
}
else if ((strcmp("-r", argv[curArg]) == 0) || (strcmp("-R", argv[curArg]) == 0))
{
// No stdout if -R
if (strcmp("-R", argv[curArg]) == 0)
resultStdout = 0;
curArg++;
if (curArg == argc)
anotherArgumentWasExpected();
char * filename = argv[curArg];
// Open the file in append mode
resultfile = fopen(filename, "a");
if (resultfile == NULL)
{
fprintf(stderr, "Could not open file %s for writing, exiting\n", filename);
fflush(stderr);
usage();
exit(1);
}
curArg++;
}
else if (strcmp("-c", argv[curArg]) == 0)
{
curArg++;
......@@ -4835,6 +4900,14 @@ int main(int argc, char *argv[])
}
} while (1);
if (resultfile != NULL)
{
pthread_mutex_lock(&mutex_lock_stdout);
fclose(resultfile);
resultfile = NULL;
pthread_mutex_unlock(&mutex_lock_stdout);
}
// Don't forget to release stdin otherwise the terminal will behave incorrectly
releaseStdin();
exit(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment