Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Why is Identical Code Producing Different Results?


This question is answered.


Permlink Replies: 5 - Last Post: Aug 2, 2017 5:45 AM Last Post By: Rudy Velthuis (...
Earl Staley

Posts: 99
Registered: 4/9/07
Why is Identical Code Producing Different Results?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 31, 2017 11:18 AM
I found some code for encrypting passwords on the internet and I wanted to use it on one of my projects.

Here is the total code in the demo project:
// ---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "MainForm.h"
// ---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
 
std::string encrypt(std::string msg, std::string key) {
	// Make sure the key is at least as long as the message
	std::string tmp(key);
	while (key.size() < msg.size())
		key += tmp;
 
	// And now for the encryption part (XOR each character)
	for (std::string::size_type i = 0; i < msg.size(); ++i)
		msg[i] ^= key[i];
	return msg;
}
 
std::string decrypt(std::string msg, std::string key) {
	// reverse the process
	return encrypt(msg, key); // lol
}
 
// ---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner) : TForm(Owner) {
}
 
// ---------------------------------------------------------------------------
void __fastcall TForm2::btnGoClick(TObject *Sender) {
	AnsiString str=lePW->Text;
 
	string msg = str.c_str();
 
	str=leKey->Text;
	string key = str.c_str();
 
	std::string message = encrypt(msg, key);
	int i = 0;
	str = "";
	while (message[i] != 0)
		str += message[i++];
	leEncrypted->Text = str;
 
	message = decrypt(message, key);
	str = "";
	i = 0;
	while (message[i] != 0)
		str += message[i++];
	leDecrypted->Text = str;
}
// ---------------------------------------------------------------------------
void __fastcall TForm2::lePWChange(TObject *Sender)
{
btnGo->Enabled=(lePW->Text!="")&&(leKey->Text!="");
}
//---------------------------------------------------------------------------


Here is the key: 5mDNFLqqYIllgLo9oZzCjvxsuV1q1YfnQVMt5fvGnEbnQJnK41ZBBefuAso3TkaluyQpcYNWsT18fFbP

and here is the password: MyFinalFinalPassword

The code worked as expected in the demo projects. I then copied the code for the 'encrypt' and 'decrypt' functions into my main project. Both the demo and main projects return the same result from the 'encrypt' function. Here is the character result in the Edit box in the demo project: x'(-70'
. Here is the hex code result in the Local variables window: msg "x\x14\x02'(-\x1D70'\r".

The code for returning 'message' to readable text is also identical in both projects:
	int i = 0;
	str = "";
	while (message[i] != 0)
		str += message[i++];


The problem arises when the encrypted value is decrypted. The demo project returns the correct result: "MyFinalFinalPassword". The main project returns an incorrect result: "MyFinalFin"
I assume the problem is the return character ('\r') occurs when the 11th character 'a' in the password is XOR'd with the eleventh character 'l' in the key which results in the '\r' character.

1) Why does the code work OK in the demo project but not in the main project?

2) Why is the encrypted password (11 characters) shorter than the length of the un-encrypted password (20 characters)?

I put a break point on this line of code in both projects:
msg[i] ^= key[i];


Here is the output from the Local Variables window in the debugger:

Local Variables in demo project:
Name Value
tmp "5mDNFLqqYIllgLo9oZzCjvxsuV1q1YfnQVMt5fvGnEbnQJnK41ZBBefuAso3TkaluyQpcYNWsT18fFbP"
key "5mDNFLqqYIllgLo9oZzCjvxsuV1q1YfnQVMt5fvGnEbnQJnK41ZBBefuAso3TkaluyQpcYNWsT18fFbP"
msg "MyFinalFinalPassword"
i 0 (0x00000000)

Local Variables in main project:
Name Value
tmp E2451 Undefined symbol 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str()'
key E2451 Undefined symbol 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str()'
msg E2451 Undefined symbol 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str()'
i 0 (0x00000000)

3) Why do the variables display OK in the demo window, but not in the main project?

Thank you for enduring a rather long post, but I have been working on this problem for a week and have come up empty?

Earl Staley

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Why is Identical Code Producing Different Results?
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 31, 2017 1:46 PM   in response to: Earl Staley in response to: Earl Staley
Earl Staley wrote:

