Password change system not working

Hey. I am working on a project for fun with different types of sensors and stuff. It's sort of like a mini smarthome box to test stuff with. I am currently working on the password system, and my change password system is not working.
When you click the change password button, it checks if the password you have entered currently is correct. If it is, it enters password set mode, where you can enter the new password and press the same button. It then should change the password and the old one stops working. Instead, every password seems to be correct now. If I print the guess and the target in the serial monitor, it seems like the target is changing to the guess.

#include <IRremote.hpp>
#define IR_RECEIVE_PIN A2
#include <LiquidCrystal_I2C.h>
#include <Password.h>

LiquidCrystal_I2C mylcd(0x27, 16, 2);

Password password = Password( "1234" );

// Variable declarations
bool setpass;
volatile int gas;

void setup()
{
  Serial.begin(9600);
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  mylcd.init();
  mylcd.backlight();
  mylcd.setCursor(1 - 1, 1 - 1);
  mylcd.print("Password:");
}

void loop() {
  if (IrReceiver.decode()) {
    bool num;
      switch (IrReceiver.decodedIRData.decodedRawData) {
        case 3860463360:
        password.append('0');
        num = true;
        break;
        case 3125149440:
        password.append('1');
        num = true;
        break;
        case 3108437760:
        password.append('2');
        num = true;
        break;
        case 3091726080:
        password.append('3');
        num = true;
        break;
        case 3141861120:
        password.append('4');
        num = true;
        break;
        case 3208707840:
        password.append('5');
        num = true;
        break;
        case 3158572800:
        password.append('6');
        num = true;
        break;
        case 4161273600:
        password.append('7');
        num = true;
        break;
        case 3927310080:
        password.append('8');
        num = true;
        break;
        case 4127850240:
        password.append('9');
        num = true;
        break;
        case 3810328320:
        checkPass();
        break;
        case 3910598400:
        resetPass(true);
        break;
        case 4061003520:
        setPass();
        break;
      }
      if (num) {
        mylcd.setCursor(1 - 1, 2 - 1);
        mylcd.print(password.guess);
      }
      delay(300);
      IrReceiver.resume();
  }
}
// Password functions
void checkPass() {
  Serial.println(password.target);
  Serial.println(password.guess);
  if (password.evaluate()) {
    mylcd.setCursor(1 - 1, 2 - 1);
    mylcd.clear();
    mylcd.print("Correct!");
  } else {
    mylcd.setCursor(1 - 1, 2 - 1);
    mylcd.clear();
    mylcd.setCursor(1 - 1, 1 - 1);
    mylcd.print("Wrong");
    delay(1000);
    resetPass(true);
  }
}
void resetPass(bool again) {
  password.reset();
  mylcd.setCursor(1 - 1, 2 - 1);
  mylcd.print("Reset");
  delay(1000);
  mylcd.clear();
  if (again) {
    mylcd.setCursor(1 - 1, 1 - 1);
    mylcd.clear();
    mylcd.print("Password:");
  }
}
void setPass() {
  if (setpass) {
    setpass = false;
    password.target = password.guess;
    mylcd.setCursor(1 - 1, 1 - 1);
    mylcd.clear();
    mylcd.print("Password Set");
    delay(1000);
    resetPass(true);
    return 0;
  }
  if (password.evaluate()) {
    setpass = true;
    password.reset();
    mylcd.setCursor(1 - 1, 1 - 1);
    mylcd.clear();
    mylcd.setCursor(1 - 1, 1 - 2);
    mylcd.clear();
    mylcd.print("Set Password:");
  } else {
    mylcd.setCursor(1 - 1, 2 - 1);
    mylcd.clear();
    mylcd.print("Wrong");
    delay(1000);
    resetPass(true);
  }
}

This is using a well known password management library that can be found here: Arduino Playground - Password Library
Serial Monitor (after pass change to 4321):

6789 (target password)
6789 (guess)

The target password should be 4321, and the guess should be 6789, which are not equal, and it should be marked as wrong, but they are equal.

Are you certain?

Yes. I set the password to 4321 using the change password function and it still says all password are correct. If I log the target password right after I change it, it outputs the correct thing, it’s just when it evaluates it or something in that function.

Would you post the Password.h file? The one on that link does not compile... or probably I am missing another file.

Yes, there is another password.cpp file. Check the link in the original post.

It is custom to post all files involved. Chasing links to zip files to folders to find a particular file is not desired.

Oh, sorry.
Password.h:

/**
 *
 * @file Password.h
 * @version 1.2.1
 * @author Alexander Brevig
 * @authors Alexander Brevig,Nathan Sobieck, Sam4uk
 * 
 * @details Handle passwords easily
 *
 * @note
 * 
 * 	1.2.1  2024-02-16 - Sam4uk : Availability of the library in the library
 *                      manager
 *
 * 	1.2    2012-05-12 - Nathan Sobieck : Arduino IDE v1.0 With BAckwards
 *                      compatibility
 *
 *  1.1    2009-06-17 - Alexander Brevig : Added assignment operator =, equality
 *                      operators == != and insertion operator <<
 *
 *  1.0    2009-06-17 - Alexander Brevig : Initial Release
 */
#ifndef PASSWORD_H
#define PASSWORD_H

// Arduino versioning.
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"	// for digitalRead, digitalWrite, etc
#else
#include "WProgram.h"
#endif

#define MAX_PASSWORD_LENGTH (20)

#define STRING_TERMINATOR '\0'

