Преобразование массива uint8_t (шестнадцатеричного) в строку на C

#c #encryption #type-conversion #uint8t

#c #шифрование #преобразование типа #uint8t

Вопрос:

Требования

Я разработчик, но еще неделю назад у меня был почти нулевой опыт работы с C. Для проекта мне нужно зашифровать / расшифровать исходный код / текстовые файлы, и для этого мне нужно использовать C.

Что я делал до сих пор?

Я использую для этого библиотеку Kokke / tony-AES-c и реализую ее с дополнением pkcs7, как описано в this Gist.

В моем коде (приведенном ниже) у меня есть функция my_encrypt , которая шифрует содержимое и возвращает uint8_t массив (который содержит шестнадцатеричный код). Мне нужно сохранить его и прочитать позже из файла для расшифровки. Я знаю, как сохранить строку в файл, но как я могу сохранить uint8_t ее в файле?

Для этого мне нужно преобразовать uint8_t в строку, но после попытки нескольких решений я не могу этого сделать.

Вопрос

Как я могу преобразовать uint8_t массив (который содержит шестнадцатеричное число) в строку на C.

Мой код

 #include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>

#define CBC 1
#define DECRYPT 0;
#define ENCRYPT 1;

#include "aes.h"
#include "pkcs7_padding.h"

const uint8_t * my_encrypt(char *report) {
    //Initialization Vector
    uint8_t iv[]  = { 0x75, 0x52, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x21, 0x21 };

    uint8_t i;
//    char* report = "my super secret thing that needs to remain that way!";
    char* key = "thisIstheKey";
    int dlen = strlen(report);
    int klen = strlen(key);

    printf("THE PLAIN TEXT STRING = ");
    for (i=0; i<dlen;i  ){
        printf("%c", report[i]);
    }
    printf("n");

    //Proper Length of report
    int dlenu = dlen;
    if (dlen % 16) {
        dlenu  = 16 - (dlen % 16);
        printf("The original length of the STRING = %d and the length of the padded STRING = %dn", dlen, dlenu);
    }

    //Proper length of key
    int klenu = klen;
    if (klen % 16) {
        klenu  = 16 - (klen % 16);
        printf("The original length of the KEY = %d and the length of the padded KEY = %dn", klen, klenu);
    }

    // Make the uint8_t arrays
    uint8_t hexarray[dlenu];
    uint8_t kexarray[klenu];

    // Initialize them with zeros
    memset( hexarray, 0, dlenu );
    memset( kexarray, 0, klenu );

    // Fill the uint8_t arrays
    for (int i=0;i<dlen;i  ) {
        hexarray[i] = (uint8_t)report[i];
    }
    for (int i=0;i<klen;i  ) {
        kexarray[i] = (uint8_t)key[i];
    }

    int reportPad = pkcs7_padding_pad_buffer( hexarray, dlen, sizeof(hexarray), 16 );
    int keyPad = pkcs7_padding_pad_buffer( kexarray, klen, sizeof(kexarray), 16 );

    printf("The padded STRING in hex is = ");
    for (i=0; i<dlenu;i  ){
        printf("x",hexarray[i]);
    }
    printf("n");

    printf("The padded key in hex is = ");
    for (i=0; i<klenu;i  ){
        printf("x",kexarray[i]);
    }
    printf("n");

    // In case you want to check if the padding is valid
    int valid = pkcs7_padding_valid( hexarray, dlen, sizeof(hexarray), 16 );
    int valid2 = pkcs7_padding_valid( kexarray, klen, sizeof(kexarray), 16 );
    printf("Is the pkcs7 padding valid  report = %d  |  key = %dn", valid, valid2);

    //start the encryption
    struct AES_ctx ctx;
    AES_init_ctx_iv(amp;ctx, kexarray, iv);

    // encrypt
    AES_CBC_encrypt_buffer(amp;ctx, hexarray, dlenu);

    printf("the encrypted STRING = ");
    for (i=0; i<dlenu;i  ){
        printf("x",hexarray[i]);
    }
    printf("n");

    return hexarray;
}

int main(int argc, char *argv[]) {
    // File pointer
    FILE *input_file;

    int operation;

    char * input_file_buffer = 0;
    long input_file_length;

    // ////////////////////////////////////////////////////////
    // Read command line arguments
    // ////////////////////////////////////////////////////////

    // Make sure proper command params are supplied
    if (argc != 3) {
        printf("Usage: %s encrypt/decrypt filenamen", argv[0]);
        return -1;
    }

    // Define operation type
    if (strcmp(argv[1], "encrypt") == 0) {
        operation = ENCRYPT;
    } else if (strcmp(argv[1], "decrypt") == 0) {
        operation = DECRYPT;
    }

    // ////////////////////////////////////////////////////////
    // Open File contents
    // ////////////////////////////////////////////////////////

    // Open input_file to encrypt/decrypt.
    input_file = fopen(argv[2], "rb");
    if (!input_file) {
        fprintf(stderr, "ERROR: '%s' file fopen error: %sn", argv[2], strerror(errno));
        return errno;
    }

    // Read contents of file in buffer
    fseek(input_file, 0, SEEK_END);
    input_file_length = ftell (input_file);
    fseek(input_file, 0, SEEK_SET);
    input_file_buffer = malloc (input_file_length);
    if (input_file_buffer)
    {
        fread(input_file_buffer, 1, input_file_length, input_file);
    }

    // Close input_file
    fclose(input_file);

    // We have contents of file in input_file_buffer, let's print them.
    printf("File contents:n-------n%sn", input_file_buffer);

    // Let's encrypt input_file_buffer
    uint8_t result = 0;
    result = my_encrypt(input_file_buffer);

    // Convery result to string.
    printf("main: Encrypted File contents:n-------n%dn", result);

    return 0;
}
 

Комментарии:

1. Разве это не проблема XY? Если ваша цель — сохранить массив uint8_t, вам следует сохранить массив uint8_t. Для этого нет необходимости преобразовывать его в строку.

2. Шестнадцатеричные строки представляют собой понятную для человека интерпретацию байтов. Выходные printf данные оператора представлены в шестнадцатеричных числах, а входные данные в uint_8 массиве являются двоичными. Итак, если вы поместите выходные printf данные в файл, то все готово. Однако двоичные файлы обрабатываются отлично; вам нужны только шестнадцатеричные числа для использования человеком.

3. Ах, позвольте мне попробовать сохранить двоичный файл в файле. Вернется с результатом.

4. Хорошо, для тестирования есть, например, утилиты Posix, такие как hexdump -C (или просто hd ) для просмотра содержимого двоичного файла в виде шестнадцатеричных чисел. Многие редакторы / IDE также имеют возможность просматривать содержимое двоичного файла с использованием шестнадцатеричных чисел.

5. Мне неясно, что вы подразумеваете под «массивом uint8_t (который содержит шестнадцатеричный)» — это массив uint8_t, то есть массив байтов без знака. Вы присваиваете их, представляя значения байтов в коде в шестнадцатеричном виде, но если бы вы использовали ‘u’ вместо 0x75, массив содержал бы то же значение.