Encription upgrade

I need to improve my encription code and I've thought of putting random chars in between a char array (example down below) but I can only replace chars in the array, effetively ruining the encription code

1
2
3
4
5
6
  char example ={'t','e','s','t'},total_char[1000];
  char ch='a' + rand() % 26;
  // code here
  for(i=0;i<(char array length);i++){
    	cout<<total_char[i];
  }

Output (theoretical):

t(ch)e(ch)s(ch)t
char example ={'t','e','s','t'}

This is not valid code.
error: scalar object 'example' requires one element in initializer


I suggest having two strings, and build the 2nd string up from the 1st (source) string.
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
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>

int main()
{
    std::srand(std::time(nullptr));
    
    char random_char = 'a' + std::rand() % 26;
    
    std::string example = "test";
    std::string output;
    
    if (example.size() >= 1)
    {
        for (size_t i = 0; i < example.size() - 1; i++) // loop through every char except last
        {
            output += example[i];
            output += random_char; // (will be same random char each time)
        }
        output += example.back(); // last actual character
    }

    std::cout << output << std::endl;
}
Last edited on
Thank you, this is pretty much how I wanted!
Could you just explain the use of "+=" ?
+ is doing string concatenation for two strings (or a string and char).

output += random_char;
is equal to doing
output = output + random_char;

string_a + string_b puts "left" and "right" together to make "leftright".
Why not generate a new random char for every iteration? You have to keep track of the rubbish characters either way. And maybe you could make it less obvious by putting the random char at random intervals instead of just alternating between the input and the random char. Of course you have to remember the interval to decrypt. You can just use the modulus of a randomly generated number and insert the char when it's the modulus is 0.
I already changed the code to randomize every rand char, but maybe within the encryption code I could make it so it picks between 0 and 1, so the char to decrypt lands on 1?
Example:

Input: test

encryption:asdf

Randomized chars: aYTsEdf

Check code: 1001011

(note: Caps chars are just for reference, only the check code matters)
That's not a bad idea at all. But the thing is you would have to maintain a separate array for every string of chars that you encrpyt. So that would not only make everything messy (because of having to map every string with its key and all) but also cost you twice the memory. It's just unnecessarily complicated as opposed to simply generating a random number (or using a fixed number).

Well before we get there I have an issue:
I'm trying to use scanf(" %[^\n]s",&example) to read the example string, but it doesn't print the randomized string
How do I fix this?

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
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;

int main()
{
    srand (time(NULL));
    char random_char = 'a' + rand() % 26;
    string example;
    string output;
    int r,rtotal[example.size()];
    scanf(" %[^\n]s",&example);// to be able to use spaces
    if (example.size() >= 1)
    {
        for (size_t i = 0; i < example.size() -1; i++) // loop through every char except last
        {
        	r=rand() % 2;// 50/50 chance
        	if (r==1){//normal char
        		output += example[i];
		}else{//random char
			output += example[i];
            	        random_char = 'A' + rand() % 26;
           		output += random_char; 
        	}
        	rtotal[i]=r;// also not working, not the main issue
        }
        output += example.back(); // last actual character
    }

    cout << output << endl;
}
Last edited on
do not scanf into the string. if you MUST do this, preallocate the string and be more careful with your pointers.

string example(100);
scanf(..., &example[0]); // this is a terribly bad plan. but I can live with it if you can. you really, really really need to be using cin here. This code is breaking the string's built in length and generally not good, even if you can club it to death and make it work, its still going to be technically wrong.

try this...
string example = "";
for(however many random letters you want)
example += (random character expression);
cout << example << endl;

if you want random letters AND spaces, a quick solution is this
string allowed = "abcdefghijklmnopqrstuvwxyz "; //has space
and do example += allowed[randomexpression];
Last edited on
Actually, it may work if you leave the & off the string, using scanf as-is. I don't know... ? you could try it.
Well, cin seems to work but not with spaces, and removing the & gives me:

[Error] cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'


Look, the encryption code (seen below) uses a char array to read, so I either repurpose all of the above to work on char arrays or convert the array to string

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cout << "Please enter a string:\t";
scanf(" %[^\n]s",&str);
strl = strlen(str);
for(i = 0; i < strl; i++){
     if(str[i]==' '){// to prevent errors, spaces are changed to underscores (see ASCII table)
               str[i]='_';	
        }
}
for(i = 0;i <strl; i++){
	rtotal[i]= rand() % 9 +1;
        enstr[i] = str[i] - rtotal[i];
}
enstrl = strlen(enstr);// to remove odd chars right after encrypted code 
for(i = strl;i < enstrl; i++){
           enstr[i]='\0';
}
cout << "\nEncrypted string: " << enstr << endl;
cout << "\nEncryption key: " ;
for(i = 0;i < strl; i++){
           cout << rtotal[i];
} 
cout << endl;


What's the best way to go at this?
Last edited on
I wasnt sure about the &, I never tried it but strings sometimes can pretend to be c-strings and sometimes not so much. Looks like that is a no-go.

