Considering that the string class is really a typedef'd basic_string<char>, every time you call the at() method it's probably returning a signed char, and somewhere in the Encrypt function a sign extension happens.
I did a quick test by typedef'ing basic_string<unsigned char> ustring, and then converting all your strings to ustrings. Unfortunately this gave me issues with getline(), so I just switched to C-style input.
Does this work for you?
Code:
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
typedef basic_string<unsigned char> ustring;
ustring Encrypt(const ustring &plaintext, const ustring &key);
int main()
{
unsigned char buf[1024];
ustring cyphertext, plaintext, key;
fputs("Enter string to be encrypted/decrypted: ", stdout);
fgets((char*)buf, sizeof(buf), stdin);
plaintext.assign(buf);
fputs("Enter encryption key: ", stdout);
fgets((char*)buf, sizeof(buf), stdin);
key.assign(buf);
cyphertext = Encrypt(plaintext, key);
for(unsigned int i = 0; i < cyphertext.length(); ++i)
printf("%x ", cyphertext.at(i));
return 0;
}
ustring Encrypt(const ustring &plaintext, const ustring &key)
{
unsigned int i(0);
unsigned int j(0);
unsigned int k(0);
vector<unsigned int> S(256, 0);
ustring cyphertext;
//BEGIN KEY-SCHEDULING ALGORITHM
for(i = 0; i < 256; ++i)
{
S.at(i) = i; //initialize s-box S[0] = 0...S[255] = 255
}
for(i = 0; i < 256; ++i)
{
//transpose s-box values based on key
j = (j + S.at(i) + key.at(i % key.length())) % 256;
swap(S.at(i), S.at(j));
}
//END KEY-SCHEDULING ALGORITHM
//BEGIN PSEUDO-RANDOM GENORATION ALGORITHM
for(i = 0, j = 0; i < plaintext.length(); ++i)
{
//transpose s-box values based on s-box values
j = (j + 1) % 256;
k = (k + S.at(j)) % 256;
swap(S.at(j), S.at(k));
//encryption happens here
cyphertext += plaintext.at(i) ^ (S.at((S.at(j) + S.at(k)) % 256));
}
//END PSEUDO-RANDOM GENORATION ALGORITHM
return cyphertext;
}
Code:
>a.exe
Enter string to be encrypted/decrypted: Hello.
Enter encryption key: 1234
39 2a 9c 93 ce 20 ed