so I would like to encrypt my data when write into .txt file so I choose XOR-Encryption from this code:
Github
So when I run in code blocks it runs and shows this result:
Encrypted: :=.43*-:8m2$.a
Decrypted:kylewbanks.com0
Process returned 0 (0x0) execution time : 0.025 s
Press any key to continue.
But When I start use Visual Studio 2017 it shows this error:
Error (active) E0059 function call is not allowed in a constant expression
Which means I cant put variable when declaring an array, so is there any method for my encryption to work in VS2017.
I think the problems is when declare the variable using constant, anyway to force it or other encryption method that is easy to use, I wont need to be secure just to prevent plain text in file.
Anyway this is the only code:
#include <stdio.h>
#include <string.h>
void encryptDecrypt(char *input, char *output) {
char key[] = {'K', 'C', 'Q'}; //Can be any chars, and any size array
int i;
for(i = 0; i < strlen(input); i++) {
output[i] = input[i] ^ key[i % (sizeof(key)/sizeof(char))];
}
}
int main () {
char baseStr[] = "kylewbanks.com";
char encrypted[strlen(baseStr)];
encryptDecrypt(baseStr, encrypted);
printf("Encrypted:%s\n", encrypted);
char decrypted[strlen(baseStr)];
encryptDecrypt(encrypted, decrypted);
printf("Decrypted:%s\n", decrypted);
}
MSVC does not support Variable Length Arrays. One way round is to allocate the memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void encryptDecrypt(char *input, char *output) {
char key[] = {'K', 'C', 'Q'}; //Can be any chars, and any size array
size_t i;
for(i = 0; i < strlen(input); i++) {
output[i] = input[i] ^ key[i % (sizeof(key)/sizeof(char))];
}
output[i] = '\0'; // terminate
}
int main () {
char baseStr[] = "kylewbanks.com";
size_t len = strlen(baseStr) + 1;
char *encrypted = malloc(len);
if(encrypted == NULL) {
// error handling
}
encryptDecrypt(baseStr, encrypted);
printf("Encrypted:%s\n", encrypted);
char *decrypted = malloc(len);
if(decrypted == NULL) {
// error handling
}
encryptDecrypt(encrypted, decrypted);
printf("Decrypted:%s\n", decrypted);
free(decrypted);
free(encrypted);
}
Please note that an extra byte is needed for the string terminator - and the string should be terminated.
Related
In the code below the debugger shows no error but when I run this piece of code inside a function scope char *s is also in the function scope the debugger gives a segmentation error for the strlen function. Would adding char *s as a parameter solve the problem? Or is it something else?
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <locale.h>
#define SIZE1 100
#define SIZE2 2000
int main() {
const char *getFileExtension(const char *filename);
char tags[100][2000];
char files[100][2000];
char paths[100][2000];
char textfiles[100][2000];
char orph[100][2000];
int i, j, k = 0;
char *s;
for (i = 0; i < SIZE1; i++) {
if (strncmp(getFileExtension(files[i]), "txt", 3) == 0) {
strcpy(textfiles[k], files[i]);
k++;
}
}
k = 0;
for (i = 0; i < SIZE1; i++) {
for (j = 0; j < SIZE1; j++) {
if (strcmp(tags[i], textfiles[j]) != 0) {
snprintf(s, strlen(tags[i]), "%s", tags[i]);
s[strlen(s) - 1] = '\0';
strcpy(orph[k], s);
k++;
}
}
}
return 0;
}
const char *getFileExtension(const char *filename) {
const char *dot = strrchr(filename, '.');
if (!dot || dot == filename)
return "";
return dot + 1;
}
EDIT: after initializing char *s and the other arrays I ran my code on devc++ and www.onlinegdb.com. It kept giving me a segmentation fault on devc++ but the code worked on the website.
You declared uninitialized arrays
char tags[100][2000];
char files[100][2000];
char paths[100][2000];
char textfiles[100][2000];
char orph[100][2000];
So using them in standard C string functions like for example
if(strcmp(tags[i],textfiles[j])!=0)
{
snprintf(s,strlen(tags[i]),"%s",tags[i]);
invokes undefined behavior.
It seems the function getFileExtension also does not set elements of the array files in this call.
getFileExtension(files[i])
Also the pointer s
char *s;
used in this statement
snprintf(s,strlen(tags[i]),"%s",tags[i]);
also has an indeterminate value.
your tags array is not initialized. so strlen has undefined behavior. snprintf requires the size of available space not the length of the (uninitialized) contents. you should use sizeof instead of strlen in the snprintf call.
The 2nd argument to snprintf is the size which was allocated to the first argument. But you allocated nothing.
i'm trying to create a random strings using this function:
static char *rand_string(char *str)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
int i;
for ( i = 0; i < 10; i++)
{
int key = rand() % (int) (sizeof charset - 1);
str[i] = charset[key];
}
str[11] = '\0';
return str;
}
The problem is this: sometimes when i am going to print the pointer, it display some strange char like this:
As you can see in the first launch the chars in a string are 10, in the second and third launch the chars in a string are 11...
This is my program:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
static char *rand_string(char *str);
int main()
{
char *string, //str
*string_result; //str1
int dimensione= 15,
i;
for(i=0;i<dimensione;i++)
{
string_result = rand_string(string);
printf("%s\n", string_result);
}
}
static char *rand_string(char *str)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
int i;
for ( i = 0; i < 10; i++)
{
int key = rand() % (int) (sizeof charset - 1);
str[i] = charset[key];
}
str[11] = '\0';
return str;
}
You can view and test my code here --> https://onlinegdb.com/r1yY8DWc8
Your whole code invoke undefined behavior, because you are passing string which is an uninitialized pointer which may "not" be guaranteed to accessible for the 11 bytes your are accessing in the rand_string() function.
You need to allocate memory from the main() and pass that buffer to be filled by the random string generator function, that way you have control of the memory you are modifying.
Also the for loop in your generator already fills indices from 0 to 9. To set the final byte to NULL, you need to use the index as 10.
Also the headers time.h and unistd.h are useless here. Here is a re-write of the same program with memory allocated through malloc(). Also modified your function rand_string() to void instead of returning a string.
#include <stdio.h>
#include <stdlib.h>
void rand_string(char *str);
int main()
{
int dimensione= 15;
char *string = malloc(11 * sizeof *string); // extra byte for NULL
if (!string) return 1;
int i;
for(i=0;i<dimensione;i++)
{
rand_string(string);
printf("%s\n", string);
}
free(string);
return 0;
}
void rand_string(char *str)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
int i;
for ( i = 0; i < 10; i++)
{
int key = rand() % (int) (sizeof charset - 1);
str[i] = charset[key];
}
str[10] = '\0';
}
Always compile with extra flags to enable all sorts of warnings from your compiler. For e.g. with gcc always add -Wall -Wextra to see the warnings that you could fix from your side.
I try to learn the XOR algorithm using C. I have found a great example on KyleBank's GitHub:
#include <stdio.h>
#include <string.h>
void encryptDecrypt(char *input, char *output) {
char key[] = {'K', 'C', 'Q'}; //Can be any chars, and any size array
int i;
for(i = 0; i < strlen(input); i++) {
output[i] = input[i] ^ key[i % (sizeof(key)/sizeof(char))];
}
}
int main (int argc, char *argv[]) {
char baseStr[] = "kylewbanks.com";
char encrypted[strlen(baseStr)];
encryptDecrypt(baseStr, encrypted);
printf("Encrypted:%s\n", encrypted);
char decrypted[strlen(baseStr)];
encryptDecrypt(encrypted, decrypted);
printf("Decrypted:%s\n", decrypted);
}
The above works well under Linux and gcc.
However, it does not compile in Visual Studio under Windows.
I am using build tools included in Visual Studio 2017.
What am I doing wrong?
Microsoft's compiler does not support C99 VLAs (see the note here). Array sizes must be a constant expression. The code is also broken because it fails accommodate and place a nul terminator in the output.
In this case, decrypted and encrypted might be declared thus:
char encrypted[sizeof(baseStr)] ;
...
char decrypted[sizeof(baseStr)] ;
And encryptDecrypt() modified thus:
void encryptDecrypt(char *input, char *output) {
...
output[i] = 0 ;
}
Finally the signed mismatch warning may be cleaned up by declaring i as type size_t.
On Windows of course you could always use MinGW/GCC if you want more modern C support. Or you could use C++ and std::string or std::vector containers if you want to stick with Microsoft's compiler.
Use malloc for dynamic memory allocation. Requires #include <stdlib.h>
char baseStr[] = "123";
char *encrypted = malloc(strlen(baseStr) + 1);
...
free(encrypted);
As mentioned before, you have to add 1 for the null-terminated character at the end.
The char* pointer is one piece of information, it shows where the string begins. But where does it end? strlen and other C functions have no idea where the string ends, so they go through all the characters until a '\0' character is encountered.
For efficiency, take strlen(input) out of the loop and calculate it only once:
void encryptDecrypt(char *input, char *output)
{
char key[] = { 'K', 'C', 'Q' };
int keysize = sizeof(key);
size_t i;
size_t len = strlen(input);
for(i = 0; i < len; i++)
output[i] = input[i] ^ key[i % keysize];
output[len] = 0; //will be same as output[i] = 0;
}
The function int main should return zero. Note that this method cannot be described as "encryption" by modern standards. You can call it "obfuscation".
I am try to write a user defined function which will do exactly what strcpy() library function do. But although there is no error, my program crashes and not copying second string to first string. What's wrong with this code and how to fix it?
#include<stdio.h>
#include<string.h>
int main(){
char *ch1="abcd";
char *ch2="efgh";
str_cpy(ch1,ch2);
}
str_cpy(char *c1,char *c2){
int i=0;
while(c1[i]!='\0'){
i++;
}
printf("%c",*(c1+3));
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
String literals are generally put into read only area, that's why the program crashed when you are writing into c1. The destination string needs to be an array or allocated buffer:
char c1[5];
str_cpy(c1, c2);
Also, in the function, it looks you are copying c2 to c1, but you are counting the length of c1, you should count the length of c2 instead:
// copy string c2 to c1
void str_cpy(char *c1, const char *c2){
int i=0;
while(c2[i]!='\0'){
i++;
}
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
Your program invokes undefined behavior because you are trying to write to a string literal. String literals can be stored in read only memory, which is probably the case on your system, hence causing a crash.
Note that your string copying function can perform the copy in a single loop:
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
You can verify the behavior with a modified main:
#include <stdio.h>
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
int main(void) {
char buf[20];
char *ch2 = "Hello world\n";
printf("%s\n", str_cpy(buf, ch2));
return 0;
}
Here is a possible rework of your code, which doesn't have to pre-define buffer size (c1). You simply pass the buffer address. Also, please note that such buffer has to be freed once used (for example, if declared in local scope, not in main()):
#include <stdio.h>
#include <stdlib.h>
char *str_cpy(char **c1, const char *c2) {
int i, size = 0;
for(i = 0; ; i++)
if(c2[i] == '\0')break;
size = i + 1;
if(!(*c1 = realloc(*c1,size*sizeof(char))))
return *c1;//or devise some more sophisticated error handling
for (i = 0;; i++) {
(*c1)[i] = c2[i];
if (c2[i] == '\0')
return *c1;
}
}
int main(void){
char *ch1 = malloc(1); //you're responsible for freeing it, once used
char *ch2 = "Hello, everybody in the neighborhood!";
printf("%s\n",str_cpy(&ch1,ch2));
free(ch1);
return 0;
}
Please, also note you don't need to #include <string.h>
I have a piece of code that looks like this
#include <stdio.h>
int main()
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
for(i = 0; i < number_of_chunks; i++)
{
char *chunk = some_hash_table.pop(i);
asprintf(&final_string, "%s%s", (final_string==NULL?"":final_string), chunk);
}
free(final_string);
return 0;
}
Here I am concatinating string chunks dynamically, meaning I don't know the size of each chunk in advance. For this I am using asprintf. The code works fine, however rise some serious memory issue. My doubt is asprintf allocates memory in each iteration and the code loses pointer in each iteration. If there is any other way I can concate string inside loop please guide me
To put your question in the simplest possible way, what you are essentially trying to do with the above code is
1. Allocate memory to a pointer continuously(in your case 12 times in the for loop) and
2. free it at the end only once, which is causing memory leak.
Like in the below code
#include <stdio.h>
int main()
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
for(i = 0; i < number_of_chunks; i++)
{
/*For example: similar to what asprintf does, allocate memory to the pointer*/
final_string = malloc(1);
}
free(final_string);
return 0;
}
From the above example it is easily visible that you have allocated the memory 12 times but freed only once.
code snippet:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
char *tmp = NULL;
for(i = 0; i < number_of_chunks; i++)
{
char *chunk = some_hash_table.pop(i);
asprintf(&final_string, "%s%s", (tmp==NULL?"":tmp), chunk);
if (tmp)
free(tmp);
tmp = final_string;
}
printf("%s\n", final_string);
free(final_string);
return 0;
}
Others have already pointed out that you lose the reference to all but the last allocation and that having the same string that is written to as printf argument is probably undefined behaviour, even more so as re-allocations might occur and invalidate the format argument.
You don't use asprintf's formatting capabilities, you use it only to concatenate strings, so you might want to take another approach. You could either collect the strings in an array, determine the needed length, allocate as appropriate and fill the allocated buffer with memcpy.
Or you could write a self-allocating string buffer similar to C++'s std::stringstream, for example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct append_t {
char *str; /* string */
size_t len; /* length of string */
size_t size; /* allocated size */
};
void append(struct append_t *app, const char *str)
{
size_t len = strlen(str);
while (app->len + len + 1 >= app->size) {
app->size = app->size ? app->size * 2 : 0x100;
app->str = realloc(app->str, app->size);
/* error handling on NULL re-allocation */
}
strcpy(app->str + app->len, str);
app->len += len;
}
int main(int argc, char **argv)
{
struct append_t app = {NULL};
for (int i = 1; i < argc; i++) {
append(&app, argv[i]);
}
if (app.str) puts(app.str);
free(app.str);
return 0;
}