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



这是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

渺小的

输出文件中的预期内容:

5b8fb57c 806fbcce

在输出文件中实际,out.txt

F3A810FF 3874D755

我做错了什么?


+运算的优先级高于^,所以(z<<4 ^ z>>5) + z^sum + k[sum&3]解析为

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

其他表达式也是如此。

应添加括号以使表达式明确执行方式。

这个问题确实与这些表达式有关(由@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];

最新更新