class Password {
public:
	/**
	 * @brief Construct object in memory, set all variables
	 * 
	 * @param pass 
	 */
	Password(char* pass);
	
	/**
	 * @brief Set the password
	 * 
	 * @param pass 
	 */
	void set(char* pass);
	/**
	 * @brief Evaluate a string, is it equal to the password?
	 * 
	 * @param pass 
	 * @return true 
	 * @return false 
	 */
	bool is(char* pass);
	/**
	 * @brief Append a char to the guessed password
	 * 
	 * @param character 
	 * @return true 
	 * @return false 
	 */
	bool append(char character);
	/**
	 * @brief Reset the guessed password, one can guess again
	 * 
	 */
	void reset();
	/**
	 * @brief Is the current guessed password equal to the target password?
	 * 
	 * @return true 
	 * @return false 
	 */
	bool evaluate();
	
	//char* getPassword();
	//char* getGuess();
	
	//operators
	/**
	 * @brief password using operator =
	 */
	Password &operator=(char* pass);
	/**
	 * @brief Test password using ==
	 */
	bool operator==(char* pass);
	/**
	 * @brief Test password using != 
	 */
	bool operator!=(char* pass);
	/**
	 * @brief Append to currently guessed password using operator <<
	 */
	Password &operator<<(char character);
	

	char* target;
	char guess[ MAX_PASSWORD_LENGTH ];
	byte currentIndex;
};

#endif

Password.cpp:

/**
 * @file Password.cpp
 * @version 1.2.1
 * @author Alexander Brevig
 * @authors Alexander Brevig,Nathan Sobieck, Sam4uk
 *
 * @details Handle passwords easily
 *
 * @note
 *
 * 	1.2.1  2024-02-16 - Sam4uk : Availability of the library in the library
 *                      manager
 *
 * 	1.2    2012-05-12 - Nathan Sobieck : Arduino IDE v1.0 With BAckwards
 *                      compatibility
 *
 *  1.1    2009-06-17 - Alexander Brevig : Added assignment operator =, equality
 *                      operators == != and insertion operator <<
 *
 *  1.0    2009-06-17 - Alexander Brevig : Initial Release
 *
 */

#include "Password.h"

Password::Password(char* pass) {
  set(pass);
  reset();
}

void Password::set(char* pass) { target = pass; }

bool Password::is(char* pass) {
  byte i = 0;
  while (*pass && i < MAX_PASSWORD_LENGTH) {
    guess[i] = pass[i];
    i++;
  }
  return evaluate();
}

bool Password::append(char character) {
  if (currentIndex + 1 == MAX_PASSWORD_LENGTH) {
    return false;
  } else {
    guess[currentIndex++] = character;
    guess[currentIndex] = STRING_TERMINATOR;  // ensure a valid c string
  }
  return true;
}

void Password::reset() {
  currentIndex = 0;
  guess[currentIndex] = STRING_TERMINATOR;
}

bool Password::evaluate() {
  char pass = target[0];
  char guessed = guess[0];
  for (byte i = 1; i < MAX_PASSWORD_LENGTH; ++i) {
    // check if guessed char is equal to the password char
    if ((STRING_TERMINATOR == pass) && (STRING_TERMINATOR == guessed)) {
      return true;  // both strings ended and all previous characters are equal
    } else if ((pass != guessed) || (STRING_TERMINATOR == pass) ||
               (STRING_TERMINATOR == guessed)) {
      return false;  // difference OR end of string has been reached
    }

    // read next char
    pass = target[i];
    guessed = guess[i];
  }
  return false;  // a 'true' condition has not been met
}

Password& Password::operator=(char* pass) {
  set(pass);
  return *this;
}

bool Password::operator==(char* pass) { return is(pass); }

bool Password::operator!=(char* pass) { return !is(pass); }

Password& Password::operator<<(char character) {
  append(character);
  return *this;
}

Thank you.

My compiler does not like this (warning only) on line 8...

Password password = Password( "1234" );

Error report:

warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

... so I guess password should be an array of characters, not a string "1234"... and...

My compiler does not like this (warning only) on line 124, because setPass() returns void so I commented it out:

    // return 0;

These are strange:

This is so it doesn't go onto the second 'if' statement, which causes a problem. Is there a better way I should break out of the function?

Also, what's strange about these?

This has nothing to do with the reported problem, but is this line

mylcd.setCursor(1 - 1, 1 - 1);

supposed to be somehow different from this?

mylcd.setCursor(0,0);

Here's your problem

The newly entered password guess is set as the target password. But

target is just a pointer, which now points to the buffer used for the guess. From now on, evaluate always returns true -- unless the buffer is full, due to an unrelated bug in evaluate, in which case it always returns false, even if you never touched target and the 19-character password matches.

To add your desired feature, you can create your own target buffer

char targetPassword[ MAX_PASSWORD_LENGTH ] = "1234";
Password password = targetPassword;

so that password.target points to it. Then to copy the guess, use memcpy or strcpy to copy the characters over. Don't touch the pointers.

1 Like

Thank you, @kenb4

Yes. That’s how I was taught to do it. I agree it doesn’t make sense but if I just use 0,0 then it doesn’t work.

Sorry, that makes no sense at all. The compiler will always replace "1 - 1" with 0. They are completely equivalent expressions.

I've done some experimenting and added more logging. It seems like password.target is blank after I change it using password.target = password.guess. password.guess returns the correct value, but password.target is blank when I set it to password.guess.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.