How to encrypt strings during build and decrypt after started the program

Hi all,

I'm working on a program and it contains lots of strings. I wan't to make it impossible to change these strings using hex editor. So the question is how can i do that ?
You can encrypt them with some algorithm like blowfish.
http://www.eecis.udel.edu/~bmiller/cis364/2012s/hw/hw3/code/blowfish-test.c
Thank you for your answer. I wonder is there any option which is better..
By better, do you mean simpler?
Yes but it seems i still can see the strings using hex editor until i write only encrypted string. Like this:

1
2
3
4
5
6
7
8
9
10
  unsigned char *out = OUT_OF_A_STRING;
  unsigned char *out2 = calloc(SIZE+1, sizeof(char));
  BF_KEY *key = calloc(1, sizeof(BF_KEY));

  /* set up a test key */
  BF_set_key(key, SIZE, (const unsigned char*)"TestKey!" );

  /* test out decryption */
  BF_ecb_encrypt(out, out2, key, BF_DECRYPT);
  printf("%s\n", out2);


So it means i have to get "out" of all of my strings and replace them all and then i have to add encrypt codes for every one of them. I have many strings and it will take a long time with this method.

Is there any way to make this method(or any other method) for all strings automatically or something with less trouble to modify the strings ?
Clearly, you wouldn't store the keys in the program. Nor would you sore the strings you want to encode (the plain text). You're place the encrypted strings (cypher text) in the program and supply the key at runtime.
Any example ?
I've written some stuff, it goes like this.

You create a resource file with the string definitions, str.rc.
1
2
Name:kbw
Id:Forum


I've written lrc, the lazy resource compiler that compiles this resource file and generates str.h and str.c which hold the encrypted text.

generated str.h
1
2
3
4
#pragma once

extern const char* Name;
extern const char* Id;


generated str.c
1
2
3
4
#include "str.h"

const char* Name = "\x24\x16\x16\xa8\xc5\x3a\xfb\x7e";
const char* Id = "\x59\x7e\x5c\x02\xf8\x52\xe8\x4c";


Here's the lazy resource compiler, lrc.cpp:
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
// lrc: read str.rc and generate str.h, str.cpp

#include <openssl/blowfish.h>

#include <fstream>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

#include <string.h>

int main()
{
        std::string passwd;
        std::cout << "password: ";
        std::getline(std::cin, passwd);

        BF_KEY* key = new BF_KEY;
        memset(key, 0, sizeof(BF_KEY));
        BF_set_key(key, passwd.size(), (unsigned char*)passwd.c_str());

        // blowfish block size is 8
        const size_t blocksize = 8;
        unsigned char plaintext[ blocksize + 1 ];
        unsigned char cyphertext[ blocksize + 1 ];

        std::ofstream hdr("str.h");
        hdr << "#pragma once" << std::endl << std::endl;

        std::ofstream bdy("str.c");
        bdy << "#include \"str.h\"" << std::endl << std::endl;

        std::ifstream is("str.rc");
        std::string line;
        while (std::getline(is, line))
        {
                // line format is ID:str
                size_t p = line.find(':');
                if (p == std::string::npos)
                {
                        std::clog << "lazy resource compiler cannot process line: " << line << std::endl;
                        return 1;
                }

                std::string id = line.substr(0, p);
                std::string str = line.substr(p + 1);
                if (str.empty())
                {
                        std::clog << "lazy resource compiler doesn't like empty strings" << std::endl;
                        return 1;
                }
                if (str.size() > 8)
                {
                        std::clog << "lazy resource compiler doesn't like long strings" << std::endl;
                        return 1;
                }

                // copy in plain text and encypt
                memset(plaintext, 0, blocksize);
                memset(cyphertext, 0, blocksize);

                strcpy((char*)plaintext, str.c_str());
                BF_ecb_encrypt(plaintext, cyphertext, key, BF_ENCRYPT);

                // write output
                hdr << "extern const char* " << id << ";" << std::endl;

                bdy << "const char* " << id << " = " << "\"";
                for (size_t i = 0; i != blocksize; ++i)
                        bdy << "\\x" << std::setw(2) << std::setfill('0') << std::hex << (unsigned)cyphertext[i];
                bdy << "\";" << std::endl;
        }

        delete key;

        return 0;
}


Here's a program that displays the strings, showstr.cpp:
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
#include "str.h"

#include <openssl/blowfish.h>

#include <iostream>
#include <string>

#include <string.h>

std::string decodestr(BF_KEY* key, const char* str)
{
        unsigned char out[64];
        memset(out, 0, sizeof(out));

        BF_ecb_encrypt((const unsigned char*)str, out, key, BF_DECRYPT);
        return (const char*)out;
}

int main()
{
        std::string passwd;
        std::cout << "password: ";
        std::getline(std::cin, passwd);

        BF_KEY* key = new BF_KEY;
        memset(key, 0, sizeof(BF_KEY));
        BF_set_key(key, passwd.size(), (const unsigned char*)passwd.c_str());

        std::cout << decodestr(key, Name) << std::endl;
        std::cout << decodestr(key, Id) << std::endl;

        delete key;
        return 0;
}


You compile them as follows:
1
2
g++ lrc.cpp -o lrc -lcrypto
g++ showstr.cpp str.c -o showstr -lcrypto


When you run lrc, it prompts you for a password and uses that to encrypt a the strings in str.c.

When you run showstr, it prompts you for a password and uses that to decrypt the strings in str.c and displays them.
Last edited on
Hmm, yes... But i couldn't make showstr.cpp work. Can you send the project files ?
I've already posted everything, there's nothing else. I didn't use an IDE project, I just compiled the files from the command line using g++ as shown. It works on Windows (cygwin), OS X and Linux as is and requires OpenSSL (devel) be installed.

You have to build the excutable showstr from showstr.cpp and str.cpp as I mention at the end. If you think about it, that's of the point, as showstr is displaying the strings we compiled into str.cpp.

It occured to me that the password could be stored in str.cpp in cleartext. As the idea is just to obscure the strings in the program, there's no harm in doing so, and the program can decode the strings without requireing the user to enter a password.

Also, as Blowfish encrypts 64bit blocks, you're restricted to 8 byte strings. But I would expect you to remove this restriction once you understood how the whole thing hangs together. I wrote it late at night and didn't want to spend time dealing with that issue at the time (or now either).
Last edited on
Ok, thanks for your help.
Topic archived. No new replies allowed.