3

Okay, so I'm building a program for a college class, it's a simple program that uses structures to simulate building a database of user information along with usernames and passwords. For extra credit on the lab, we can encrypt the passwords. This isn't anything special....we're not using MD5 or anything advanced like that.

All I need to do is be able to switch uppercase characters to lowercase, lowercase characters to uppercase, and, finally, the part I'm having trouble with, converting decimal integers into hexadecimal.

I'll try to post just the relevant parts of the program instead of the whole thing.

Here's the structure:

struct Info
{
    string sFname;
    string sLname;
    string sUname;
    string sPword;
    string sAddress;
    string sEmail;
    string sPhone;
};

Note: This is a dynamic array of structures

Info *Users;
        Users = new Info[size];

And here's the code to encrypt the password that I have so far:

//string length for controlling loops
strlen = Users[iUsrCount].sPword.length();

        //temp string to hold the encrypted version of password
        string temp;

        //switch uppercase characters to lowercase and vice versa, and convert
        //decimal integers into hexadecimal
        for(int i=0; i<strlen; i++)
        {
                cout << "\n\nInside encryption for loop iteration " << i << "\n\n";

                if(islower(Users[iUsrCount].sPword[i]))
                {
                        temp += toupper(Users[iUsrCount].sPword[i]);
                        continue;
                }
                else if(isupper(Users[iUsrCount].sPword[i]))
                {
                        temp += tolower(Users[iUsrCount].sPword[i]);
                        continue;
                }
                else if(isdigit(Users[iUsrCount].sPword[i]))
                {
                        char charNum = Users[iUsrCount].sPword[i];
                        int iDec = charNum - '0';



                        //get integer
                        while((i+1) < strlen && isdigit(Users[iUsrCount].sPword[i+1]))
                        {
                                i++;
                                iDec = iDec * 10 + Users[iUsrCount].sPword[i] - '0';
                                cout << " " << iDec << " ";
                        }

                        char hexTemp[10];

                        //convert
                        sprintf(hexTemp, "%x", iDec);

                        temp += hexTemp;

                        //debugging cout to make sure hexes are properly calculated
                        cout << " " << hexTemp << " ";
                        continue;
                }
        }
                //debugging cout to make sure that password is properly encrypted
                cout << endl << endl << temp << endl << endl;

                strlen = temp.length();

                //overwrite the plain text password with the encrypted version
                for(int i=0; i<strlen; i++)
                        Users[iUsrCount].sPword[i] = temp[i];

                //debugging cout to make sure copy was successful
                cout << endl << endl << Users[iUsrCount].sPword;

So if your password was:

456Pass45word87

It would look like this when encrypted:

1c8pASS2dWORD57

We also have to reverse the string, but that's fairly simple.

My 2 questions are this:

  1. Is there any easier way to do this?

  2. I cannot, for the life of me, figure out the right algorithm to DECRYPT the password, which I will need to do so that when the user logs in, the computer can compare what they type to the plain text version of their password.

Note: I am by no means a professional coder, so please have mercy on a noob and try not to get too super-advanced on me. I've looked all over the place but I can't find anything that is really helping me with my specific situation.

And so I throw myself upon the mercy of the Internets. :D

Warren Smith
  • 111
  • 1
  • 6
  • 6
    You should never decrypt a password, simply encrypt the password they entered and encrypt that and compare it with the encrypted password. – allejo Nov 04 '13 at 05:18
  • 1
    Completey agree with allejo. Nonetheless, since this is just an assignment knowing how to reverse the encryption process is still educational. What you have to do is apply the encryption process backwards. eg. first reverse the string, turn upper to lower visa-versa then convert hex back into decimal form. – greatwolf Nov 04 '13 at 05:23
  • 1
    This is not really an encryption algorithm because it's irreversible. 'ab' could mean the input was 'AB' or it could mean the input was '171'. – David Schwartz Nov 04 '13 at 05:25
  • Contemplate how XOR works. See, for example, what happens with characters in the ASCII character set when you XOR them with, say, a space character. – Carey Gregory Nov 04 '13 at 05:35
  • I couldn't, for the life of you, either figure out the right algorithm to *decrypt* the password. Why? Consider: `123AbCd` encrypted: `7baBcD` How can you tell that the `a` is not part of your password anymore? You'd need something like a delimiter. Thus I'd still go with allejo's method, even regarding the educational value of decryption. – Kiruse Nov 04 '13 at 06:19

