c++ password storage .txt file + masking input - c++

I'm pretty new to programming - just starting out with C++. So I wanted to make an application - just for fun - which would mask user input with asterisks. I did some research and found exactly what I was looking for. As you can see inside the code below it works fine but only checks password from a char I put - "correct_password". I thought it'd be more challenging to extend options. The program would write two options out: 1. register - just put your login and password (without asterisks), then store it into a file (fstream I guess), 2. login - after putting login and password (with asterisks just the way it is in getpass) it would check the file for data if user is actually registered. Even thought maybe about encrypting data in that file, although I have no idea how to proceed. Well, it's just made up thing to learn some new stuff, I know it's not really a THING and there's no really a purpose to write such code - just messing around with C++. Maybe you got some ideas how to snap that? After I wrote this asterisk thing i don't really see where I should put those other options, storing in file and so on. Would love to go through some ideas and appreciate the input from more experienced coders :)
I tried using fstream inside getpass but didn't work out. Generally I'd like to extend this program with login and password input, storing them into .txt file and then program would check if user is registered and while logging with this data input would be masked with asterisks - just like my first idea of that program which is only masking password input. I don't really know how to split unmasked input with that inside getpass.
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
string getpass(const char *dat, bool s_asterisk=true)
{
const char BACKSPACE=8;
const char RETURN=13;
string password;
unsigned char ch=0;
cout << dat;
DWORD con_mode;
DWORD dwRead;
HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode( hIn, &con_mode );
SetConsoleMode( hIn, con_mode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT) );
while(ReadConsoleA( hIn, &ch, 1, &dwRead, NULL) && ch !=RETURN)
{
if(ch==BACKSPACE)
{
if(password.length()!=0)
{
if(s_asterisk)
cout <<"\b \b";
password.resize(password.length()-1);
}
}
else
{
password+=ch;
if(s_asterisk)
cout <<'*';
}
}
cout << endl;
return password;
}
int main()
{
const char *correct_password="fdsidfjsijdsf21128321873";
START:
string password=getpass("Enter the password: ",true);
if(password==correct_password){
cout <<"\nCorrect password."<<endl;
exit(1);
}else{
cout <<"\nIncorrect password. Try again.\n"<<endl;
goto START;
}
return 0;
}

Usually you don't want to store actual passwords in a file. Although encrypting them would help security (to at least some degree), it's still generally pretty insecure and better avoided.
What you usually want to do instead is salt the password, then hash the salted password with a cryptographic hash. Then you store the salt and the hash, rather than the password itself.
Then (for the simplest case) when the user wants to log in, you repeat the same process: retrieve the salt for their password, apply the salt to the password they enter, hash the result, and finally compare that result to the value you stored. If they match, you assume the user entered the correct password. If they don't match, you know they didn't.
Note that this is only reasonable for the user logging into your application locally (or at least over a secure connection). If they might log in over an insecure connection, you need to get considerably more sophisticated still.
Another major point though: nearly all of this should happen outside getpass. getpass should do exactly one thing: read in a password from the user. Salting, hashing, storing, and so on, should all happen separately from that.

Related

Overwrite std::cin read-buffer after reading password

