2016-04-03 14 views
2

Ich versuche, eine einfache Version der Pseudozufallsfunktion zu implementieren, die in RFC3711 (Secure RTP-Protokoll) definiert ist ist AES im Zählermodus mit einem 128-Bit-Hauptschlüssel.Unerwartete Ausgabe von OpenSSL AES_ctr128_encrypt() als Pseudozufallsfunktion für Schlüsselableitung in RFC3711 (SRTP)

Ich verwende eine 32-Bit-Intel-Core2Duo-CPU (LittleEndian) und OpenSSL v0.9.8AES_ctr128_encrypt().

Wie durch RFC3711 für Schlüsselableitungs instruierte Ich brauche nur einen einzigen Aufruf an AES_ctr128_encrypt() und bot zu tun:

  1. Die Verkettung eines bekannten 112-Bit (14-Byte) Eingangsvektor und einen 16-bit (2-Byte) Zähler auf Null initialisiert
  2. einen bekannten 128-Bit-Master-Schlüssel

... genau 16 Byte von chiffrierten Text zu erhalten (zum Beispiel, den Verschlüsselungsschlüssels).

Ich bin mit dem Probentestvektor für Key-Verschlüsselung Ableitung vorgesehen in Anhang B.3 von RFC3711 - in einer Prise fasst dies an folgenden up:

128-Bit-Master Key: E1F97A0D3E018BE0D64FA32C06DE4139

112-Bit-Eingangsvektor: 0EC675AD498AFEEBB6960B3AABE6

16-Bit-Zähler: 0000

Beim Zuführen der Verkettung von der 112-Bit-Eingabevektor und der 16-Bit-Zähler in AES_ctr128_encrypt() Ich bin NICHT bekomme die erwartete Ausgabe, die Anhang B.3 von RFC3711 ist gelistet.

Der erwartete Chiffretext ausgegeben (nach Anhang B.3 von RFC3711) sollte sein:
C61E7A93744F39EE10734AFE3FF7A087

Die eigentliche Geheimtext Ausgabe ich mit meinem Code zu bekommen ist: C8D80F3E3DC5C705A6E541C49411A087

(FEST, dass nur die letzten 16 Bits sind wie erwartet).

Warum ist das? Was mache ich falsch?

Hier ist der Code, den ich habe:

// 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; 
} 

tatsächliche Ausgang auf meinem Bildschirm:

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 

Antwort

2

Dieses:

memcpy(x, iv, 14); 

nicht da sein soll. Entfernen Sie es.Damit alles andere in Ihrem Code zu verlassen, wie sie ist:

Ausgabe

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

Wow! Tatsächlich! Ich hatte das schon lange gesucht. Vielen Dank! Daher nehme ich an, dass der tatsächliche "Eingabe" -Wert, der von AES_ctr128_encrypt() verwendet wird, sein fünfter Parameter (ivec) ist. Wofür wird der 1. Parameter (in) wirklich verwendet? Und warum muss es 0 sein? (Ich dachte, der Zähler war die niederwertigen Bytes des 5. Parameters (IVEC) ...? – user972301