C++ TEA algorithm confusion

I'm going to use the C++ TEA algorithm in an application. Unfortunately I couldn't find a C++ complete version of that algorithm with good comments throughout its code so that it can be figured out what each part of the algorithm do.
I faced the algorithm in the book Programming Principle and Practice using C++ 2nd edition first printing.

There in section 25.5.6 we have:

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
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;
}


And the main function as below for which he says: "We can use TEA like this to produce a file to be sent over an unsafe connection"


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
int main() // sender
{
    const int nchar = 2 * sizeof(long); // 64 bits
    const int kchar = 2 * nchar; // 128 bits
    string op;
    string key;
    string infile;
    string outfile;

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

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

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

    if (!inf || !outf) error("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 << hex; // use hexadecimal output
        if (++count == nchar) {
            encipher(inptr, outptr, k);
            // pad with leading zeros:
            outf << setw(8) << setfill('0') << outptr[0] << ' '
                << setw(8) << setfill('0') << outptr[1] << ' ';
            count = 0;
        }
    }

    if (count) { // pad
        while (count != nchar) inbuf[count++] = '0';
        encipher(inptr, outptr, k);
        outf << outptr[0] << ' ' << outptr[1] << ' ';
    }
}


I have got a few questions:

1) Is the code above written right? (Inside main, the function encipher is called twice!)
2) If so, is it just to produce a enciphered text ready to be sent (something that needs to be deciphered in the destination)?
3) What is string op; (in main) used for, please?
Last edited on
Unfortunately I couldn't find a C++ complete version of that algorithm


And the first hit was:

https://developpaper.com/implementation-of-c-code-of-tea-encryption-algorithm/

with complete code a the github link at the bottom.
I'm going to use the C++ TEA algorithm

Surely you mean: TEA algorithm implemented in C++? Algorithms are generic ideas -- logic.

Never heard of TEA.
https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm

> 1) Is the code above written right? (Inside main, the function encipher is called twice!)
Well you need to understand why count exists and what it does.

> 2) If so, is it just to produce a enciphered text ready to be sent (something that needs to be deciphered in the destination)?
As a minimum, you could pass what you get out of encipher and push it through decipher to see if you get your original message back.

On a fundamental level, it seems hard to prove.
For example, I couldn't find any published examples of "message" + "key" => "cypher".
If there were such a thing (or you can find some), you can independently test that your implementation is the same as everyone else's.

But at the moment, you could have compatible bugs in both your functions which make them appear to work, but broken with respect to everyone else.


> 3) What is string op; (in main) used for, please?
Well you could just search for 'op' using your text editor and find all the places it's mentioned.


@TheIdeasMan
The code differs from the one post here making it worse since I have not understood the current one well enough! By the way, the github link doesn't work!

@salem c:
count is non-zero since the number of chars in the input isn't a multiple of 8.
In both casts we convert a pointer to a null-terminated array of chars into a pointer to const unsigned long because the functions get such a type! Looks rather messy. Each time we send that pointer as one of the arguments to encipher.

As well as, there's no code for *op*. Tested before sending the question.
@frek
The wikipedia article @salem pointed to is all I needed. Unless you haven't worked out the algorithm in detail from the article, which you can, and I haven't, then it all seems fairly straight forward to me. Lucky me :)

The sample data comes from the first external link. There are a couple of simple samples I've added to make sure it's working to my satisfaction.

To me the only problems seem to be vectors would be better than arrays and adding functionality to handle real messages - that's a dead simple string manipulation.


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
#include <iostream>
#include <iomanip>

void encrypt(uint32_t* v, const uint32_t k[4])
{
    uint32_t sum{0};
    uint32_t delta{0x9E3779B9};
    
    for (int i = 0; i < 32; i++)
    {
        sum += delta;
        v[0] += ((v[1]<<4) + k[0]) ^ (v[1] + sum) ^ ((v[1]>>5) + k[1]);
        v[1] += ((v[0]<<4) + k[2]) ^ (v[0] + sum) ^ ((v[0]>>5) + k[3]);
    }
}

void decrypt(uint32_t* v, const uint32_t k[4])
{
    uint32_t sum = 0xC6EF3720;
    uint32_t delta = 0x9E3779B9;
    
    for (int i = 0; i < 32; i++)
    {
        v[1] -= ((v[0]<<4) + k[2]) ^ (v[0] + sum) ^ ((v[0]>>5) + k[3]);
        v[0] -= ((v[1]<<4) + k[0]) ^ (v[1] + sum) ^ ((v[1]>>5) + k[1]);
        sum -= delta;
    }
}

void demonstrate(uint32_t* v, const uint32_t k[4])
{
    std::cout
    << std::hex << std::showbase
    << " Original: " << v[0] << ' ' << v[1] << '\n';
    
    encrypt(v,k);
    std::cout
    << "Encrypted: " << v[0] << ' ' << v[1] << '\n';
    
    decrypt(v,k);
    std::cout
    << "Decrypted: " << v[0] << ' ' << v[1] << '\n'
    << '\n';
}

int main()
{
    uint32_t a = 0x4e238eb9;
    std::cout
    << std::showbase
    << std::hex << a << '\n'
    << std::dec << a << '\n';
    
    uint32_t v1[]{1105869322,2495260992};//{99,88};
    uint32_t k1[]{2495260992,1105869322,802249527,659110869};//{0,0,0,0};
    demonstrate(v1, k1);
    
    uint32_t v2[]{0x31c5fa6c, 0x241756d6};
    uint32_t k2[]{0xbc3a7de2,0x845846cf,0x2794a127,0x6b8ea8b8};
    demonstrate(v2, k2);
    
    uint32_t v3[]{0x2bb0f1b3,0xc023ed11};
    uint32_t k3[]{0x5c60bff2,0x7072d01c,0x4513c5eb,0x8f3a38ab};
    demonstrate(v3, k3);
    
    return 0;
}

/*
   1        0 9e3779b9        0        0         0        0
   2 ec01a1de aaa0256d        0        0         0        0
   4 bc3a7de2 4e238eb9        0        0  ec01a1de 114f6d74
   8 31c5fa6c 241756d6 bc3a7de2 845846cf  2794a127 6b8ea8b8
  16 1d8e6992 9a478905 6a1d78c8  8c86d67  2a65bfbe b4bd6e46
  32 d26428af  a202283 27f917b1 c1da8993  60e2acaa a6eb923d
  64 7a01cbc9 b03d6068 62ee209f  69b7afc  376a8936 cdc9e923
   1        0        0        0        0         0        0

 tea does the same but the number of iterations
 is constant at 32

   1 41ea3a0a 94baa940        0        0         0        0
   2 4e8e7829 7d8236d8        0        0         0 41ea3a0a
   4 b84e28af b6b62088        0 41ea3a0a  4e8e7829 c88ba95e
   8 5ddf75d9 7a4ce68f b84e28af a0a47295  ed650698 1024eea0
  16 4ec5d2e2 5ada1d89 a9c3801a 32a1e654   8b63bb9 21410574
  32 7d2c6c57 7a6adb4d 69c53e0f 60388ada  df70a1f5 d9cb4e09
  64 2bb0f1b3 c023ed11 5c60bff2 7072d01c  4513c5eb 8f3a38ab
   1        0        0        0        0         0        0
 */


Last edited on
Topic archived. No new replies allowed.