Reputation: 772
I am trying to create a shadowfile-like txt file and I am using crypt to produce the hash. I ask for password via terminal and i produce a pseudo-random salt. I give these two values in crypt function but it creates a different hash everytime or nothing at all and I cannot get what's wrong with my code.
#include<stdio.h>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<ctime>
#include<crypt.h>
#include<unistd.h>
using namespace std;
/*====== READ STRING DYNAMICALLY ======*/
char* readFromTerminal() {
int length = 0; //counts number of characters
char c; //holds last read character
char *input;
input = (char *) malloc(sizeof (char)); //Allocate initial memory
if (input == NULL) //Fail if allocating of memory not possible
{
printf("Could not allocate memory!");
exit(1);
}
while ((c = getchar()) != '\n') //until end of line
{
realloc(input, (sizeof (char))); //allocate more memory
input[length++] = c; //save entered character
}
input[length] = '\0'; //add terminator
return input;
}
/*====== GENERATE PSEUDO RANDOM SALT VALUE ======*/
char* generateSalt() {
const char alphanum[] =
"0123456789"
"!@#$%^&*"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"; //salt alphanum
int alphanumLength = sizeof (alphanum) - 1; // alphanum lenght
char *salt; //salt string
salt = (char *) malloc(sizeof (char)); //Allocate initial memory
if (salt == NULL) //Fail if allocating of memory not possible
{
printf("Could not allocate memory!");
exit(1);
}
srand(time(NULL));
for (int i = 0; i < 21; i++) {
realloc(salt, (sizeof (char))); //allocate more memory
salt[i] = alphanum[rand() % alphanumLength]; //generate a random character from the alphanum
}
salt[21] = '\0'; //add terminator
return salt;
}
/*====== MAIN ======*/
int main(int argc, char** argv) {
char *username, *password, *salt, *hash;
ofstream myshadow("myshadow.txt", ios::out);
cout << "Enter your username: ";
username = readFromTerminal();
cout << "Enter your password: ";
password = readFromTerminal();
salt = generateSalt();
hash = (char *) malloc(30 * sizeof (char)); //Allocate memory for hash
hash = crypt(password, salt);
myshadow << username << ":" << hash;
return 0;
}
Upvotes: 0
Views: 1854
Reputation: 148900
There is a lot to improve here!
char *
when C++ comes with std::string
malloc
and realloc
that alone let think that problems will soon arriveManual memory management requires very cautious programming. Here the error is caused by an incorrect use of realloc
: the size parameter gives the new total allocated size, not an increment. So you should keep track of the allocated size, increase it and call realloc with that new value. And as realloc
may return a new block of memory, you should always use:
input = (char *) realloc(input, new_size);
BTW, equivalent problem in generateSalt
...
But all is already included in C++, thanks to std::getline
! And in addition, the <random>
module comes with great generators when old rand
suffers number of defaults (just google for rand vs. random)
So the code could be stripped down to:
include<iostream>
#include<fstream>
#include<unistd.h>
#include <random>
using namespace std;
std::string generateSalt() {
const char alphanum[] =
"0123456789"
"!@#$%^&*"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"; //salt alphanum
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> dis(0, sizeof(alphanum)-1); //Uniform distribution on an interval
char salt[22]; // 21 useful characters in salt (as in original code)
for(char& c: salt) {
c = alphanum[dis(gen)];
}
salt[21] = 0;
return std::string(salt);
}
/*====== MAIN ======*/
int main(int argc, char** argv) {
string username, password, salt, hash;
ofstream myshadow("myshadow.txt", ios::out);
cout << "Enter your username: ";
if (! getline(cin, username)) return 1;
cout << "Enter your password: ";
if (! getline(cin, password)) return 1;
salt = generateSalt();
hash = crypt(password.c_str(), salt.c_str());
myshadow << username << ":" << hash;
return 0;
}
Another nice side effect of using C++ strings is that allocation and deallocation is automatically handled, no need to call free
...
Upvotes: 1