Unresolved symbols and other problems (Crypto++)

closed account (937X92yv)
Hi guys,

Im, pretty new to programming and I am having a few problems. I am making a windows form program for storing encrypted passwords.

I have created the program in cmd, but I am now converting it to a windows form program. In the cmd version, all the code was in one .cpp file. Now I am trying to use .cpp and .h files to order my code and generally improve it.

I am using crypto++ for encryption. I have got two projects in my solution. One is the cryptlib and the other is my password encryptor project.

These are some errors I am getting:
1
2
1>Authenticate.obj : error LNK2028: unresolved token (0A0005AC) "bool __cdecl Password_Encryptor::AuthenticateLogin(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?AuthenticateLogin@Password_Encryptor@@$$FYA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0@Z) referenced in function "private: void __clrcall Password_Encryptor::Authenticate::Auth(void)" (?Auth@Authenticate@Password_Encryptor@@$$FA$AAMXXZ)
1>Authenticate.obj : error LNK2019: unresolved external symbol "bool __cdecl Password_Encryptor::AuthenticateLogin(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?AuthenticateLogin@Password_Encryptor@@$$FYA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0@Z) referenced in function "private: void __clrcall Password_Encryptor::Authenticate::Auth(void)" (?Auth@Authenticate@Password_Encryptor@@$$FA$AAMXXZ)


The Login files are the files that include all the encryption functions.

Login.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//#ifndef LOGIN_H
//#define LOGIN_H

#include <string>

namespace Password_Encryptor {
	
	using namespace System;
	using namespace std;

	bool fexists(string File);
	bool AuthenticateLogin(string userpass, string Password);
	void EncryptUserpass(string userpass, string Password);

}

//#endif 


Login.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "stdafx.h"

//Define CRYPTO stuff
#define _CRT_SECURE_NO_DEPRECATE
#define CRYPTOPP_DEFAULT_NO_DLL
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1

#include "dll.h"
#include "default.h"
#include "Login.h"
#include <iostream>
#include "FilePaths.h"

//Added for Password SALT + Hash
#include "osrng.h"
#include "sha.h"
#include "aes.h"
#include "hex.h"
#include "integer.h"
#include "pwdbased.h"
#include "modes.h"
#include <string>

using namespace CryptoPP;
using namespace std;
using namespace System;
using namespace Password_Encryptor;

unsigned int iterations = 100000;

.....functions.....
bool fexists(string File)

bool AuthenticateLogin(string userpass, string Password)

void EncryptUserpass(string userpass, string Password)



The main .cpp file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Password Encryptor.cpp : main project file.

#include "stdafx.h"
#include "Main.h"

using namespace Password_Encryptor;

[STAThreadAttribute]

int main(array<System::String ^> ^args) {
	
	// Create the main window and run it
	Application::Run(gcnew Main() );

}



There are 8 files in the project:
Password_Encryptor.cpp
Authenticate.cpp
Authenticate.h
Main.cpp
Main.h
Login.cpp
Login.h
FilePaths.h

I can post the code in these files if needed...


My questions are basically, are they any obvious reasons to why I am receiving these LNK errors? and
Am I coding these .cpp and .h files correctly? i.e. using the namespace correctly...


Many thanks,
Jack
1
2
3
4
5
bool fexists(string File)

bool AuthenticateLogin(string userpass, string Password)

void EncryptUserpass(string userpass, string Password)


Should be:

1
2
3
4
5
bool Password_Encryptor::fexists(string File)

bool Password_Encryptor::AuthenticateLogin(string userpass, string Password)

void Password_Encryptor::EncryptUserpass(string userpass, string Password)


If it isn't then you are just defining functions with the same name in the global namespace.
closed account (937X92yv)
Thanks! Atleast this solves my first problem :)


Now the program does load. But when it does, it skips all validation (the login files) and just loads the main program. It does not seem to look at the Login functions atall.


These are the files that access the Login functions:


Authenticate.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#pragma once

#include <msclr\marshal_cppstd.h>
using namespace System;

#include "Main.h"
#include <string>

using namespace std;

#if       _WIN32_WINNT < 0x0500
  #undef  _WIN32_WINNT
  #define _WIN32_WINNT   0x0500
#endif

