2013-05-27 22 views
0

我一直在嘗試編寫加密和解密函數,其簽名要求輸入和輸出字符串僅爲void*類型。如果輸入可以指定爲IBuffer^,但在另一種情況下源字符串和加密 - >解密字符串不匹配,則代碼工作正常。如何加密和解密WinRT中的const char *

CodeIBuffer^ byteArrayToIBufferPtr(byte *source, int size) 
{ 
    Platform::ArrayReference<uint8> blobArray(source, size); 
    IBuffer ^buffer = CryptographicBuffer::CreateFromByteArray(blobArray); 
    return buffer; 
} 

byte* IBufferPtrToByteArray(IBuffer ^buffer) 
{ 
    Array<unsigned char,1U> ^platArray = ref new Array<unsigned char,1U>(256); 
    CryptographicBuffer::CopyToByteArray(buffer,&platArray); 

    byte *dest = platArray->Data; 
    return dest; 
} 

int DataEncryption::encryptData(EncryptionAlgorithm algo, int keySize, void* srcData, const unsigned int srcSize, 
     void*& encData, unsigned int& encSize) 
{ 

    LOG_D(TAG, "encryptData()"); 

    if(srcData == nullptr) 
    { 
     LOG_E(TAG,""); 
     return DataEncryption::RESULT_EMPTY_DATA_ERROR; 
    } 
    if(srcSize == 0) 
    { 
     LOG_E(TAG,""); 
     return DataEncryption::RESULT_SIZE_ZERO_ERROR; 
    } 

    IBuffer^ encrypted; 
    IBuffer^ buffer; 
    IBuffer^ iv = nullptr; 
    String^ algName; 
    bool cbc = false; 

    switch (algo) 
    { 
    case DataEncryption::ENC_DEFAULT: 
     algName = "AES_CBC"; 
     cbc = true; 
     break; 
    default: 
     break; 
    } 

    // Open the algorithm provider for the algorithm specified on input. 
    SymmetricKeyAlgorithmProvider^ Algorithm = SymmetricKeyAlgorithmProvider::OpenAlgorithm(algName); 

    // Generate a symmetric key. 
    IBuffer^ keymaterial = CryptographicBuffer::GenerateRandom((keySize + 7)/8); 
    CryptographicKey^ key; 

    try 
    { 
     key = Algorithm->CreateSymmetricKey(keymaterial); 
    } 
    catch(InvalidArgumentException^ e) 
    { 
     LOG_E(TAG,"encryptData(): Could not create key."); 
     return DataEncryption::RESULT_ERROR; 
    } 

    // CBC mode needs Initialization vector, here just random data. 
    // IV property will be set on "Encrypted". 
    if (cbc) 
     iv = CryptographicBuffer::GenerateRandom(Algorithm->BlockLength); 

    // Set the data to encrypt. 
    IBuffer ^srcDataBuffer = byteArrayToIBufferPtr(static_cast<byte*>(srcData),256); 

    // Encrypt and create an authenticated tag. 
    encrypted = CryptographicEngine::Encrypt(key, srcDataBuffer, iv); 

    //encData = encrypted; 
    byte *bb = IBufferPtrToByteArray(encrypted); 
    encData = IBufferPtrToByteArray(encrypted); 
    encSize = encrypted->Length; 

    return DataEncryption::RESULT_SUCCESS; 
} 


int DataEncryption::decryptData(EncryptionAlgorithm algo, int keySize, void* encData, const unsigned int encSize, 
     void*& decData, unsigned int& decSize) 
{ 
    LOG_D(TAG, "decryptData()"); 

    if(encData == nullptr) 
    { 
     LOG_E(TAG,""); 
     return DataEncryption::RESULT_EMPTY_DATA_ERROR; 
    } 
    if(encSize == 0) 
    { 
     LOG_E(TAG,""); 
     return DataEncryption::RESULT_SIZE_ZERO_ERROR; 
    } 

    IBuffer^ encrypted; 
    IBuffer^ decrypted; 
    IBuffer^ iv = nullptr; 
    String^ algName; 
    bool cbc = false; 

    switch (algo) 
    { 
    case DataEncryption::ENC_DEFAULT: 
     algName = "AES_CBC"; 
     cbc = true; 
     break; 
    default: 
     break; 
    } 

    // Open the algorithm provider for the algorithm specified on input. 
    SymmetricKeyAlgorithmProvider^ Algorithm = SymmetricKeyAlgorithmProvider::OpenAlgorithm(algName); 

    // Generate a symmetric key. 
    IBuffer^ keymaterial = CryptographicBuffer::GenerateRandom((keySize + 7)/8); 
    CryptographicKey^ key; 

    try 
    { 
     key = Algorithm->CreateSymmetricKey(keymaterial); 
    } 
    catch(InvalidArgumentException^ e) 
    { 
     LOG_E(TAG,"encryptData(): Could not create key."); 
     return DataEncryption::RESULT_ERROR; 
    } 

    // CBC mode needs Initialization vector, here just random data. 
    // IV property will be set on "Encrypted". 
    if (cbc) 
     iv = CryptographicBuffer::GenerateRandom(Algorithm->BlockLength); 

    // Set the data to decrypt. 
    byte *cc = static_cast<byte*>(encData); 
    IBuffer ^encDataBuffer = byteArrayToIBufferPtr(cc,256); 
    // Decrypt and verify the authenticated tag. 
    decrypted = CryptographicEngine::Decrypt(key, encDataBuffer, iv); 

    byte *bb = IBufferPtrToByteArray(decrypted); 
    decData = IBufferPtrToByteArray(decrypted); 

    decSize = decrypted->Length; 

    return DataEncryption::RESULT_SUCCESS; 
} 
+0

