2016-04-03 61 views
2

中作爲僞隨機函數的意外輸出我試圖實現在RFC3711(安全RTP協議)中定義的僞隨機函數的簡單版本,它使用128位主密鑰的計數器模式下的AES爲OpenSSL AES_ctr128_encrypt()作爲僞隨機函數在RFC3711(SRTP)

我使用的是32位Intel Core2Duo CPU(LittleEndian)和OpenSSL v0.9.8AES_ctr128_encrypt()

作爲指示由RFC3711用於密鑰推導我只需要做一個調用AES_ctr128_encrypt()和提供:

  1. 已知112位(14字節)的輸入向量的級聯和一個16位的(2字節)計數器初始化爲零
  2. 一種已知的128位的主密鑰

...,得到正好16個字節的密文(例如加密密鑰)。

我使用RFC3711附錄B.3提供加密密鑰推導樣本測試向量 - 在緊要關頭,這個總結了以下幾點:

128位的主密鑰:E1F97A0D3E018BE0D64FA32C06DE4139

112位輸入矢量:0EC675AD498AFEEBB6960B3AABE6

16位計數器:0000

餵奶時的級聯將112位輸入向量和16位計數器轉換爲AES_ctr128_encrypt()我是不是得到預期的輸出附錄B.3的RFC3711列出了

(根據RFC3711的附錄B.3)

預期的密文的輸出應該是:
C61E7A93744F39EE10734AFE3FF7A087

實際的密文輸出我跟我的代碼得到的是: C8D80F3E3DC5C705A6E541C49411A087

(請注意,只有最後的16位與預期的一樣)。

這是爲什麼?我究竟做錯了什麼?

這裏是我的代碼:

// COMPILE WITH: 
// g++ -o aesctr128 -lcrypto aesctr128_test.cpp 

#include <openssl/aes.h> 
#include <stdio.h> 
#include <string.h> 

struct counter_state 
{ 
    unsigned char ivec[16]; // ivec[0..13] (high-order bytes) is 'IV'/ivec[14..15] (low-order bytes) is 'counter' 
    unsigned int num;   // Block byte offset 
    unsigned char ecount[16]; 
}; 

int reset_state(struct counter_state *state, const unsigned char iv[14]) 
{ 
    // aes_ctr128_encrypt() requires 'num' and 'ecount' to be set to zero on its first call 
    state->num = 0; 
    memset(state->ecount, 0, 16);  

    // Clear BOTH 14 high-order bytes [0..13] for 'IV' *AND* 2 low-order bytes [14..15] for 'counter' 
    memset(state->ivec, 0, 16); 
    // Copy 'IV' into 14 high-order bytes [0..13] -- 2 low-order bytes [14..15] remain zero 
    memcpy(state->ivec, iv, 14); 

    return 0; 
} 

