Speck 128/256 реализация неправильный тестовый вектор - PullRequest
3 голосов
/ 27 марта 2020

Привет, я пытаюсь реализовать Speck128 / 256 в C. Я следую руководству по внедрению , но получаю неправильный результат с векторами теста.

Это код (тот же, что и в документе)

#define ROTL64(x, r) (((x) << (r)) | (x >> (64 - (r))))
#define ROTR64(x, r) (((x) >> (r)) | ((x) << (64 - (r))))

#define ER64(x, y, s) (x = (ROTR64(x, 8) + y) ^ (s), y = ROTL64(y, 3) ^ x)
#define DR64(x, y, k) (y ^= x, y = ROTR64(y, 3), x ^= k, x -= y, x = ROTL64(x, 8))

static void hex_print(uint8_t *pv, uint16_t s, uint16_t len)
{
    uint8_t *p = pv;
    if (NULL == pv)
        printf("NULL");
    else
    {
        unsigned int i;
        for (i = s; i < len; ++i)
            printf("%02x ", p[i]);
    }
    printf("\n\n");
}

void Words64ToBytes(u64 words[], u8 bytes[], int numwords)
{
    int i, j = 0;
    for (i = 0; i < numwords; i++)
    {
        bytes[j] = (u8)words[i];
        bytes[j + 1] = (u8)(words[i] >> 8);
        bytes[j + 2] = (u8)(words[i] >> 16);
        bytes[j + 3] = (u8)(words[i] >> 24);
        bytes[j + 4] = (u8)(words[i] >> 32);
        bytes[j + 5] = (u8)(words[i] >> 40);
        bytes[j + 6] = (u8)(words[i] >> 48);
        bytes[j + 7] = (u8)(words[i] >> 56);
        j += 8;
    }
}

void BytesToWords64(u8 bytes[], u64 words[], int numbytes)
{
    int i, j = 0;
    for (i = 0; i < numbytes / 8; i++)
    {
        words[i] = (u64)bytes[j] | ((u64)bytes[j + 1] << 8) | ((u64)bytes[j + 2] << 16) |
                   ((u64)bytes[j + 3] << 24) | ((u64)bytes[j + 4] << 32) | ((u64)bytes[j + 5] << 40) |
                   ((u64)bytes[j + 6] << 48) | ((u64)bytes[j + 7] << 56);
        j += 8;
    }
}

void Speck128256Encrypt(u64 Pt[], u64 Ct[], u64 rk[])
{
    u64 i;
    Ct[0] = Pt[0];
    Ct[1] = Pt[1];
    for (i = 0; i < 34;)
    {
        ER64(Ct[1], Ct[0], rk[i++]);
    }
}

void Speck128256KeySchedule(u64 K[], u64 rk[])
{
    u64 i, D = K[3], C = K[2], B = K[1], A = K[0];
    for (i = 0; i < 33;)
    {
        rk[i] = A;
        ER64(B, A, i++);
        rk[i] = A;
        ER64(C, A, i++);
        rk[i] = A;
        ER64(D, A, i++);
    }
    rk[i] = A;
}

int main(){

 u8 pt[16] = {
        0x70, 0x6f, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65};
    u8 k[32] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};

    u8 ct[16];
    u64 K[4];
    u64 Pt[2];
    u64 Ct[2];
    u64 rk[34];

    BytesToWords64((u8 *)pt, (u64 *)Pt, 16);
    for (int i = 0; i < 2; i++)
        printf("Pt[%d]: %2lx\n", i, Pt[i]);
    printf("\n");

    BytesToWords64((u8 *)k, K, 32);
    for (int i = 0; i < 4; i++)
        printf("k[%d]: %2lx\n", i, K[i]);
    printf("\n");

    Speck128256KeySchedule(K, rk);
    for (int i = 0; i < 34; i++)
        printf("rk[%d]: %2lx\n", i, rk[i]);
    printf("\n");

    Speck128256Encrypt(Pt, Ct, rk);
    for (int i = 0; i < 2; i++)
        printf("Ct[%d]: %2lx\n", i, Ct[i]);
    printf("\n");

    Words64ToBytes(Ct, ct, 2);
    hex_print((u8 *)ct, 0, 16);
}

Мои выводы:

  • Pt [1]. *
  • rk [0]: 0001020304050607 ...

ожидайте:

  • (Pt [1], Pt [0]) = (65736f6874206e49,202e72656e6f6f70)
  • K = (K [3], K [2], K [1], K [0]) = (1f1e1d1c1b1a1918,1716151413121110,0f0e0d0c0b0a0908,0706050403020100)
  • рк [0] = 0706050403020100 ...

что я не прав? Я думаю, что ошибка связана с ошибкой типа, но я не уверен.

EDIT

После нескольких тестов, я думаю, что нашел проблему. Тестовый вектор находится в Big endian (смотрите вывод и результат).

EDIT

после перезаписи кода тестовый вектор работает.

...