1) Why does the code work OK in the demo project but not in the main
project?

Encryption operates on raw binary data, not on character data. You
should not be storing binary data in strings to begin with. I suggest
you use TBytes or std::vector<unsigned char> instead.

Also, when encrypting string data and then decrypting it, make sure you
handle the character data in a consistent character encoding, like
UTF-8, not as ANSI, which varies on different computers.

And, when displaying encrypted data, you should not display it as-is as
textual data, because it not text to begin with. It is best to display
it in hex format instead.

2) Why is the encrypted password (11 characters) shorter than the
length of the un-encrypted password (20 characters)?

Notice that "MyFinalFin" is exactly 1/2 the number of characters (10)
as "MyFinalFinalPassword" (20). That implies you might mixing Ansi and
Unicode logic, since sizeof(char)=1 and sizeof(wchar_t)=2 on Windows.
What version of C++Builder are you using? In CB2009+, lePW->Text will
be a UnicodeString, not an AnsiString. And you should not be storing
binary data in a UnicodeString.

But, more importantly, your loops are not taking the full std::string
length into consideration. 'while (message[i] != 0)' only works with
null-terminated C-style strings, which std::string is not. For
std::string, you need to use its size() or length() method instead, eg:

while (i < message.size())


while (i < message.length())


Or better, use a 'for' loop instead of a 'while' loop.

Even with AnsiString, you should be using its Length() method in a
similar manner.

Now, with that said, try something more like this instead:

#include <vector>
#include <string>
#include <sstream>
#include <iomanip>
 
std::vector<unsigned char> encrypt(const std::string &msg, const
std::string &key)
{
    const std::string::size_type msg_size = msg.size();
    const std::string::size_type key_size = key.size();
 
    std::vector<unsigned char> out;
    out.resize(msg_size);
 
    for (std::string::size_type i = 0; i < msg_size; ++i)
        out[i] = ((unsigned char) msg[i]) ^ ((unsigned char) key[i %
key_size]));
 
    return out;
}
 
std::string decrypt(const std::vector<unsigned char> &msg, const
std::string &key)
{
    const std::vector<unsigned char>::size_type msg_size = msg.size();
    const std::string::size_type key_size = key.size();
 
    std::string out;
    out.resize(msg_size);
 
    for (std::vector<unsigned char>::size_type i = 0; i < msg_size; ++i)
        out[i] = (char) (msg[i] ^ ((unsigned char) key[i % key_size]));
 
    return out;
}
 
void __fastcall TForm2::btnGoClick(TObject *Sender)
{
    std::string msg, key;
 
    // if using CB2009 or later...
    msg = UTF8String(lePW->Text).c_str();
    key = UTF8String(leKey->Text).c_str();
 
    // if using CB2007 or earlier...
    msg = UTF8Encode(lePW->Text).c_str();
    key = UTF8Encode(leKey->Text).c_str();
 
    std::vector<unsigned char> encryped = encrypt(msg, key);
 
    // ...
 
    // using STL formatting...
    std::ostringstream oss;
    oss << std::hex << std::uppercase << std::noshowbase <<
std:setfill('0');
    for (std::vector<unsigned char>::size_type i = 0; i <
encryped.size(); ++i)
        oss << std::setw(2) << int(encryped[i]) << ' ';
    leEncrypted->Text = oss.str().c_str();
 
    // using RTL formatting...
    system::String oss;
    for (std::vector<unsigned char>::size_type i = 0; i <
encryped.size(); ++i)
        oss += (IntToHex(int(encryped[i]), 2) + " ");
    leEncrypted->Text = oss;
 
    // ...
 
    msg = decrypt(encryped, key);
 
    // if using CB2009 or later...
    leDecrypted->Text = UTF8String(str.c_str());
 
    // if using CB2007 or earlier...
    leDecrypted->Text = UTF8Decode(str.c_str());
}


--
Remy Lebeau (TeamB)
Earl Staley

Posts: 99
Registered: 4/9/07
Re: Why is Identical Code Producing Different Results?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 1, 2017 4:24 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy,

Thank you for your extensive reply.

I am using C++ Berlin 10.1.

I am still trying to digest all of your suggestions and incorporate your suggestions into my code. I have never worked with vectors or ostringstream before so I have a lot of learning to do.

