2017-02-22 129 views
0

我想在使用新密鑰加密AES(如DESX)之前和之後在AES中執行XOR操作。但異或操作需要太多時間。如何在Crypto ++中執行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; 
} 

任何幫助,將不勝感激。

+3

XOR比從內存中讀取或寫入單詞花費的時間少得多。 – stark

+0

'k =(++ k stark

回答

0

How can I do XOR operation in Crypto++?

有兩種方法可以使用該庫來執行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)

異或的第二種方法是使用ArrayXorSinkfilters.h。在內部,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*


How can I reduce the XOR operation time?

你可能想使用一個操作數大小的1字節時,它的可行性。圖書館的xorbuf在可用時使用word32word64。另外,如果你有AVX,那麼你可以在高達512位的緩衝區上操作。如果保持緩衝區對齊,那麼GCC將嘗試使用-O3及以上的較大緩衝區。 -O3非常重要,因爲那時GCC開始進行強力矢量化並使用AVX和AVX2提供的功能。

幾年前,Crypto ++庫忍受了一筆不平常的痛苦,因爲它的緩衝區沒有像GCC預期的那樣對齊,並且導致SEGFAULT的-O3及以上。參見例如Crash on Cygwin i386 with -O3

對齊問題不限於Cygwin; Cygwin碰巧證明了這一點。當NEON被啓用時,這個問題偶爾出現在其他平臺和CPU上,例如ARM。我們相信所有問題都已被清除。

+0

感謝您的回答jww。有沒有一種方法可以在crypto ++中使用xor字符串?加密後給出的結果是字符串。 –

+0

@ T.Rifle - 如上所述使用'xorbuf'。 – jww

+0

jww - 我在C++中很新,所以對於這個問題很抱歉。如何投個字節?它給出錯誤:從'char *'無效轉換爲'byte * {aka unsigned char *}'[-fpermissive] –