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