我希望在使用新密钥加密AES(如DESX)之前和之后在AES中执行XOR操作。但XOR操作需要花费太多时间。
如何减少XOR操作时间?
这是我的代码:
string XOR(string value, string key)
{
string retval(value);
short unsigned int klen=key.length();
short unsigned int vlen=value.length();
short unsigned int k=0;
short unsigned int v=0;
for(v;v<vlen;v++)
{
retval[v]=value[v]^key[k];
k=(++k<klen?k:0);
}
return retval;
}
int main(int argc, char* argv[])
{
AutoSeededRandomPool prng;
byte key1[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key1, sizeof(key1));
byte key[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key, sizeof(key));
byte key2[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key2, sizeof(key2));
byte iv[AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));
string plain = "AESX CBC Mode Test";
string cipher,encoded, encodediv, encodedkey1, encodedkey,
encodedkey2, recovered, prerecovered, postrecovered,
prewhiten, postwhiten;
// Pretty print key1
StringSource(key1, sizeof(key1), true,
new HexEncoder(
new StringSink(encodedkey1)
) // HexEncoder
); // StringSource
cout << "key1: " << encodedkey1 << endl;
// Pretty print iv
StringSource(iv, sizeof(iv), true,
new HexEncoder(
new StringSink(encodediv)
) // HexEncoder
); // StringSource
cout << "iv: " << encodediv << endl;
// Pretty print key
StringSource(key, sizeof(key), true,
new HexEncoder(
new StringSink(encodedkey)
) // HexEncoder
); // StringSource
cout << "key: " << encodedkey << endl;
// Pretty print key2
StringSource(key2, sizeof(key2), true,
new HexEncoder(
new StringSink(encodedkey2)
) // HexEncoder
); // StringSource
cout << "key2: " << encodedkey2 << endl;
cout << "plain text: " << plain << endl;
prewhiten = XOR(plain, encodedkey1);
try
{
cout << "pre whiten text: " << prewhiten << endl;
CBC_Mode< AES >::Encryption e;
e.SetKeyWithIV(key, sizeof(key), iv);
// The StreamTransformationFilter removes
// padding as required.
StringSource s(prewhiten, true,
new StreamTransformationFilter(e,
new StringSink(cipher)
) // StreamTransformationFilter
); // StringSource
}
catch(const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
exit(1);
}
/*********************************\
\*********************************/
// Pretty print
encoded.clear();
StringSource(cipher, true,
new HexEncoder(
new StringSink(encoded)
) // HexEncoder
); // StringSource
cout << "cipher text: " << encoded << endl;
postwhiten = XOR(encoded, encodedkey2);
cout << "post whiten text: " << postwhiten << endl;
//decryption
prerecovered = XOR(postwhiten, encodedkey2);
encoded.clear();
StringSource(prerecovered, true,
new HexEncoder(
new StringSink(encoded)
) // HexEncoder
); // StringSource
cout << "pre recovered text: " << encoded << endl;
try
{
CBC_Mode< AES >::Decryption d;
d.SetKeyWithIV(key, sizeof(key), iv);
// The StreamTransformationFilter removes
// padding as required.
StringSource s(prerecovered, true,
new HexDecoder(
new StreamTransformationFilter(d,
new StringSink(recovered)
) // StreamTransformationFilter
)//HexDecoder
); // StringSource
cout << "recovered text: " << recovered << endl;
}
catch(const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
exit(1);
}
postrecovered = XOR(recovered, encodedkey1);
cout << "post recovered text: " << postrecovered << endl;
return 0;
}
任何帮助都将不胜感激。
答案 0 :(得分:0)
如何在Crypto ++中进行XOR操作?
使用库执行XOR有两种方法。首先,misc.h
中有两个函数xorbuf
。第一个实现如下所示,它使用带掩码的单个输入/输出缓冲区:
void xorbuf(byte *buf, const byte *mask, size_t count)
{
size_t i=0;
if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
{
if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
{
for (i=0; i<count/8; i++)
((word64*)(void*)buf)[i] ^= ((word64*)(void*)mask)[i];
count -= 8*i;
if (!count)
return;
buf += 8*i;
mask += 8*i;
}
for (i=0; i<count/4; i++)
((word32*)(void*)buf)[i] ^= ((word32*)(void*)mask)[i];
count -= 4*i;
if (!count)
return;
buf += 4*i;
mask += 4*i;
}
for (i=0; i<count; i++)
buf[i] ^= mask[i];
}
第二个xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
使用带掩码的单独输入和输出缓冲区。
XOR的第二种方法是使用filters.h
中的ArrayXorSink
。在内部,ArrayXorSink
为您调用xorbuf
。你会喜欢使用这个pipelines。
size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
// Avoid passing NULL pointer to xorbuf
size_t copied = 0;
if (m_buf && begin)
{
copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
xorbuf(m_buf+m_total, begin, copied);
}
m_total += copied;
return length - copied;
}
string XOR(string value, string key) { string retval(value); short unsigned int klen=key.length(); short unsigned int vlen=value.length(); short unsigned int k=0; short unsigned int v=0; for(v;v<vlen;v++) { retval[v]=value[v]^key[k]; k=(++k<klen?k:0); } return retval; }
为此,您可以执行以下操作。它要求编译器inline
函数,并通过常量引用传递value
和key
以避免副本。
inline string XOR(const string& value, const string& key)
{
ASSERT(key.length() == value.length());
string retval(value);
xorbuf(&retval[0], &key[0], retval.length());
return retval;
}
技巧是,您必须获取元素0的地址以获取非const指针并避免潜在的未定义行为。您可能需要转换为byte*
。
如何减少XOR操作时间?
您可能希望在可行时使用大于1字节的操作数大小。图书馆xorbuf
在可用时使用word32
和word64
。
此外,如果你有AVX,那么你可以在最高512位的缓冲区上运行。如果保持缓冲区对齐,GCC将尝试使用-O3
及更高版本的较大缓冲区。 -O3
很重要,因为当GCC开始积极的矢量化并使用AVX和AVX2提供的功能时。{/ p>
Crypto ++库在几年前经历了一个非常微不足道的痛苦,因为它的缓冲区没有像GCC预期那样对齐,而且它导致了SEGFAULT的-O3
及以上。例如,请参阅Crash on Cygwin i386 with -O3。
对齐问题不仅限于Cygwin; Cygwin碰巧证明了这一点。在启用NEON的情况下,问题在其他平台和CPU之间偶尔浮出水面。我们相信所有问题都已被清除。