Простой текст в C массив тестовых векторов - PullRequest
0 голосов
/ 05 апреля 2020

Я внедряю AES, как описано FIPS_197 , и я буду sh для реализации тестовых случаев, описанных в Приложении C (C1 - C3). Я скопировал контрольные примеры в текстовый файл FIPS_197_tests.txt, который выглядит следующим образом:

# Контрольные примеры из приложения FIPS_192 C
# Открытый текст
# Ключ
# Выходные данные
#
# C .1 AES-128 (Nk = 4, Nr = 10)
00112233445566778899aabbccddeeff
000102030405060708090a0b0c0d0e0f
101c4e0d80a0b2c0. (Nk = 6, № = 12)
00112233445566778899aabbccddeeff
000102030405060708090a0b0c0d0e0f1011121314151617
dda97ca4864cdfe06eaf70a0ec0d7191
# C 0,3 AES-256 (Nk = 8, № = 14)
00112233445566778899aabbccddeeff * * 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f одна тысяча двадцать-одна
8ea2b7ca516745bfeafc49904b496089

Я хотел бы создать файл заголовка FIPS_197_tests.h, который определяет некоторые тестовые векторы, которые можно легко использовать в C. Например, первый тестовый вектор:

// C.1  AES-128 (Nk=4, Nr=10)
unsigned char Key_1[4][4] = {
        {0x00, 0x11, 0x22, 0x33},
        {0x44, 0x55, 0x66, 0x77},
        {0x88, 0x99, 0xaa, 0xbb},
        {0xcc, 0xdd, 0xee, 0xff} };
unsigned char PlainText_1[4][4]  = {
        {0x00, 0x01, 0x02, 0x03},
        {0x04, 0x05, 0x06, 0x07},
        {0x08, 0x09, 0x0a, 0x0b},
        {0x0c, 0x0d, 0x0e, 0x0f} };
unsigned char CipherText_1[4][4]  = {
        {0x69, 0xc4, 0xe0, 0xd8},
        {0x6a, 0x7b, 0x04, 0x30},
        {0xd8, 0xcd, 0xb7, 0x80},
        {0x70, 0xb4, 0xc5, 0x5a} };

Есть только 3 набора тестовых векторов, и я мог бы просто сделать это вручную, но я часто делал шестнадцатеричные тестовые векторы в C и хотел бы чтобы иметь более умное решение, чем шестнадцатеричные массивы, вводимые вручную.

Ключевые вопросы, требующие решения:

  1. Именование : Векторы входят в наборы по три
    • Первый - Key_n массив
    • Второй - PlainText_n массив
    • Третий - CipherText_n массив
  2. Размеры : все значения в векторах представлены в шестнадцатеричном виде, но не всегда заполняют массивы размером [4] [4] Размеры массивов должны быть правильными

Пока у меня есть этот скрипт, который немного упрощает работу, но ничего, что делает всю работу:

cat FIPS_192_tests.txt | sed '/^#/ d; s/../0x&, /g' | xargs -n4 | rev | sed 's/,//' | rev | sed 's|^|{|; s|$|},|'

В итоге

Я надеюсь, что можно легко создать шестнадцатеричные тестовые векторы в C из текстового файла, содержащего длинные текстовые строки. Тестовые векторы входят в наборы по 3 на каждый тестовый пример и должны иметь соответствующие имена (A_1, B_1, C_1, A_2, B_2 ... et c.). Тестовые векторы имеют переменный размер, поэтому некоторые массивы должны быть объявлены как type [4][4], в то время как другие должны быть объявлены type [4][5]

Идеальное решение допускает переменность следующих элементов текстового файла:

  1. Количество последовательных строк, которые определили тестовый пример.
  2. Базовые имена для каждой строки (Key_n, Ciphertext_n, Apple_n, Banana_n).
  3. Тип данных для каждого Базовое имя .
  4. Размер каждого массива.
  5. Формат считываемых данных (шестнадцатеричный, десятичный, двоичный, ...)

Он может называться следующим образом:
./solution -i FIPS_197_tests.txt -n 3 -b "Key, PlainText, CipherText" -d "unsigned char, unsigned char, unsigned char" -f HEX -o FIPS_197_tests.h

Ответы [ 2 ]

2 голосов
/ 05 апреля 2020

Это не такое полное решение, как хорошая программа, предоставляемая @TheRockSays, но оно более ограничено в соответствии с вашими cat, sed, xargs, rev, sed, .. подход, хотя и заменяет все утилиты одним вызовом awk, например

