如何在 Crypto++ 中进行异或运算?
How can I do XOR operation in Crypto++?
我想在使用新密钥在 AES(如 DESX)加密之前和之后在 AES 中执行异或运算。但是异或操作太费时间了。
如何减少异或运算时间?
这是我的代码:
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;
}
如有任何帮助,我们将不胜感激。
How can I do XOR operation in Crypto++?
有两种方法可以使用该库执行 XOR。首先,misc.h
中有两个函数xorbuf
。第一个实现如下所示,它使用带有掩码的单个 in/out 缓冲区:
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)
使用带有掩码的单独输入和输出缓冲区。
异或的第二种方法是使用来自 filters.h
. Internally, ArrayXorSink
calls xorbuf
for you. You would use this is you prefer pipelines 的 ArrayXorSink
。
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 的地址来获取非常量指针并避免潜在的未定义行为。您可能需要转换为 byte*
.
How can I reduce the XOR operation time?
您可能希望在可行时使用大于 1 字节的操作数大小。图书馆的 xorbuf
在可用时使用 word32
和 word64
。
此外,如果您有 AVX,那么您最多可以对 512 位的缓冲区进行操作。如果您保持缓冲区对齐,那么 GCC 将尝试在 -O3
及以上使用更大的缓冲区。 -O3
很重要,因为那时 GCC 开始积极矢量化并使用 AVX 和 AVX2 提供的功能。
Crypto++ 库在几年前经历了一次不小的痛苦,因为它的缓冲区没有按照 GCC 的预期对齐,并且它导致了 SEGFAULT -O3
及以上。参见,例如,Crash on Cygwin i386 with -O3.
对齐问题不仅限于Cygwin; Cygwin 碰巧演示了它。该问题有时会在其他平台和 CPU 下出现,例如启用 NEON 时的 ARM。我们相信所有问题都已解决。
我想在使用新密钥在 AES(如 DESX)加密之前和之后在 AES 中执行异或运算。但是异或操作太费时间了。
如何减少异或运算时间?
这是我的代码:
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;
}
如有任何帮助,我们将不胜感激。
How can I do XOR operation in Crypto++?
有两种方法可以使用该库执行 XOR。首先,misc.h
中有两个函数xorbuf
。第一个实现如下所示,它使用带有掩码的单个 in/out 缓冲区:
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)
使用带有掩码的单独输入和输出缓冲区。
异或的第二种方法是使用来自 filters.h
. Internally, ArrayXorSink
calls xorbuf
for you. You would use this is you prefer pipelines 的 ArrayXorSink
。
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 的地址来获取非常量指针并避免潜在的未定义行为。您可能需要转换为 byte*
.
How can I reduce the XOR operation time?
您可能希望在可行时使用大于 1 字节的操作数大小。图书馆的 xorbuf
在可用时使用 word32
和 word64
。
此外,如果您有 AVX,那么您最多可以对 512 位的缓冲区进行操作。如果您保持缓冲区对齐,那么 GCC 将尝试在 -O3
及以上使用更大的缓冲区。 -O3
很重要,因为那时 GCC 开始积极矢量化并使用 AVX 和 AVX2 提供的功能。
Crypto++ 库在几年前经历了一次不小的痛苦,因为它的缓冲区没有按照 GCC 的预期对齐,并且它导致了 SEGFAULT -O3
及以上。参见,例如,Crash on Cygwin i386 with -O3.
对齐问题不仅限于Cygwin; Cygwin 碰巧演示了它。该问题有时会在其他平台和 CPU 下出现,例如启用 NEON 时的 ARM。我们相信所有问题都已解决。