3 Answers3

1
  1. Is there any easier way to do this?

-- Your method seems fine to me. Your way is clear and easy enough.

  1. I cannot, for the life of me, figure out the right algorithm to DECRYPT the password, which I will need to do so that when the user logs in, the computer can compare what they type to the plain text version of their password.

-- You shouldn't try to decrypt your password. When user logs in, use the encrypted password to do the comparison.

Colt
  • 134
  • 1
  • 1
  • 6
  • How to compare passwords wasn't the question. – Carey Gregory Nov 04 '13 at 05:35
  • @CareyGregory An example of what Colt meant is that password ABC might become 233dweww when encrypted, ABC will always become 233dweww since the encryption method does not change so you should test that `encPassword = encrypt(unencPassword);` where unencPassword is what the user is entering and encPassword is their stored and encrypted password :) – Matthew Pigram Nov 04 '13 at 05:42
  • @MatthewPigram - I understand, but re-read the question. It's a student's homework problem. It's very limited in scope and not expecting a professional level solution. How to encrypt and decrypt, that is all. – Carey Gregory Nov 04 '13 at 06:55
0

There are easier ways to do this using boost and C++11, but if you don't mind vanilla C++98, then you can do this using the STL and Unary Functions

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <sstream>
#include <cctype>
#include <vector>
#include <iterator>
using namespace std;

//modified from here:
//https://stackoverflow.com/a/313990/866930
char flipcase (char in) {
    if (in<='Z' && in>='A')
        return in-('Z'-'z');
    else if (in<='z' && in>='a') {
        return in+('Z'-'z');
    }
    return in;
}

int main() {
    string test = "456Pass45word87";
    transform(test.begin(), test.end(), test.begin(), flipcase);//this flips uppercase to lowercase and vice-versa

    string nums, text;
    vector<string> parts;

    //break the string into its constituent number and textual parts and operate
    //on them accordingly.
    //for text, store all until a non-text character is reached. Reset.
    //for numbers, keeping iterating until the first non-digit character
    //is reached. Store, then reset.
    for (int i = 0; i < test.length(); i++) {
        if (isdigit(test[i])) {
            nums += test[i];
            if (!text.empty()) {
                parts.push_back(text);//store the text
            }
            text.clear();//reset the memory in it
        }
        else {
            text += test[i];

            if (!nums.empty()) {                
                int n = atoi(nums.c_str());
                stringstream ss;
                //now reinsert back into the string stream and convert it to a hexadecimal:
                ss << std::hex << n;

                parts.push_back(ss.str());//now store it
                nums.clear();//clear the number string
            }
        }
    }

    //at this point the vector contains the string broken into different parts
    //that have been correctly modified.
    //now join all the strings in the vector into one:
    //adapted from here:
    //https://stackoverflow.com/a/5689061/866930
    ostringstream oss;
    copy(parts.begin(), parts.end(), ostream_iterator<string>(oss,""));//we want no character delimiter between our strings
    cout << oss.str();

    return 0;
}

This prints:

1c8pASS2dWORD57

As desired.

NOTE:

You could use iterators when iterating over the string, but that's something you can do for yourself.

REFERENCES:

https://stackoverflow.com/a/313990/866930

https://stackoverflow.com/a/5689061/866930

http://www.cplusplus.com/reference/algorithm/transform/

Community
  • 1
  • 1
jrd1
  • 10,358
  • 4
  • 34
  • 51
0

for your encryption you have the following set as parameters:

//switch uppercase characters to lowercase and vice versa, and convert
//decimal integers into hexadecimal

So to Decrypt all you have to do is reverse the cycle:

  • convert hex to decimal
  • switch case to the opposite case

and you would have the decrypted version.

If you need more detail let me know, and I can try to help out at some point today.

GMasucci
  • 2,834
  • 22
  • 42
  • I understand that I have to reverse the process, but just converting decimal to hex was more complicated than I anticipated. I'm having trouble figuring out how to properly reverse the algorithm to do so. I'll probably just compare the encrypted passwords as suggested earlier, since that saves me from having to decrypt in the first place, but I would like to know how to do it anyway, just for the knowledge. – Warren Smith Nov 04 '13 at 19:56
  • if you reverse your encryption code(mathematical symbols/order) that will decrypt the encrypted password for you:) when I get time I will work through a solution and post more information for you:) – GMasucci Nov 05 '13 at 10:14