2013-07-28 56 views
1

我需要在C++中編碼一些數據,並在php中解碼它,但PHP解碼不正確。 我用相同的密鑰和iv檢查了編碼這個相同的消息,結果有差異。 這是我的代碼:在c + +和PHP的openssl加密

struct ctr_state 
{ 
    unsigned char ivec[AES_BLOCK_SIZE]; 
    unsigned int num; 
    unsigned char ecount[AES_BLOCK_SIZE]; 
}; 
unsigned char indata[AES_BLOCK_SIZE]; 
unsigned char outdata[AES_BLOCK_SIZE]; 
unsigned char iv[AES_BLOCK_SIZE]; 

struct ctr_state state; 

int init_ctr(struct ctr_state *state, const byte iv[16]) 
{ 
    /* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the 
    * first call. */ 
    state->num = 0; 
    memset(state->ecount, 0, AES_BLOCK_SIZE); 

    /* Initialise counter in 'ivec' to 0 */ 
    memset(state->ivec + 8, 0, 8); 

    /* Copy IV into 'ivec' */ 
    memcpy(state->ivec, iv, 8); 
} 

void aes_encoder(byte *read, byte *write, int size, byte *enc_key, byte *iv) 
{ 
    AES_KEY key; 
    if (AES_set_encrypt_key(enc_key, 128, &key) < 0) 
    { 
     Logger::getInstance()->Error("problem with setting encrypt key"); 
    } 
    init_ctr(&state, iv); 

    AES_ctr128_encrypt(read, write, size, &key, state.ivec, state.ecount, &state.num); 
} 

byte *key = (byte*)"2123456789"; 
byte *iv = (byte*)"2asdasdasdasdasd"; 

QByteArray message = "this is message"; 
byte *data = reinterpret_cast<byte *>(message.data()); 

aes_encoder(data, data, message.size(), key, iv); 
qDebug() << message.toBase64(); 

的結果是: 「HF/nlW4e + FmuF8Bfny9M」

和PHP代碼:

<?php 
$message = "this is message"; 
$key = "2123456789"; 
$iv = "2asdasdasdasdasd"; 

$encrypted = openssl_encrypt($message, 'aes-128-ctr', $key, true, $iv); 

echo base64_encode($encrypted); 

結果: 「RLLUkP54El9FCeWpO/BI」

爲什麼結果不一樣?

+0

在memset(state-> ivec + 8,0,8)行中使用了硬編碼的'8';'? – Floris

+0

我將此代碼從此處取下:http://stackoverflow.com/a/3146214/1349417 – januszmk

+0

重複使用CTR模式的隨機數*完全*打破加密。每個帶有重用隨機數的消息都可以在不知道密鑰的情況下恢復。將隨機代碼複製粘貼到互聯網上並不是編寫與安全相關的代碼的方式 - 您需要精確地瞭解每一個細節。或者,您可以使用久經考驗的庫。 – ntoskrnl

回答

2

你的問題是你沒有使用CTR模式的標準方式。在init_ctr中,您只複製了提供的IV的8個字節,並將剩餘的字節設置爲零。相反,如果你使用整個IV,您將得到相同的結果PHP代碼:

//don't do this: 
//memset(state->ivec + 8, 0, 8); 
//memcpy(state->ivec, iv, 8); 

//do this: 
memcpy(state->ivec, iv, AES_BLOCK_SIZE); 

的教訓是,僅僅因爲你發現了一些代碼的地方,並不意味着你可以複製正貼吧不理解它在做什麼。加密代碼尤其如此。如果您甚至知道分組密碼的基本知識以及如何在CTR模式下工作,您將直接意識到您的代碼存在問題。

哦,重要的安全提示:使用CTR模式時,絕對不要用同一個IV加密多個消息。否則你會死。

+0

謝謝。 你是否推薦openssl中另一種更安全的模式? – januszmk

+1

CTR模式沒有任何問題。只要你不重複使用IV,這很棒。 – zindorsky

+1

我應該補充說,沒有加密的「最佳」模式。這取決於你的具體需求。每個人都有其優點和缺點。每個人都可能被不知道自己在做什麼的人錯誤地使用。 – zindorsky