CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6

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

  1. #1
    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);
                // pad with leading zeros:
                outf << std::setw(8) << std::setfill('0') << outptr[0] << ' '
                    << std::setw(8) << std::setfill('0') << outptr[1] << ' ';
                count = 0;
            }
        }
    
        if (count) { // pad
            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
    b9ad8e72 ad30b839 201fc553 a34a79c4 217ca84d 30f666c6
    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. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,980

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

    Quote Originally Posted by tomy12 View Post
    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?
    Victor Nijegorodov

  3. #3
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,484

    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.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++20 Compiler: Microsoft VS2019 (16.10.0)

  4. #4
    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. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,484

    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.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++20 Compiler: Microsoft VS2019 (16.10.0)

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,484

    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);
    
    	while (inf.read(inbuf, nchar)) {
    		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] {};
    
    	while (inf.read(convbuf[0], 8) && inf.ignore() && inf.read(convbuf[1], 8) && inf.ignore()) {
    		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();
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++20 Compiler: Microsoft VS2019 (16.10.0)

Posting Permissions

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


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)