微小的加密算法实现会产生意想不到的结果

时间:2017-05-11 14:21:31

标签: c++ encryption

以下是TEA的实现,它尝试加密包含文本消息的文件:

main.cpp

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

#include "TEA.h"

int main()
try
{
     // std::cout <<"sizeof(long) = " << sizeof(long) <<'\n';
     std::string src("in.txt");
     std::string dest("out.txt");
     std::string key("bs");

     send_msg(src, dest, key);
}
catch(std::exception& e)
{
    std::cerr << e.what();
    exit(1);
}

TEA.h

#ifndef TEA_h
#define TEA_h

/*
    src - eight (2 words or 2*4 bytes) characters to be enciphered.
    dest- enciphered output.
    key - array of 4 words.

    Assumes sizeof(long) == 4 bytes.
*/
void encipher(const unsigned long* const v,
              unsigned long* const w, 
              const unsigned long* const k)
{
    unsigned long y = v[0];
    unsigned long z = v[1];
    unsigned long sum = 0;
    unsigned long delta = 0x9E3779B9;
    unsigned long n = 32;

    while (n-- > 0)
    {
        y += (z<<4 ^ z>>5) + z^sum + k[sum&3];

        sum += delta;

        z += (z<<4 ^ z>>5) + y^sum + k[sum>>11&3];
    }

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

//---------------------------------------------------------------------------
/*
    Sends the clear text from: src_file as
    encrypted text to: dest_file, using TEA
    with key: the last argument.
*/
void send_msg(std::string& src_file, 
              std::string& dest_file,
              std::string key)
{
    const int nchar = 2 * sizeof(long);     // size of I/O chunk: 8 bytes = 64 bits
    const int kchar = 2 * nchar;            // size of key: 16 bytes = 128 bits
    // pad key with 0's to match en-/de- cipher argument input size
    while (key.size() < kchar)
    {
        key += '0';
    }

    // prepare files
    std::ifstream ifs(src_file.c_str());
    std::ofstream ofs(dest_file.c_str());

    if (!ifs || !ofs)
    {
        throw std::runtime_error("File can't open!\n");
    }

    // key: extract raw string data interpreted as pointer to const unsigned long 
    const unsigned long* k = reinterpret_cast<const unsigned long*>(key.data());

    // define C-compatible way to read & write from / to file 128 bits (two unsigned longs) at a time
    unsigned long outptr[2]; 

    char inbuf[nchar];

    unsigned long* inptr = reinterpret_cast<unsigned long*>(inbuf);

    int count = 0;

    while (ifs.get(inbuf[count]))
    {
        ofs << std::hex; // write output in hex 

        if (++count == nchar) // 8 characters in the input buffer: ready to encode
        {
            encipher(inptr, outptr, k);

            // pad with leading 0's
            ofs << std::setw(8) << std::setfill('0') << outptr[0] <<' '
                << std::setw(8) << std::setfill('0') << outptr[1] <<' ';

            count = 0;
        }
    }

    if (count) // pad at the end
    {
        while (count != nchar)
        {
            inbuf[count++] = '0';
        }

        encipher(inptr, outptr, k);
        ofs << outptr[0] <<' '<< outptr[1] <<' '; 
    }
}

#endif

输入文件in.txt

  

The Tiny

预计在输出文件中:

  

5b8fb57c 806fbcce

输出文件中的实际值out.txt

  

f3a810ff 3874d755

我做错了什么?

2 个答案:

答案 0 :(得分:4)

+操作的优先级高于^,因此(z<<4 ^ z>>5) + z^sum + k[sum&3]被解析为

(((z<<4) ^ (z>>5)) + z)^(sum + k[sum&3]).

与其他表达相似。

您应该添加括号以使表达式在其执行方式中明确。

答案 1 :(得分:0)

问题确实与那些表达式有关(由@ 1201ProgramAlarm指出),但是,它与(错误的)隐式运算符优先级(也不是arity)无关。

y += (z<<4 ^ z>>5) + z^sum + k[sum&3];

sum += delta;

z += (z<<4 ^ z>>5) + y^sum + k[sum>>11&3]; // <------ the problem is here

左右位移操作必须应用于变量y,即:

z += (y<<4 ^ y>>5) + y^sum + k[sum>>11&3];