加密。相當複雜的領域。你使用什麼加密方法?你正在創建自己的加密算法?你的問題是你目前遇到與加密相關的問題嗎?它只是一個C++語法/語義濫用問題,可以在不提及單詞「加密」的情況下解決? –

+0

嗨馬克!我正在編寫一個包裝來加密和解密加密庫中已有的算法。以前我使用openssl第三方庫;現在我需要使用WinRT本地API。邏輯是: encryptData()函數: -------------------------- 1.在'const char *'中隱藏源字符串格式爲'IBuffer ^'格式 2.使用WinRT API加密緩衝區 3。將編碼的緩衝區轉換回'char *'並將其安裝到目標字符串(參數) – chandrashekhar

+0

decryptData()函數: ----------------------- --- 1.'const char *'格式的隱藏源字符串爲'IBuffer ^'格式 2.使用WinRT API解密緩衝區 3.將解碼後的緩衝區轉換回'char *'並將其安裝到目標字符串(參數) 我面臨的問題是,如果我將參數作爲IBuffer,代碼工作正常;但是當源和目標參數是'void *'時;轉換的事情正在做一些奇怪的事情。源字符串和加密後解密後得到的字符串應該匹配;不幸的是,這並沒有發生。 – chandrashekhar

回答

1

我猜測,這個問題是使用此項功能:

byte* IBufferPtrToByteArray(IBuffer ^buffer) 
{ 
    Array<unsigned char,1U> ^platArray = ref new Array<unsigned char,1U>(256); 
    CryptographicBuffer::CopyToByteArray(buffer,&platArray); 

    byte *dest = platArray->Data; 
    return dest; 
} 

你在做什麼有分配一個新的Platform::Array<byte>^與1個參考,然後讓一個指向其內部管理存儲,然後返回該指針 - 此時Array將被取消引用,並因此釋放其基礎存儲。因此你返回的指針指的是釋放的內存。下一個分配可能會覆蓋這些字節。

什麼你需要做的是採取從CopyToByteArray()返回按引用Array<byte>^(這將創建一個新的磁盤陣列,想必包裝輸入IBuffer^的字節,並將其返回)和拷貝數組的內容

你的最終結果將類似地起作用以從Readium SDK項目,這需要一個std::string例如,使用SHA-1散列它,並複製散列數據到一個成員變量uint8_t _key[KeySize]此片段:

using namespace ::Platform; 
using namespace ::Windows::Foundation::Cryptography; 
using namespace ::Windows::Foundation::Cryptography::Core; 

auto byteArray = ArrayReference<byte>(reinterpret_cast<byte*>(const_cast<char*>(str.data())), str.length()); 
auto inBuf = CryptographicBuffer::CreateFromByteArray(byteArray); 
auto keyBuf = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha1)->HashData(inBuf); 

Array<byte>^ outArray = nullptr; 
CryptographicBuffer::CopyToByteArray(keyBuf, &outArray); 
memcpy_s(_key, KeySize, outArray->Data, outArray->Length); 

步驟:

  1. 創建一個ArrayReference<byte>對應於std::string(不復制)中的字節。
  2. 將其傳遞給CryptographicBuffer::CreateFromByteArray()以獲得您的IBuffer^。仍然沒有複製數據。
  3. 調用你的散列函數/加密函數,通過你剛剛製作的IBuffer^。你會得到另一個IBuffer^作爲回報,這可能會或可能不會使用完全相同的存儲(我認爲這實際上取決於算法的實現)。
  4. 創建類型爲Array<byte>^的變量。不要分配一個對象,你會被引用一個對象。
  5. 將該對象的地址傳遞到CryptographicBuffer::CopyToByteArray()以接收關鍵數據的副本。
  6. 儘管Array^仍然有效,請將其字節複製到本地陣列中。