CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

# Thread: How to use the TEA Algorithm to deal with human readable text

1. Member
Join Date
Jun 2015
Posts
175

## How to use the TEA Algorithm to deal with human readable text

Here's my TEA algorithm that I like to use for dealing with texts that humans can understand, i.e., English characters.

Code:
```#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <exception>

void encipher(
const unsigned long* const v,
unsigned long* const w,
const unsigned long* const k)
{
static_assert(sizeof(long) == 4, "size of long wrong for TEA");
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0;
const unsigned long delta = 0x9E3779B9;

for (unsigned long n = 32; n-- > 0; ) {
y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
sum += delta;
z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
}
w[0] = y;
w[1] = z;
}

//*****************************************************

void decipher(
const unsigned long* const v,
unsigned long* const w,
const unsigned long* const k)
{
static_assert(sizeof(long) == 4, "size of long wrong for TEA");
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0xC6EF3720;
const unsigned long delta = 0x9E3779B9;

// sum = delta<<5, in general sum = delta * n
for (unsigned long n = 32; n-- > 0; ) {
z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
sum -= delta;
y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
}
w[0] = y;
w[1] = z;
}

//*****************************************************

int main() try
{
const int nchar = 2 * sizeof(long); // 64 bits
const int kchar = 2 * nchar; // 128 bits
//std::cout << nchar << ' ' << kchar << '\n';

std::string op;
std::string key;
std::string infile;
std::string outfile;

std::cout << "please enter input file name, output file name, and key:\n";
std::cin >> infile >> outfile >> key;

while (key.size() < kchar) key += '0'; // pad key

std::ifstream inf(infile);
std::ofstream outf(outfile);

if (!inf || !outf) throw("bad file name");

const unsigned long* k = reinterpret_cast<const unsigned long*>(key.data());
unsigned long outptr[2];
char inbuf[nchar];
unsigned long* inptr = reinterpret_cast<unsigned long*>(inbuf);
int count = 0;

while (inf.get(inbuf[count])) {
outf << std::hex; // use hexadecimal output
if (++count == nchar) {
decipher(inptr, outptr, k);
outf << std::setw(8) << std::setfill('0') << outptr[0] << ' '
<< std::setw(8) << std::setfill('0') << outptr[1] << ' ';
count = 0;
}
}

while (count != nchar) inbuf[count++] = '0';
decipher(inptr, outptr, k);
outf << outptr[0] << ' ' << outptr[1] << ' ';
}

system("pause");
return 0;
}

catch (std::invalid_argument& e) {
std::cerr << e.what() << '\n';
abort();
}```
There're two .txt files in the project's directory named input and output with the former with no data (empty) and the latter with the content below:

5b8fb57c 806fbcce 2db72335 23989d1d 991206bc 0363a308
8f8111ac 38f3f2f3 9110a4bb c5e1389f 64d7efe8 ba133559
4cc00fa0 6f77e537 bde7925f f87045f0 472bad6e dd228bc3
a5686903 51cc9a61 fc19144e d3bcde62 4fdb7dc8 43d565e5
f1d3f026 b2887412 97580690 d2ea4f8b 2d8fb3b7 936cfa6d
6a13ef90 fd036721 b80035e1 7467d8d8 d32bb67e 29923fde
197d4cd6 76874951 418e8a43 e9644c2a eb10e848 ba67dcd8
7115211f dbe32069 e4e92f87 8bf3e33e b18f942c c965b87a
44489114 18d4f2bc 256da1bf c57b1788 9113c372 12662c23
eeb63c45 82499657 a8265f44 7c866aae 7c80a631 e91475e1
5991ab8b 6aedbb73 71b642c4 8d78f68b d602bfe4 d1eadde7
55f20835 1a6d3a4b 202c36b8 66a1e0f2 771993f3 11d1d0ab
74a8cfd4 4ce54f5a e5fda09d acbdf110 259a1a19 b964a3a9
456fd8a3 1e78591b 07c8f5a2 101641ec d0c9d7e1 60dbeb11
d018e61c d1c94ea6 6ca73314 cd60def1 6e16870e 45b94dc0
d7b44fcd 96e0425a 72839f71 d5b6427c 214340f9 8745882f
0602c1a2 b437c759 ca0e3903 bd4d8460 edd0551e 31d34dd3
c3f943ed d2cae477 4d9d0b61 f647c377 0d9d303a ce1de974
f9449784 df460350 5d42b06c d4dedb54 17811b5f 4f723692
14d67edb 11da5447 67bc059a 4600f047 63e439e3 2e9d15f7
4f21bbbe 3d7c5e9b 433564f5 c3ff2597 3a1ea1df 305e2713
9421d209 2b52384f f78fbae7 d03c1f58 6832680a 207609f3
9f2c5a59 ee31f147 2ebc3651 e017d9d6 d6d60ce2 2be1f2f9
eb9de5a8 95657e30 cad37fda 7bce06f4 457daf44 eb257206
418c24a5 de687477 5c1b3155 f744fbff 26800820 92224e9d
43c03a51 d168f2d1 624c54fe 73c99473 1bce8fbb 62452495
5de382c1 1a789445 aa00178a 3e583446 dcbd64c5 ddda1e73
fa168da2 60bc109e 7102ce40 9fed3a0b 44245e5d f612ed4c
b5c161f8 97ff2fc0 1dbf5674 45965600 b04c0afa b537a770
9ab9bee7 1624516c 0d3e556b 6de6eda7 d159b10e 71d5c1a6
b8bb87de 316a0fc9 62c01a3d 0a24a51f 86365842 52dabf4d
372ac18b 9a5df281 35c9f8d7 07c8f9b4 36b6d9a5 a08ae934
239efba5 5fe3fa6f 659df805 faf4c378 4c2048d6 e8bf4939
31167a93 43d17818 998ba244 55dba8ee 799e07e7 43d26aef
d5682864 05e641dc b5948ec8 03457e3f 80c934fe cc5ad4f9
0dc16bb2 a50aa1ef d62ef1cd f8fbbf67 30c17f12 718f4d9a
43295fed 561de2a0

