我正在尝试实现 RFC3711(安全RTP协议(protocol))中定义的伪随机函数的简单版本,它是计数器模式下的 AES,具有128位主密钥

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

按照RFC3711关于密钥派生的指示,我只需要对AES_ctr128_encrypt()进行一次调用并提供:

  • 已知的112位(14字节)输入 vector 和一个初始化为零的16位(2字节)计数器的串联
  • 已知的128位主密钥

  • ...以产生恰好16个字节的密文(例如加密密钥)。

    我正在使用RFC3711 附录B.3的中提供的用于加密密钥派生的示例测试 vector -关键是以下几点:

    128位主密钥:E1F97A0D3E018BE0D64FA32C06DE4139
    112位输入 vector :0EC675AD498AFEEBB6960B3AABE6
    16位计数器:0000
    当将112位输入 vector 和16位计数器的连接输入AES_ctr128_encrypt()时,我是 NOT ,得到了预期输出,即RFC3711的附录B.3的正在列出

    预期的密文输出(根据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
    

    最佳答案

    这个:

    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
    

    10-08 08:06