你提供的 SHA-256 散列函数,就像大多数加密散列实现一样,接受字节数组作为输入。因此,第一步是对你要散列的数据进行序列化。
这并不是将你的结构体强制转换为字节数组那么简单。序列化应该在操作系统和硬件之间具有可移植性。结构体对齐、字节顺序等可能会因系统而异,因此最好使用一个序列化库,并将所有这些棘手的严格别名问题留给库作者来解决。
最佳选择:序列化库
由于你已经在使用 Boost(float64_t 类型),所以可以使用 Boost 序列化库。首先,创建一个序列化函数,告诉 Boost 如何序列化 A:
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, A & a, const unsigned int version)
{
ar & a.array;
ar & a.x;
ar & a.y;
}
}
}
然后,将其序列化到内存流中:
std::ostringstream plaintext_buffer {};
{
boost::archive::binary_oarchive oa(plaintext_buffer);
oa << a;
}
std::string plaintext = plaintext_buffer.str();
现在你可以使用SHA-256哈希函数。我会将那部分留给你作为练习。
输入:对于数据,请使用
plaintext.data()
,对于大小,请使用
plaintext.size()
输出:
a.validationHash
很好的选择是自定义浮点数序列化程序。
根据评论,你受限于C++03(我将其视为C++98),并且不能使用任何库。因此,首先让我们使用最接近的等效标准类型重新定义您的函数:
struct A
{
double array[4][4];
double x;
double y;
uint8_t validationHash[32];
}
我稍微调整了这个答案:
Serialize double and float with C,该答案声称是一个可移植的IEEE 754序列化器。很酷!我将输出改为内存缓冲区,替换了
goto
并将C转换为
static_cast
。
void serializeIeee754(double x, uint8_t* destination)
{
int shift;
unsigned long sign, exp, hibits, hilong, lowlong;
double fnorm, significand;
int expbits = 11;
int significandbits = 52;
if(x == 0) {
hilong = 0;
lowlong = 0;
} else if(x > DBL_MAX) {
hilong = 1024 + ((1 << (expbits - 1)) - 1);
hilong <<= (31 - expbits);
lowlong = 0;
} else if(x < -DBL_MAX) {
hilong = 1024 + ((1 << (expbits - 1)) - 1);
hilong <<= (31 - expbits);
hilong |= (1 << 31);
lowlong = 0;
} else if(x != x) {
hilong = 1024 + ((1 << (expbits - 1)) - 1);
hilong <<= (31 - expbits);
lowlong = 1234;
} else {
if(x < 0) {
sign = 1;
fnorm = -x;
} else {
sign = 0;
fnorm = x;
}
shift = 0;
while(fnorm >= 2.0) {
fnorm /= 2.0;
shift++;
}
while(fnorm < 1.0) {
fnorm *= 2.0;
shift--;
}
if(shift < -1022) {
while(shift < -1022) {
fnorm /= 2.0;
shift++;
}
shift = -1023;
} else {
fnorm = fnorm - 1.0;
}
significand = fnorm * ((1LL << significandbits) + 0.5f);
exp = shift + ((1 << (expbits - 1)) - 1);
hibits = static_cast<long>(significand / 4294967296);
hilong = (sign << 31) | (exp << (31 - expbits)) | hibits;
lowlong = static_cast<unsigned long>(significand - hibits * 4294967296);
}
destination[0] = lowlong & 0xFF;
destination[1] = (lowlong >> 8) & 0xFF;
destination[2] = (lowlong >> 16) & 0xFF;
destination[3] = (lowlong >> 24) & 0xFF;
destination[4] = hilong & 0xFF;
destination[5] = (hilong >> 8) & 0xFF;
destination[6] = (hilong >> 16) & 0xFF;
destination[7] = (hilong >> 24) & 0xFF;
}
现在,您可以编写自己的序列化程序来为
A
编写一个144字节缓冲区的输出:
void serializeA(A& a, uint8_t destination[144]) {
uint8_t* out = destination;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
serializeIeee754(a.array[i][j], out);
out += 8;
}
}
serializeIeee754(a.x, out);
out += 8;
serializeIeee754(a.y, out);
}
然后将该缓冲区提供给您的哈希函数。
Sha256
函数完成这个任务。该函数可能是为以空字符结尾的字符串作为输入而设计的。你需要告诉我们更多关于该函数的信息。 - Jabberwocky