Now when I run the program and enter the name of both files as input/output (input.txt, output.txt) plus the key which is "bs", the output file is filled out with hexadecimal data by the program! How to make the output file's content readable by humans, please?

2. ## Re: How to use the TEA Algorithm to deal with human readable text

Originally Posted by tomy12
Code:
```    while (inf.get(inbuf[count])) {
outf << std::hex; // use hexadecimal output
...```
Now when I run the program ..., the output file is filled out with hexadecimal data by the program! How to make the output file's content readable by humans, please?
Isn't it because of your using std::hex by outputting?

3. ## Re: How to use the TEA Algorithm to deal with human readable text

So the contents of the input file is as given above? You are expecting the output file to be readable? What are expecting the output file to contain?

decipher() returns 2 32-bit numbers via w (outptr[0] and outptr[1]). These two numbers are then displayed as hex. what do these 2 numbers represent? How are they supposed to be shown as readable?

Looking at encipher(), this converts 2 32-bit numbers into another 2 32-bit numbers. This process is reversed in decipher(). This is all based on 32 bit numbers. Readable text doesn't come into it. For this to work with text, then you need to first convert the text into a sequence of 2 32-bit number pairs which are then enciphered. Then for the deciphering, you re-convert the 2 32-bit numbers returned back into text using the reverse of how the text was first coded into pairs of 32-bit numbers.

4. Member
Join Date
Jun 2015
Posts
175

## Re: How to use the TEA Algorithm to deal with human readable text

@VictorN: Isn't it because of your using std::hex by outputting?
I agree, but when commenting it the output contains only numbers this time. :|

@2Kaud: What are expecting the output file to contain?
The same data but with a English character format do that you and I (people) can figure out what has been the plain text.

That's the TEA algorithm, which a famous and a good practice for embedded programming.

5. ## Re: How to use the TEA Algorithm to deal with human readable text

As I said in my previous post, TEA operates on 2 32-bit numbers. It takes 2 numbers as input and produces 2 numbers as output. If you want this to operate with text, then for encryption you have to convert the text into a sequence of 2 32-bit numbers for encryption - and for decryption you have to covert the decrypted sequence of 2 32-bit numbers into text. This is not part of TEA itself.

There are programs on the internet to do this, but just code your own.

6. ## Re: How to use the TEA Algorithm to deal with human readable text

As a simple example of use with a text file, consider this. It takes an input file in plain text, encrypts to an output file and then decrypts the output file to the decrypted file in plain text.

Code:
```#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <exception>
#include <cstdlib>

void encipher(
const unsigned long* const v,
unsigned long* const w,
const unsigned long* const k)
{
static_assert(sizeof(long) == 4, "size of long wrong for TEA");
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0;
const unsigned long delta = 0x9E3779B9;

for (unsigned long n = 32; n-- > 0; ) {
y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
sum += delta;
z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
}

w[0] = y;
w[1] = z;
}

//*****************************************************

void decipher(
const unsigned long* const v,
unsigned long* const w,
const unsigned long* const k)
{
static_assert(sizeof(long) == 4, "size of long wrong for TEA");
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0xC6EF3720;
const unsigned long delta = 0x9E3779B9;

// sum = delta<<5, in general sum = delta * n
for (unsigned long n = 32; n-- > 0; ) {
z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
sum -= delta;
y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
}

w[0] = y;
w[1] = z;
}

unsigned long tohex(const char hex[9])
{
return std::strtoul(hex, NULL, 16);
}

int main() try
{
const int nchar = 2 * sizeof(long); // 64 bits
const int kchar = 2 * nchar; // 128 bits

std::string op;
std::string key;
std::string infile;
std::string outfile;
std::string decfile;

std::cout << "please enter input file name, encrypted file name, decrypted file name and key:\n";
std::cin >> infile >> outfile >> decfile >> key;

while (key.size() < kchar) key += '0'; // pad key

std::ifstream inf(infile);
std::ofstream outf(outfile);
std::ofstream decf(decfile);

if (!inf || !outf || !decf) throw("bad file name");

const unsigned long* k = reinterpret_cast<const unsigned long*>(key.data());
unsigned long outptr[2];
char inbuf[nchar + 1] {};
unsigned long* inptr = reinterpret_cast<unsigned long*>(inbuf);

encipher(inptr, outptr, k);
outf << std::hex << std::setw(8) << std::setfill('0') << outptr[0] << ' ' << std::setw(8) << std::setfill('0') << outptr[1] << ' ';
}

if (inf.gcount() != nchar) {
inf.clear();
memset(inbuf, 0, nchar + 1);
inf.seekg(-(nchar - inf.gcount() + 1), std::ios_base::end);
inf.read(inbuf, nchar - inf.gcount() - 1);
encipher(inptr, outptr, k);
outf << std::hex << std::setw(8) << std::setfill('0') << outptr[0] << ' ' << std::setw(8) << std::setfill('0') << outptr[1] << ' ';
}

inf.close();
outf.close();
inf.open(outfile);

unsigned long decptr[2];
char convbuf[2][nchar + 1] {};

decptr[0] = tohex(convbuf[0]);
decptr[1] = tohex(convbuf[1]);

decipher(decptr, outptr, k);

decf.write((char*)&outptr[0], 4);
decf.write((char*)&outptr[1], 4);
}
}

catch (std::invalid_argument& e) {
std::cerr << e.what() << '\n';
abort();
}```

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•