awk '
    BEGIN {
        a[1]="unsigned char Key_1[4][4] = "
        a[2]="unsigned char PlainText_1[4][4]  = "
        a[3]="unsigned char CipherText_1[4][4]  = "
    }
    /^#/ { if(n) exit; next }
    {
        for (i=1; i<length($1); i+=2)
            if ((i % 8) == 1) {
                if (i == 1)
                    printf "\n%s{\n%8s{0x%s", a[++n], " ", substr($1,i,2)
                else
                    printf "},\n%8s{0x%s", " ", substr($1,i,2)
            }
            else
                printf ", 0x%s", substr($1,i,2)
        print "}};"
    }
' FIPS_197_tests.txt

(для тестирования вы можете просто выбрать-копировать и middle-mouse -paste вышеперечисленное в xterm с текущим рабочим каталогом, содержащим FIPS_197_tests.txt)

Конечно, в списке wi sh вы должны будете вручную указать имена массивов, и вы пришлось бы изменить строку формата printf на десятичное, шестнадцатеричное и т. д. c ..., но для быстрого решения оболочки при первоначальном разборе файла FIPS_197_tests.txt - это наверняка лучше, чем вводить все массивы вручную .

Пример вывода

unsigned char Key_1[4][4] = {
        {0x00, 0x11, 0x22, 0x33},
        {0x44, 0x55, 0x66, 0x77},
        {0x88, 0x99, 0xaa, 0xbb},
        {0xcc, 0xdd, 0xee, 0xff}};

unsigned char PlainText_1[4][4]  = {
        {0x00, 0x01, 0x02, 0x03},
        {0x04, 0x05, 0x06, 0x07},
        {0x08, 0x09, 0x0a, 0x0b},
        {0x0c, 0x0d, 0x0e, 0x0f}};

unsigned char CipherText_1[4][4]  = {
        {0x69, 0xc4, 0xe0, 0xd8},
        {0x6a, 0x7b, 0x04, 0x30},
        {0xd8, 0xcd, 0xb7, 0x80},
        {0x70, 0xb4, 0xc5, 0x5a}};
2 голосов
/ 05 апреля 2020

Обновление:

Теперь все работает. Следующий код имеет следующие допущения:

  • У вас есть 3 строки для каждого теста, каждая для Key_1, PlainText_1 и CipherText_1 соответственно.

  • Каждый из Key_1, PlainText_1 и CipherText_1 имеет ровно 32 бита и хранится в [4] [4] матрицах.

Посмотрите на этот код. Попробуйте положить файл и посмотреть вывод. В каждом тестовом примере вы должны видеть обновленные значения Key_1, PlainText_1 и CipherText_1.

using namespace std;

