如何在Crypto ++中执行XOR操作?

时间:2017-02-22 19:51:23

标签: c++ encryption aes xor crypto++

我希望在使用新密钥加密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;
}

任何帮助都将不胜感激。

1 个答案:

答案 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函数,并通过常量引用传递valuekey以避免副本。

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在可用时使用word32word64

此外,如果你有AVX,那么你可以在最高512位的缓冲区上运行。如果保持缓冲区对齐,GCC将尝试使用-O3及更高版本的较大缓冲区。 -O3很重要,因为当GCC开始积极的矢量化并使用AVX和AVX2提供的功能时。{/ p>

Crypto ++库在几年前经历了一个非常微不足道的痛苦,因为它的缓冲区没有像GCC预期那样对齐,而且它导致了SEGFAULT的-O3及以上。例如,请参阅Crash on Cygwin i386 with -O3

对齐问题不仅限于Cygwin; Cygwin碰巧证明了这一点。在启用NEON的情况下,问题在其他平台和CPU之间偶尔浮出水面。我们相信所有问题都已被清除。