I am still curious why the local Local Variables window showed different results for the demo program and main program with identical code and an identical break point. Ant ideas why?

Here is the output from the Local Variables window in the debugger:

Local Variables in demo project:
Name Value
tmp "5mDNFLqqYIllgLo9oZzCjvxsuV1q1YfnQVMt5fvGnEbnQJnK41ZBBefuAso3TkaluyQpcYNWsT18fFbP"
key "5mDNFLqqYIllgLo9oZzCjvxsuV1q1YfnQVMt5fvGnEbnQJnK41ZBBefuAso3TkaluyQpcYNWsT18fFbP"
msg "MyFinalFinalPassword"
i 0 (0x00000000)

Local Variables in main project:
Name Value
tmp E2451 Undefined symbol 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str()'
key E2451 Undefined symbol 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str()'
msg E2451 Undefined symbol 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str()'
i 0 (0x00000000)

Thank you...
Earl Staley
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Why is Identical Code Producing Different Results?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 1, 2017 1:18 PM   in response to: Earl Staley in response to: Earl Staley
Earl Staley wrote:

I am using C++ Berlin 10.1.

I am still trying to digest all of your suggestions and incorporate
your suggestions into my code. I have never worked with vectors or
ostringstream before so I have a lot of learning to do.

Those were just suggestions, not requirements. You could write similar
code using Embarcadero's RTL classes instead, eg:

 
TBytes encrypt(const UTF8String &msg, const UTF8String &key)
{
    const int msg_size = msg.Length();
    const int key_size = key.Length();
 
    TBytes out;
    out.Length = msg_size;
 
    for (int i = 0; i < msg_size; ++i)
        out[i] = ((Byte) msg[i]) ^ ((Byte) key[i % key_size]));
 
    return out;
}
 
UTF8String decrypt(const TBytes &msg, const UTF8String &key)
{
    const int msg_size = msg.Length;
    const int key_size = key.Length();
 
    UTF8String out;
    out.SetLength(msg_size);
 
    for (int i = 0; i < msg_size; ++i)
        out[i+1] = (char) (msg[i] ^ ((Byte) key[i % key_size]));
 
    return out;
}
 
void __fastcall TForm2::btnGoClick(TObject *Sender)
{
    UTF8String msg, key;
 
    msg = lePW->Text;
    key = leKey->Text;
 
    TBytes encryped = encrypt(msg, key);
 
    // ...
 
    System::String s;
    for (int i = 0; i < encryped.Length; ++i)
        s += (IntToHex(int(encryped[i]), 2) + " ");
    leEncrypted->Text = s;
 
    // ...
 
    msg = decrypt(encryped, key);
 
    leDecrypted->Text = str;
}


I am still curious why the local Local Variables window showed
different results for the demo program and main program with
identical code and an identical break point. Ant ideas why?

No, and I don't want to debug your code for you. Step through your
code line-by-line in the debugger and compare the results on each
statement. The data you are operating on is clearly NOT identical in
both programs. You need to find the difference.

--
Remy Lebeau (TeamB)
Earl Staley

Posts: 99
Registered: 4/9/07
Re: Why is Identical Code Producing Different Results?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 1, 2017 2:45 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
No, and I don't want to debug your code for you. Step through your
code line-by-line in the debugger and compare the results on each
statement. The data you are operating on is clearly NOT identical in
both programs. You need to find the difference.

Remy,

I didn't mean for you to debug my code. What I was trying to determine is why the local variables (tmp, key, and msg) all had actual values in the demo project whereas in the main project the same variables said that all of those variables were "Undefined symbol". Seems odd.

Thank you again for all of your help and I learned a lot from your sample code.

Earl Staley
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: Why is Identical Code Producing Different Results?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 2, 2017 5:45 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

Earl Staley wrote:

1) Why does the code work OK in the demo project but not in the main
project?

Encryption operates on raw binary data, not on character data. You
should not be storing binary data in strings to begin with. I suggest
you use TBytes or std::vector<unsigned char> instead.

Exactly.

--
Rudy Velthuis http://www.rvelthuis.de

"Walking on water and developing software from a
specification are easy if both are frozen."
-- Edward V Berard
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02