cin.getline keeps spaces, you could try that?
if you can't find any other way you can also do this:

char input[1000]; //drop to C for one line to force it to work.
scanf(...blah .. input)
string whatever = input; //back to normal.

but this is not at all the 'best way' this is a bandaid if you can't get past the problem.
It should be fixable with getline or some similar C++ resolution.
Last edited on
Yep, getline worked...sorta

Encription code:
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
cout << "Please enter a string:\t";
getline(cin,test);
strl=test.size();
for(i = 0; i < strl; i++){
//had to convert string to char array,
//seems redundant but doesn't print anything with strings
	str[i]=test[i];
        if(str[i]==' '){
            	str[i]='_';	
	}
}
//everything else checks out
for(i = 0;i <strl; i++){
	rtotal[i]= rand() % 9 +1;
        enstr[i] = str[i] - rtotal[i];
}
enstrl = strlen(enstr);
for(i = strl;i < enstrl; i++){
        enstr[i]='\0';
}
cout << "\nEncrypted string: " << enstr << endl;
cout << "\nEncryption key: " ;
for(i = 0;i < strl; i++){
        cout << rtotal[i];
} 
cout << endl;


Random char code
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
int main()
{
    srand (time(NULL));
    char random_char = 'a' + rand() % 26;
    string example;
    string output;
    int r;
    getline(cin,example);//works! yay!
	for (int i = 0; i < example.size(); i++) 
        {
        	r=rand() % 2;// 50/50 chance
        	cout << r << endl;//testing,ignore
        	if (r==0){
        		output += example[i];
			}else{//read below
			output += example[i];
			random_char = 'A' + rand() % 26;
           		output += random_char; 
       		}
        	
        }
        
    

    cout << output << endl;
}

I noticed that, when it randomizes a char, it prints the normal char and then the random char,and I know why, but if I remove output += example[i] from that section, it replaces the normal char, bringing me right where I was.

How can it chose between random and normal chars without replacing them or being always
after a normal char?

Example

Input: test

output tASeRst

('A','S' and 'R' are random)
Hey, it's me again. So, I've managed to figure out how to work the code that I wanted, but now I need a way to have a string that has only the original chars.

Code:
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
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;

int main()
{
    
    srand (time(NULL));
    char random_char ;
    string example,output,input;
    int r,rtotal[1000],ch_count,i;
	getline(cin,example);
    while(ch_count!=example.size()){
    r=rand() % 2+1;// 1 or 2 instead of 0 and 1 to be able to set the length as "when r==0" 
		if (r==1){
			output += example[ch_count];
			ch_count++;
		}else{
    		random_char = 'A' + rand() % 26;// Upper chars just for reference, will change 
                                                                  //code to also use lowercase keys
   			output += random_char;
		}
	rtotal[i]=r;
	cout << rtotal[i];
	i++;
	
	}
	printf("\n");
    cout << output << endl;
   
}


I've thought of putting chars only when the corresponding number is a 1:

Example

Input: test

output tASeRst

code: 1221211

descramble:

t=1,so 1st char reads as 't';
A=2, so it ignores;
and so on...

but in practice, nothing happens. What should I do?

Last edited on
So, I'm done with this program. If anyone wants the code, here it is:

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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <string.h>
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <cstdlib>
#include <fstream>
using namespace std;

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); // used for goto
COORD CursorPosition; // used for goto

void gotoXY(int x, int y) 
{ 
	CursorPosition.X = x; 
	CursorPosition.Y = y; 
	SetConsoleCursorPosition(console,CursorPosition); 
}