int pseudorandom_function2() 
{ 
    int rc = 0; 
    AES_KEY aes_key; 
    struct counter_state state; 
    unsigned char key[16];   // Master key (16-byte -- 128 bits) 
    unsigned char iv[14];   // Input vector (14-byte -- 112 bits) 
    unsigned char x[16];   // 16-byte concatenation of 14-byte Input Vector and 2-byte counter (00) 
    unsigned char out[16];   // 16-byte encrypted ciphertext 

    memset(key, 0, sizeof(key)); 
    key[0] = 0xE1; 
    key[1] = 0xF9; 
    key[2] = 0x7A; 
    key[3] = 0x0D; 
    key[4] = 0x3E; 
    key[5] = 0x01; 
    key[6] = 0x8B; 
    key[7] = 0xE0; 
    key[8] = 0xD6; 
    key[9] = 0x4F; 
    key[10] = 0xA3; 
    key[11] = 0x2C; 
    key[12] = 0x06; 
    key[13] = 0xDE; 
    key[14] = 0x41; 
    key[15] = 0x39; 

    memset(iv, 0, sizeof(iv)); 
    iv[0] = 0x0E; 
    iv[1] = 0xC6; 
    iv[2] = 0x75; 
    iv[3] = 0xAD; 
    iv[4] = 0x49; 
    iv[5] = 0x8A; 
    iv[6] = 0xFE; 
    iv[7] = 0xEB; 
    iv[8] = 0xB6; 
    iv[9] = 0x96; 
    iv[10] = 0x0B; 
    iv[11] = 0x3A; 
    iv[12] = 0xAB; 
    iv[13] = 0xE6; 

    memset(x, 0, sizeof(x)); 
    memcpy(x, iv, 14); 

    // Initialize encryption KEY 
    rc = AES_set_encrypt_key(key, 128, &aes_key); 
    if (rc < 0) 
    { 
     return -1; 
    } 

    reset_state(&state, iv); 

    memset(out, 0, sizeof(out)); 

    printf("ivec BEFORE: "); 
    for (int i = 0; i < 16; i++) { 
     printf("%02x", state.ivec[i]); 
    } 
    printf("\n"); 

    // Encrypt given x input using key to out 
    AES_ctr128_encrypt(x, out, AES_BLOCK_SIZE, &aes_key, state.ivec, state.ecount, &state.num); 

    for (int k = 0; k < 16; k++) 
    { 
     printf("pseudorandom_function2: out[%d] = %02x\n", k, out[k]); 
    } 

    printf("ivec AFTER: "); 
    for (int i = 0; i < 16; i++) { 
     printf("%02x", state.ivec[i]); 
    } 
    printf("\n"); 

    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    pseudorandom_function2(); 
    return 0; 
} 

實際輸出我的屏幕上:

ivec BEFORE: 0ec675ad498afeebb6960b3aabe60000 
pseudorandom_function2: out[0] = c8 
pseudorandom_function2: out[1] = d8 
pseudorandom_function2: out[2] = 0f 
pseudorandom_function2: out[3] = 3e 
pseudorandom_function2: out[4] = 3d 
pseudorandom_function2: out[5] = c5 
pseudorandom_function2: out[6] = c7 
pseudorandom_function2: out[7] = 05 
pseudorandom_function2: out[8] = a6 
pseudorandom_function2: out[9] = e5 
pseudorandom_function2: out[10] = 41 
pseudorandom_function2: out[11] = c4 
pseudorandom_function2: out[12] = 94 
pseudorandom_function2: out[13] = 11 
pseudorandom_function2: out[14] = a0 
pseudorandom_function2: out[15] = 87 
ivec AFTER: 0ec675ad498afeebb6960b3aabe60001 

回答

2

此:

memcpy(x, iv, 14); 

不應該在那裏。去掉它。這樣做,把一切都在你的代碼爲別的,就是:

輸出

ivec BEFORE: 0ec675ad498afeebb6960b3aabe60000 
pseudorandom_function2: out[0] = c6 
pseudorandom_function2: out[1] = 1e 
pseudorandom_function2: out[2] = 7a 
pseudorandom_function2: out[3] = 93 
pseudorandom_function2: out[4] = 74 
pseudorandom_function2: out[5] = 4f 
pseudorandom_function2: out[6] = 39 
pseudorandom_function2: out[7] = ee 
pseudorandom_function2: out[8] = 10 
pseudorandom_function2: out[9] = 73 
pseudorandom_function2: out[10] = 4a 
pseudorandom_function2: out[11] = fe 
pseudorandom_function2: out[12] = 3f 
pseudorandom_function2: out[13] = f7 
pseudorandom_function2: out[14] = a0 
pseudorandom_function2: out[15] = 87 
ivec AFTER: 0ec675ad498afeebb6960b3aabe60001 
+0

哇!確實!我一直在尋找這個理解這麼久。謝謝!因此,我認爲AES_ctr128_encrypt()使用的實際「輸入」值是其第5個參數(ivec)。那麼真正使用的第一個參數是什麼?爲什麼它必須是0? (我認爲計數器是第五個參數(ivec)的低位字節...? – user972301