void readFile(std::string fileName) {
    unsigned char Key_1[4][4];
    unsigned char PlainText_1[4][4];
    unsigned char CipherText_1[4][4];
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            Key_1[i][j] = 0x00 ; PlainText_1[i][j] = 0x00 ; CipherText_1[i][j] = 0x00;
        }
    }

    std::ifstream reader;
    reader.open(fileName);

    bool commentBlock = true;
    int line_flag = 0;
    int str2int = 0;
    int line_idx = 0;

    if (reader.is_open()) {
        std::string line;
        while (getline(reader, line)) {
            if (line.substr(0, 1) != "#")
                commentBlock = false;
            else{
                printf("\n");
                printf("Key_1 Contents:\n");
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        printf("%x\t",Key_1[i][j]);
                    }
                    printf("\n");
                }
                printf("\n");

                printf("PlainText_1 Contents:\n");
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        printf("%x\t",PlainText_1[i][j]);
                    }
                    printf("\n");
                }
                printf("\n");

                printf("CipherText_1 Contents:\n");
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        printf("%x\t",CipherText_1[i][j]);
                    }
                    printf("\n");
                }
                printf("\n");

                commentBlock = true;
                while (commentBlock) {
                    getline(reader, line);
                    if (line.substr(0, 1) != "#")
                        commentBlock = false;
                }
            }
            std::cout << "Read line:" << std::endl;
            printf("%s\n", line.c_str());
            line_idx = 0;
            if (line_flag > 2){
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        Key_1[i][j] = 0x00 ; PlainText_1[i][j] = 0x00 ; CipherText_1[i][j] = 0x00;
                    }
                }
                line_flag = 0;
            }

            switch (line_flag){
            case 0:
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        switch(line.at(line_idx)){
                        case 'a':
                            str2int = 10;
                            Key_1[i][j] += str2int * 16;
                            break;
                        case 'b':
                            str2int = 11;
                            Key_1[i][j] += str2int * 16;
                            break;
                        case 'c':
                            str2int = 12;
                            Key_1[i][j] += str2int * 16;
                            break;
                        case 'd':
                            str2int = 13;
                            Key_1[i][j] += str2int * 16;
                            break;
                        case 'e':
                            str2int = 14;
                            Key_1[i][j] += str2int * 16;
                            break;
                        case 'f':
                            str2int = 15;
                            Key_1[i][j] += str2int * 16;
                            break;
                        default:
                            str2int = stoi(line.substr(line_idx, 1));
                            Key_1[i][j] += str2int * 16;
                            break;
                        }
                        line_idx ++;
                        switch(line.at(line_idx)){
                        case 'a':
                            str2int = 10;
                            Key_1[i][j] += str2int;
                            break;
                        case 'b':
                            str2int = 11;
                            Key_1[i][j] += str2int;
                            break;
                        case 'c':
                            str2int = 12;
                            Key_1[i][j] += str2int;
                            break;
                        case 'd':
                            str2int = 13;
                            Key_1[i][j] += str2int;
                            break;
                        case 'e':
                            str2int = 14;
                            Key_1[i][j] += str2int;
                            break;
                        case 'f':
                            str2int = 15;
                            Key_1[i][j] += str2int;
                            break;
                        default:
                            str2int = stoi(line.substr(line_idx, 1));
                            Key_1[i][j] += str2int;
                            break;
                        }
                        line_idx ++;
                    }
                }
                line_flag++;
                break;
            case 1:
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        switch(line.at(line_idx)){
                        case 'a':
                            str2int = 10;
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        case 'b':
                            str2int = 11;
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        case 'c':
                            str2int = 12;
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        case 'd':
                            str2int = 13;
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        case 'e':
                            str2int = 14;
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        case 'f':
                            str2int = 15;
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        default:
                            str2int = stoi(line.substr(line_idx, 1));
                            PlainText_1[i][j] += str2int * 16;
                            break;
                        }
                        line_idx ++;
                        switch(line.at(line_idx)){
                        case 'a':
                            str2int = 10;
                            PlainText_1[i][j] += str2int;
                            break;
                        case 'b':
                            str2int = 11;
                            PlainText_1[i][j] += str2int;
                            break;
                        case 'c':
                            str2int = 12;
                            PlainText_1[i][j] += str2int;
                            break;
                        case 'd':
                            str2int = 13;
                            PlainText_1[i][j] += str2int;
                            break;
                        case 'e':
                            str2int = 14;
                            PlainText_1[i][j] += str2int;
                            break;
                        case 'f':
                            str2int = 15;
                            PlainText_1[i][j] += str2int;
                            break;
                        default:
                            str2int = stoi(line.substr(line_idx, 1));
                            PlainText_1[i][j] += str2int;
                            break;
                        }
                        line_idx ++;
                    }
                }
                line_flag++;
                break;
            case 2:
                for (int i = 0; i < 4; ++i) {
                    for (int j = 0; j < 4; ++j) {
                        switch(line.at(line_idx)){
                        case 'a':
                            str2int = 10;
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        case 'b':
                            str2int = 11;
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        case 'c':
                            str2int = 12;
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        case 'd':
                            str2int = 13;
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        case 'e':
                            str2int = 14;
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        case 'f':
                            str2int = 15;
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        default:
                            str2int = stoi(line.substr(line_idx, 1));
                            CipherText_1[i][j] += str2int * 16;
                            break;
                        }
                        line_idx ++;
                        switch(line.at(line_idx)){
                        case 'a':
                            str2int = 10;
                            CipherText_1[i][j] += str2int;
                            break;
                        case 'b':
                            str2int = 11;
                            CipherText_1[i][j] += str2int;
                            break;
                        case 'c':
                            str2int = 12;
                            CipherText_1[i][j] += str2int;
                            break;
                        case 'd':
                            str2int = 13;
                            CipherText_1[i][j] += str2int;
                            break;
                        case 'e':
                            str2int = 14;
                            CipherText_1[i][j] += str2int;
                            break;
                        case 'f':
                            str2int = 15;
                            CipherText_1[i][j] += str2int;
                            break;
                        default:
                            str2int = stoi(line.substr(line_idx, 1));
                            CipherText_1[i][j] += str2int;
                            break;
                        }
                        line_idx ++;
                    }
                }
                line_flag++;
                break;
            }
        }

        printf("\n");
        printf("Key_1 Contents:\n");
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                printf("%x\t",Key_1[i][j]);
            }
            printf("\n");
        }
        printf("\n");

        printf("PlainText_1 Contents:\n");
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                printf("%x\t",PlainText_1[i][j]);
            }
            printf("\n");
        }
        printf("\n");

        printf("CipherText_1 Contents:\n");
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                printf("%x\t",CipherText_1[i][j]);
            }
            printf("\n");
        }
        printf("\n");

    }
    else {
        cerr << "Can't open file " + fileName;
    }
}
...