int main()
{
	const int bufferSize = MAX_PATH;
    char oldDir[bufferSize];
	int menu_item=0,sub_item=0, run, x=7;
	bool running = true,subrunning=false;
	int r,rtotal[100000],ch_total[100000],ch_count=0,i,strl=0;
    string str,output,input,dele,check;
    srand (time(NULL));
	gotoXY(18,5); cout << "Main Menu";
	gotoXY(18,7); cout << "->";
	while(running)
	{
		gotoXY(20,7);  cout << "1) Encrypt";
		gotoXY(20,8);  cout << "2) Decrypt";
		gotoXY(20,9); cout << "Quit Program";
		system("pause>nul"); // the >nul bit causes it the print no message
		if(GetAsyncKeyState(VK_DOWN) && x != 10) //down button pressed
			{
				gotoXY(18,x); cout << "  ";
				x++;
				gotoXY(18,x); cout << "->";
				menu_item++;
				continue;
				
			}
			
		if(GetAsyncKeyState(VK_UP) && x != 7) //up button pressed
			{
				gotoXY(18,x); cout << "  ";
				x--;
				gotoXY(18,x); cout << "->";
				menu_item--;
				continue;
			}
		if(GetAsyncKeyState(VK_RETURN)){ // Enter key pressed
		strl=0;
		ch_count=0;
		output="";
		input="";
		dele="";
		check="";
			switch(menu_item){
				case 0: {
					system("cls");
					cout << "Please enter a string:\t";
					getline(cin,str);
					for(i = 0;i <str.size(); i++){
            			if(str[i]==' '){
            				str[i]='_';	
						}
						rtotal[i]= rand() % 9 +1;
    					str[i] -= rtotal[i];
					}
					i=0;
					while(ch_count!=str.size()){
				    r=rand() % 3;
				    switch(r){
				    	case 0:{output += str[ch_count];
							ch_total[ch_count]=i;
							ch_count++;
							break;
						}
						case 1:{output += 'A' + rand() % 26;
							break;
						}
						case 2:{output += 'a' + rand() % 26;
							break;
						}
					}
					i++;
					}
					cout << "\nEncrypted string: " << output << endl;
    				cout << "\nEncryption key: " ;
					for(i = 0;i < str.size(); i++){
    					cout << rtotal[i];
					}
					cout << endl;
					cout << "\nRead key: " ;
					for(i = 0;i < str.size(); i++){
    					cout << ch_total[i];
					}  
					cout << endl;
         			ofstream afile;
 		 			afile.open ("str.bin");
 		 			afile << output <<" "<< str.size() <<" ";
 		 			for(i = 0;i < str.size(); i++){
            			afile << ch_total[i]<<" ";
					}
 		 			for(i = 0;i < str.size(); i++){
            			afile << rtotal[i]<<" ";
					} 
					cout << endl;
 		 			afile.close();
 		 			system("pause");
 		 			system("cls");
 		 			gotoXY(18,5); cout << "Main Menu";
					gotoXY(18,7); cout << "->";
					break;
				}
				case 1: {
					system("cls");
					ifstream afile ("str.bin");
 					afile >> output >>r;
					for (i = 0; i <r; i++) // Using for loop we are initializing
					{
						afile >> ch_total[i];
				    	input+=output[ch_total[i]];
					}
					for(i = 0;i < input.size(); i++){
       					afile >> rtotal[i];
					}
					cout << "\nEncrypted string: " << output <<endl;
					cout << "\nEncryption key: " ;
					for(i = 0;i < input.size(); i++){
            			cout << rtotal[i];
					} 
					cout << endl;
					cout << "\nRead key: " ;
					for(i = 0;i < input.size(); i++){
    					cout << ch_total[i];
					}  
					cout << endl;
       				for(i = 0;i < input.size(); i++){
					input[i] += rtotal[i];
					}
					for(i = 0; i < input.size(); i++){
            			if(input[i]=='_'){
            				input[i]=' ';	
						}
         			}
      				cout << "\nDecrypted string: " << input <<endl;
      				cout << endl;
      				system("pause");
 		 			system("cls");
 		 			gotoXY(18,5); cout << "Main Menu";
					gotoXY(18,8); cout << "->";
					break;
				}
				case 2: {
					system("cls");
					subrunning=true;
					x=7;
					gotoXY(18,5); cout << "Delete file?";
					gotoXY(18,7); cout << "->";
					while(subrunning)
					{
				        gotoXY(20,7);  cout << "1) No";
						gotoXY(20,8);  cout << "2) Yes";
				
						system("pause>nul"); // the >nul bit causes it the print no message
						
						if(GetAsyncKeyState(VK_DOWN) && x != 8) //down button pressed
							{
								gotoXY(18,x); cout << "  ";
								x++;
								gotoXY(18,x); cout << "->";
								sub_item++;
								continue;
								
							}
							
						if(GetAsyncKeyState(VK_UP) && x != 7) //up button pressed
							{
								gotoXY(18,x); cout << "  ";
								x--;
								gotoXY(18,x); cout << "->";
								sub_item--;
								continue;
							}
							
						if(GetAsyncKeyState(VK_RETURN)){ // Enter key pressed
							subrunning = false;
							GetCurrentDirectory(bufferSize, oldDir);
							}
					}
							switch(sub_item){
								
								case 0: {
									gotoXY(20,16);
									cout << "File remains in "<<oldDir<<endl;
									break;
								}
								case 1: {
									gotoXY(20,16);
									cout << "Done!! File removed from "<<oldDir<<endl;
									remove("str.bin");
									break;
								}
							}
					running = false;
					
				}
			}
		}			
	}
	gotoXY(20,18);
	system("pause");
}
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string>
#include <cstring>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <windows.h>

minor fixes to includes. Using the C versions of includes (which you had) fails to use the namespaces correctly which can cause some strange behaviors, esp in huge projects.

otherwise, nice work getting it going!
Last edited on
Yet more ways to complicate text encription:

I need a way to scramble text with an array containing the original text order (without repeating the same string position)

Example:


Input:

test

t 0
e 1
s 2
t 3

(randomize order)

Output:

sett

s 2
e 1
t 0
t 3
Last edited on
Topic archived. No new replies allowed.