After reading a password from std::cin
std::cout << "Password: ";
SecureString pw{}; // secure string, wipes automatically on destruction
SetConsoleEcho(false); // hide input in terminal
std::getline(std::cin, pw); // input the password
SetConsoleEcho(true); // switch echo back on
the password stays stored in the read buffer of cin (heap memory) until it is overwritten with new input and can easily be sniffed with tools like Process Hacker or would be written to disk in case of a memory dump.
Does anyone know how the std::cin.rdbuf() can be cleared/overwritten, ideally in a cross-platform way? Or is there a way how to avoid using the buffer in the first place?
The above code uses SecureString which is implemented using Crypto++'s AllocatorWithCleanup which wipes memory at destruction. SetConsoleEcho switches the console echo on/off in order to avoid seeing the plain text password on screen.
I realize this question is very similar to this one but it's been over 10 years and the accepted answer actually does not answer the question.
The linked post has all the answers you need and unfortunately there isn't a way to securely read and then clear the password with 0 risk of it being exposed. See
Even if you scribble over the buffer immediately, it's still possible the password is written to disk. A system i/o buffer might be paged to disk, as might the working memory which std::cin is in. I used to develop forensic software which sniffed out exactly these conditions.
Furthermore if a malicious actor has access to the PC a keylogger can just be used to extract the password.
Or is there a way how to avoid using the buffer in the first place?
I found a cross-platform way (Linux, Mac, Windows) how to avoid the read buffer of cin using a readline replacement library. I used replxx but other readline replacement libraries will likely do as well.
I created a simple wrapper class PasswordInput around replxx that clears its input buffer on every key stroke and stores the entered password in a secure string using Crypto++'s AllocatorWithCleanup. The secure string is automatically wiped after a password digest is created, thus leaving no copy of the plain password in process memory.
All this achieves is to avoid having the plain password in process memory for longer than needed. It does not guard against keyloggers nor against the possibility of leaking the password if the process crashes while calculating the digest nor against well timed sniffing attacks nor against any other possible attack vectors.
So far I've only tested on Windows and I only did basic memory sniffing tests using Process Hacker. These showed no trace of the plain password (contrary to using std::cin)
Header file:
using SecureString =
std::basic_string<char, std::char_traits<char>, CryptoPP::AllocatorWithCleanup<char>>;
class PasswordInput {
public:
PasswordInput();
void Read(const std::string& prompt);
inline const SecureString& Secret() const { return secret_; }
private:
void RxPwModifyCb(std::string& line, int& pos);
Replxx rx_;
SecureString secret_;
};
Implementation:
namespace ph = std::placeholders;
PasswordInput::PasswordInput() :
rx_{}
{
rx_.set_modify_callback(std::bind(&PasswordInput::RxPwModifyCb, this, ph::_1, ph::_2));
}
void PasswordInput::Read(const std::string& prompt)
{
char const* cinput{nullptr};
do
{
cinput = rx_.input(prompt);
} while ((cinput == nullptr) && (errno == EAGAIN));
}
void PasswordInput::RxPwModifyCb(std::string& line, int& pos)
{
if (!line.empty())
{
secret_.append(1, line[0]);
line.clear();
}
}
Usage:
PasswordInput pwi{}; // create password input handler
pwi.Read("Password: "); // read the password
std::cout << "\x1b[A" << "\33[2K\r"; // go one line up, delete line and go to beginning (does nothing in terms of security but looks cool)
CalculatePassphrase(pwi.Secret().c_str(), pwi.Secret().size()); // Scrypt, pbkdf2, etc..
Please note this is not complete code and it needs replxx and Crypto++ libraries linked

Password Manager - Continuing / Long-Term Things

Okay, I know very well how everybody feels about homemade password managers, but I would like help with mine. Not for actual use, just for the sake of learning.
I was wondering, in C++ how to have long-term variables. Or really, have anything long-term.
What do I mean by long-term? Something that is saved or continues upon next run of the .exe. In my case, I want where, the first time you run the program it asks you to enter an access password, so next time you launch the program, you will have to type the password chosen when you first launched.
Currently, I just use an if() statement to check if password is equal to my desired password, and if it is, to run. However, that is far from actually effective and isn't very practical.
Something I thought of was to create a text file somewhere containing the access password, and read it, but that kind of defeats the purpose of a password manager.
Every variable in your program is only in memory and lost at exit. You must store it on your disk and later read it from there.
There are many ways to do that directly or indirectly.
A very simple low level way is to use ofstream and ifstream. E.g.:
#include <iostream>
#include <fstream>
int main() {
using namespace std;
int counter = 0;
// try to load counter from file
{
ifstream myfile("mycounter.txt");
if (myfile.is_open())
{
myfile >> counter;
}
myfile.close();
}
cout << "current counter: " << counter << endl;
// save counter to file
{
ofstream myfile;
myfile.open("mycounter.txt");
myfile << counter << endl;
}
}
You might be more comfortable with the C-functions fopen, fread, fwrite, fclose, etc.
Then, there are databases and there are easy libraries to use such databases. Check out sqlite, you can use it from C++.
You could start a database or save/write the data into files.

How to have multiple attempt to enter password, with terminal in RAW mode?