namespace Password_Encryptor {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	/// <summary>
	/// Summary for Authenticate
	/// </summary>
	public ref class Authenticate : public System::Windows::Forms::Form
	{
	public:
		Authenticate(void)
		{
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Authenticate()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Button^  BtnAuthenticate;
	protected: 

	private: System::Windows::Forms::Label^  LaUsername;
	private: System::Windows::Forms::Label^  LaPassword;
	private: System::Windows::Forms::TextBox^  TbUsername;
	private: System::Windows::Forms::TextBox^  TbPassword;
	private: System::Windows::Forms::GroupBox^  GbNewLogin;


	protected: 

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>

		
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->BtnAuthenticate = (gcnew System::Windows::Forms::Button());
			this->LaUsername = (gcnew System::Windows::Forms::Label());
			this->LaPassword = (gcnew System::Windows::Forms::Label());
			this->TbUsername = (gcnew System::Windows::Forms::TextBox());
			this->TbPassword = (gcnew System::Windows::Forms::TextBox());
			this->GbNewLogin = (gcnew System::Windows::Forms::GroupBox());
			this->SuspendLayout();
			// 
			// BtnAuthenticate
			// 
			this->BtnAuthenticate->Location = System::Drawing::Point(132, 74);
			this->BtnAuthenticate->Name = L"BtnAuthenticate";
			this->BtnAuthenticate->Size = System::Drawing::Size(60, 24);
			this->BtnAuthenticate->TabIndex = 0;
			this->BtnAuthenticate->Text = L"Submit";
			this->BtnAuthenticate->UseVisualStyleBackColor = true;
			this->BtnAuthenticate->Click += gcnew System::EventHandler(this, &Authenticate::BtnAuthenticate_Click);
			// 
			// LaUsername
			// 
			this->LaUsername->AutoSize = true;
			this->LaUsername->Location = System::Drawing::Point(12, 21);
			this->LaUsername->Name = L"LaUsername";
			this->LaUsername->Size = System::Drawing::Size(55, 13);
			this->LaUsername->TabIndex = 1;
			this->LaUsername->Text = L"Username";
			// 
			// LaPassword
			// 
			this->LaPassword->AutoSize = true;
			this->LaPassword->Location = System::Drawing::Point(12, 52);
			this->LaPassword->Name = L"LaPassword";
			this->LaPassword->Size = System::Drawing::Size(53, 13);
			this->LaPassword->TabIndex = 2;
			this->LaPassword->Text = L"Password";
			// 
			// TbUsername
			// 
			this->TbUsername->Location = System::Drawing::Point(73, 19);
			this->TbUsername->Name = L"TbUsername";
			this->TbUsername->Size = System::Drawing::Size(119, 20);
			this->TbUsername->TabIndex = 3;
			this->TbUsername->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(this, &Authenticate::TbUsername_KeyPress);
			// 
			// TbPassword
			// 
			this->TbPassword->Location = System::Drawing::Point(73, 48);
			this->TbPassword->Name = L"TbPassword";
			this->TbPassword->PasswordChar = '*';
			this->TbPassword->Size = System::Drawing::Size(119, 20);
			this->TbPassword->TabIndex = 4;
			this->TbPassword->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(this, &Authenticate::TbPassword_KeyPress);
			// 
			// GbNewLogin
			// 
			this->GbNewLogin->Location = System::Drawing::Point(10, 12);
			this->GbNewLogin->Name = L"GbNewLogin";
			this->GbNewLogin->Size = System::Drawing::Size(190, 106);
			this->GbNewLogin->TabIndex = 6;
			this->GbNewLogin->TabStop = false;
			this->GbNewLogin->Text = L"Enter new login details";
			this->GbNewLogin->Visible = false;
			// 
			// Authenticate
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(210, 112);
			this->Controls->Add(this->BtnAuthenticate);
			this->Controls->Add(this->TbUsername);
			this->Controls->Add(this->TbPassword);
			this->Controls->Add(this->LaPassword);
			this->Controls->Add(this->LaUsername);
			this->Controls->Add(this->GbNewLogin);
			this->Name = L"Authenticate";
			this->Text = L"Log In";
			this->Load += gcnew System::EventHandler(this, &Authenticate::Authenticate_Load);
			this->Shown += gcnew System::EventHandler(this, &Authenticate::Authenticate_Shown);
			this->ResumeLayout(false);
			this->PerformLayout();

		}

#pragma endregion
	
	private: void Auth();

	private: System::Void BtnAuthenticate_Click(System::Object^  sender, System::EventArgs^  e);
};



Authenticate.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include "stdafx.h"
#include "Authenticate.h"
#include "Login.h"
#include <iostream>
#include <fstream>
#include <string>
#include <tchar.h>
#include <stdlib.h>
#include <vcclr.h>
#include "FilePaths.h"

using namespace std;
using namespace System;
using namespace Password_Encryptor;

bool filexists;
int chances = 3;
bool login = true;

void Authenticate::Auth() {
	
	if (chances == 0) {
		MessageBox::Show("You have failed 3 times, the application will now close", "Bad Login");
		Close();
	}

	String ^UsernameTemp = Authenticate::TbUsername->Text;
	String ^PasswordTemp = Authenticate::TbPassword->Text;
	string Username, Password;
	int Ulen, Plen;
	char *Uch, *Pch;
	bool Uresult, Presult;

    pin_ptr<const wchar_t> Uwch = PtrToStringChars( UsernameTemp );
	Ulen = (( UsernameTemp->Length+1) * 2);
    Uch = new char[ Ulen ];
	Uresult = wcstombs( Uch, Uwch, Ulen ) != -1;

    Username = Uch;
    delete Uch;

	pin_ptr<const wchar_t> Pwch = PtrToStringChars( PasswordTemp );
	Plen = (( PasswordTemp->Length+1) * 2);
    Pch = new char[ Plen ];
	Presult = wcstombs( Pch, Pwch, Plen ) != -1;

    Password = Pch;
    delete Pch;

	string userpass = Username + Password;


	//If there was no username + pasword file (found earlier), then create one with the newly entered info
	if (!filexists){
		EncryptUserpass(userpass, Password);
	}
		
	//Authenticate the login details
	login = AuthenticateLogin(userpass, Password);

	//this->TbPassword->Text = login;
	

	if ( login == true ) {
		MessageBox::Show("Login Successful", "Authentication", MessageBoxButtons::OK);
		Authenticate::Close();
	} else {
		MessageBox::Show("Login Failed /n/n You have " + chances + " chance(s) remaining!", "Authentication", MessageBoxButtons::OK);
		chances --;

		this->TbUsername->Text = "";
		this->TbPassword->Text = "";
	}

};

System::Void Authenticate::BtnAuthenticate_Click(System::Object^  sender, System::EventArgs^  e){
	Auth();
}


Basically, when the main program is loaded, it hides the main form, and opens the login form (Authenticate). This then calls on the login functions to authenticate the login details. Once this is done it closes the login form and shows the main form again.

But it seems to be skipping the authentication functions altogether!
Last edited on
closed account (937X92yv)
Hmmm I think I have debugged it a little bit more.

It seems like all the variables being passed to the login functions (the managed code) is just being jumbled up. The Password is always blank, and the Username is garbled.

Is there any reason the variable would be destroyed when being passed to my managed code?


The AuthenticateLogin funciton:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
bool Password_Encryptor::AuthenticateLogin(string userpass, string Password, string Username){
	ofstream out3 ("C:/Users/Default/AppData/Roaming/Pass Holder/temp3.dat");
	out3 << "1 " << Username << endl;
	out3.close();
	ofstream out4 ("C:/Users/Default/AppData/Roaming/Pass Holder/temp4.dat");
	out4 << "1 " << Password << endl;
	out4.close();

	//This function is to make sure the username and password entered by the user is correct
	int size;
	char *buf;
	string hashText;

	//Read in the SALT used for the previous userpass
	ifstream in1(SALTfile, ios::in | ios::binary | ios::ate);
	size = in1.tellg();
	buf = new char[size + 1];
	buf[size] = 0;
	in1.seekg(0, ios::beg);
	in1.read(buf, size);
	in1.close();

	string hexsalt = string(buf);

	//Read in the IV used for the previous userpass
	ifstream in2(IVfile, ios::in | ios::binary | ios::ate);
	size = in2.tellg();
	buf = new char[size + 1];
	buf[size] = 0;
	in2.seekg(0, ios::beg);
	in2.read(buf, size);
	in2.close();

	string hexiv = string(buf);

	//Read in the hash used for the previous userpass, this will be compared the to newly entered userpass encrypted with the previous SALT and IV
	ifstream in3(UserpassFile, ios::in | ios::binary | ios::ate);
	size = in3.tellg();
	buf = new char[size + 1];
	buf[size] = 0;
	in3.seekg(0, ios::beg);
	in3.read(buf, size);
	in3.close();

	string cipherText = string(buf);

	//Recover the SALT and IV from the hex values in the file,
	PKCS5_PBKDF2_HMAC<SHA256> pbkdf;

	SecByteBlock recoveredkey(AES::DEFAULT_KEYLENGTH);
	SecByteBlock recoveredsalt(AES::DEFAULT_KEYLENGTH);
	StringSource saltDecoder(hexsalt,true,new HexDecoder(new ArraySink(recoveredsalt, recoveredsalt.size() ) ) );
	
	test();

	ofstream out1 ("C:/Users/Default/AppData/Roaming/Pass Holder/temp.dat");
	out1 << "1 " << Password << endl;
	out1 << "1 " << userpass << "\n2 " << Password << endl;
	out1 << "1 " << recoveredkey << "\n2 " << recoveredkey.size() << "\n3 " << Password << "\n4 " << Password.size() << "\n5 " <<
		 recoveredsalt << "\n6 " << recoveredsalt.size() << "\n7 " << iterations	;
	out1.close();

	pbkdf.DeriveKey(recoveredkey, recoveredkey.size(), 0x00, (byte *) Password.data(), Password.size(), recoveredsalt, recoveredsalt.size(), iterations);
	
	test();
		
	SecByteBlock recoverediv(AES::BLOCKSIZE);
	StringSource ivDecoder(hexiv,true,new HexDecoder(new ArraySink(recoverediv, recoverediv.size() ) ) );

	//Encrypt the userpass that has been entered, using the SALT and IV stored in the file
	SecByteBlock derivedkey(AES::DEFAULT_KEYLENGTH);

	//Buffer that holds the derived key, purpose byte (unused), password bytes, salt bytes, iteration count (large as you can tolerate)
	pbkdf.DeriveKey(derivedkey, derivedkey.size(), 0x00, (byte *) Password.data(), Password.size(), recoveredsalt, recoveredsalt.size(), iterations);
	
	//Encrypt the userpass using key derived above, storing the hex encoded result into hashtext
	CBC_Mode<AES>::Encryption aesencryption(derivedkey,derivedkey.size(),recoverediv);
	StringSource encryptor(userpass, true, new StreamTransformationFilter(aesencryption, new HexEncoder( new StringSink(hashText))) );

	//Return whether the comparison between the newly created hash, and the old hash is correct
	
	return (hashText == cipherText);
}



The function that calls it (Auth):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
void Authenticate::Auth() {

	if (chances == 0) {
		MessageBox::Show("You have failed 3 times, the application will now close", "Bad Login");
		Close();
	}

	String ^UsernameTemp = Authenticate::TbUsername->Text;
	String ^PasswordTemp = Authenticate::TbPassword->Text;
	string Username, Password;
	int Ulen, Plen;
	char *Uch, *Pch;
	bool Uresult, Presult;

    pin_ptr<const wchar_t> Uwch = PtrToStringChars( UsernameTemp );
	Ulen = (( UsernameTemp->Length+1) * 2);
    Uch = new char[ Ulen ];
	Uresult = wcstombs( Uch, Uwch, Ulen ) != -1;

    Username = Uch;
    delete Uch;

	pin_ptr<const wchar_t> Pwch = PtrToStringChars( PasswordTemp );
	Plen = (( PasswordTemp->Length+1) * 2);
    Pch = new char[ Plen ];
	Presult = wcstombs( Pch, Pwch, Plen ) != -1;

    Password = Pch;
    delete Pch;

	string userpass = Username + Password;
	
	//If there was no username + pasword file (found earlier), then create one with the newly entered info
	if (!filexists){
		EncryptUserpass(userpass, Password);
	}

	ofstream out1 ("C:/Users/Default/AppData/Roaming/Pass Holder/temp1.dat");
	out1 << "1 " << Username << endl;
	out1.close();
	ofstream out2 ("C:/Users/Default/AppData/Roaming/Pass Holder/temp2.dat");
	out2 << "1 " << Password << endl;
	out2.close();


	//Authenticate the login details
	login = AuthenticateLogin(userpass, Password, Username);


	if ( login == true ) {
		MessageBox::Show("Login Successful", "Authentication", MessageBoxButtons::OK);
		Authenticate::Close();
	} else {
		MessageBox::Show("Login Failed /n/n You have " + chances + " chance(s) remaining!", "Authentication", MessageBoxButtons::OK);
		chances --;

		this->TbUsername->Text = "";
		this->TbPassword->Text = "";
	}

};


Basically the line 'login = AuthenticateLogin(userpass, Password, Username);' is running, but when the variable are passed, they are garbled and meaningless. I have checked the variable before they are passed, and they are as they should be. Only when passed to the managed code are they destroyed.
closed account (937X92yv)
What do people normally do when using Crypto++ and Windows forms? As this is causing some problems, how does everyone else overcome this? (Or do they only use command line for something like this)


Also, does anyone have any links to a good tutorial using the c++ .NET cryptography namespace, as this may be the next logical step to get my program working.
Topic archived. No new replies allowed.