中作爲僞隨機函數的意外輸出我試圖實現在RFC3711(安全RTP協議)中定義的僞隨機函數的簡單版本,它使用128位主密鑰的計數器模式下的AES爲。OpenSSL AES_ctr128_encrypt()作爲僞隨機函數在RFC3711(SRTP)
我使用的是32位Intel Core2Duo CPU(LittleEndian)和OpenSSL v0.9.8的AES_ctr128_encrypt()
。
作爲指示由RFC3711用於密鑰推導我只需要做一個調用AES_ctr128_encrypt()
和提供:
- 已知112位(14字節)的輸入向量的級聯和一個16位的(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
哇!確實!我一直在尋找這個理解這麼久。謝謝!因此,我認爲AES_ctr128_encrypt()使用的實際「輸入」值是其第5個參數(ivec)。那麼真正使用的第一個參數是什麼?爲什麼它必須是0? (我認爲計數器是第五個參數(ivec)的低位字節...? – user972301