I am creating a login menu in C++
i wish to give the user 3 attempts at entering the password before the program terminates.
My code runs fine if the user gets the password right the first time. It would then go into the home menu ect. However, if the user gets the password wrong. The terminal would run up to:
Login: Fred
Password: ***
Wrong password
Please re-enter password:
After which point nothing would show up regardless of what the user types. Not even ctrl-C can exit the program. I was wondering if anyone know what's going on and can point me in the right direction.
Here's part of the codes for the method "login" in a class called "HomePage":
cout<<"Password: ";
while (loginAttempt < 3){ //The user gets to attempt to type
//the password 3 times
password = receivePassword(); //Receives password from user
if (flatMemberList[match].getPassword()==password){ //Check if the password is correct
cout<<endl<<"Welcome back "<<loginName<< endl; //If correct, display welcome message
return;
}
else{
loginAttempt++; //Record down one failed attempt
cout<<endl<<"Wrong password"<<endl; //If incorrect, display error
cout<<"Please re-enter password: ";
}
}
cout<<"you have exceeded the legal login attempts"<<endl;
exit(1);
Where receivePassword() is a custom method as follows:
//This method is called when the user types in a password
//The terminal's setting is first changed to 'raw' configuration
//The password are taken in one letter at a time
//It outputs to terminal "*" instead of echoing the input
string HomePage::receivePassword(){
termios oldt, newt; //The structs for manipulation
char password[PaswordLength]; //Password held here
int j = 0; //Password index
tcgetattr(STDIN_FILENO, &oldt); //Get configuration details
newt = oldt;
cfmakeraw(&newt); //Set up new 'raw' configuration structure
//Set up new terminal configuration
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
cin.ignore(1000, '\n'); //flush all the buffers
while(true){
password[j] = cin.get();
if( password[j] == '\r' ) { //check if 'enter' key is entered
password[j] = '\0'; //replace cr with null to make C string
break;
}
cout.put('*'); //echo the asterisk
j++;
} ;
//Reset terminal to old configuration
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return password;
}
Thanks in advance
If you think the problem might be elsewhere, let me know, and i'll post the codes.
I don't know what your specific problem is. However, you can apply standard debugging techniques to find out which part is causing the problem.
First, you're doing weird things with terminals (cfmakeraw, tcsetattr, etc). It sounds like that might be related to the problem. So, remove the code that hides the user input and make sure your program works when the password is echoed to the screen normally. You should be able to do that easily.
After doing this, you can then decide whether your problem is related to:
the terminal attribute code that you removed, or
the password loop that remains.
This is often called the "divide and conquer" debugging technique. If you remove the code that you think is the problem, then whether the problem remains or not can help you decide whether it's related to the code you removed.
I was just using the similar set of codes for my final project in our 1st term of our freshmen year. It turns out that the problem was coming from the password masking itself.
Now that I have removed those parts, the program now works well other than the pin being exposed.

How to get a password with a CLI program?

I am writing a Linux CLI program. I need to get a password from the user and, obviously, I don't want the password to be echoed to the console.
There are several solutions available here, but they are all for plain C.
C command-line password input
How to mask password in c?
Getting a password in C without using getpass (3)?
How can those be adapted for C++, using std::string instead of char[]?
What would be the most elegant C++ solution?
Use any of the plain C solutions:
std::string pass (100); // size the string at your max password size (minus one)
func_to_get_pass(&pass[0], pass.size());
// function takes a char* and the max size to write (including a null char)
pass.resize(pass.find('\0'));
cout << "Your password is " << pass << ".\n"; // oops! don't show it ;)
Linux itself is written (mostly) in C, so anything you could find in C++ would only be an abstraction around a single C routine. Better to call the routine yourself, converting the input and result.

is it possible to change what the user types without pressing enter? this is a console program in C

Is this possible? The idea is typing a password and it being translated to asterisks on the fly- pretty much like a password field on HTML. I've written this code, but it converts the input AFTER the user presses enter, not while he/she is typing.
#include <stdio.h>
#include <string.h>
#include <iostream>
int main()
{
char password[11]; int i, j;
printf("Enter the password : ");
gets(password);
system("cls");
int str_len = (int)strlen(password);
printf("Enter the password : ");
for(i = 0;i<2;i++)
{
printf(" ");
for(j=0;j<str_len/2;j++)
{
printf("*");
}
}
system("PAUSE>nul");
}
I don't think it is possible using standard io. You need a library for more advanced text user interface like ncurses.
If you do want to get some extra points from the teacher, you could look into the function int getch() which does what you want. It is located in the header file conio.h.
Googling for getch should provide you with some info - MSDN and cplusplus.com are my favorite pages.
It is not directly possible using standard C, no. You typically need to convince the terminal to go into "raw" mode, in which the program is able to read each character as it's typed, i.e. not requiring enter to pressed. In the raw mode, you can also often turn off any built-in echo in the terminal, and thus get the display of typed-in characters under program control.
It might be possible to convince a terminal to do these things by outputting various escape codes, but if that is within your scope or not is hard to tell. Also, it depends on the exact terminal (and thus platform) in use.