c - 在C中读取包含十六进制值的char数组

标签 c arrays hex

这是我用 C 语言解密 AES 的程序的一部分。该程序应该从外部文件中获取 IV,读取它,然后将其设置为 IV。不幸的是,IV 在代码中被声明为 char 数组(我无法更改),所以我尝试做的是将外部文件读取为 byte[],然后将其转换为 char[]。

我目前面临的问题之一是关于 AES_IV 变量,如下所示:

#define AES_BLOCK_SIZE  0x10

char AES_IV[AES_BLOCK_SIZE] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};

当我尝试使用代码打印 AES_IV 时

printf("\nAES_IV: ");
for (i3 = 0; i3 < AES_BLOCK_SIZE; i3++) {
printf("%02x", AES_IV[i3]);
}
printf("\n");

输出为:

AES_IV: 0c0a513398f1eda13ed2fc7213b50b10

这与我声明的 AES_IV 不同。

我将 for 循环更改为

for (i3 = 0; i3 < 50; i3++) {

结果输出更长

AES_IV: 0c0a513398f1eda13ed2fc7213b50b105369a...(100 chars in total)

我检查了 AES_IV 的长度,它仍然是 16,但是为什么我的 for 循环返回这么长的结果?另外,为什么 AES_IV 的值发生了变化?我已经检查过了,在这部分之前的任何地方都没有提到 AES_IV。

非常感谢您的帮助。

引用源码:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <dlfcn.h>
#include "SmartSDLib.h"

#define SDCARD_PATH "/boot"

#define P1_INDEX 2
#define P2_INDEX 3
#define P3_INDEX 4

#define AES_BLOCK_SIZE  0x10
#define APDU_HEADER_SIZE 5

#define FILELEN 32 // For reading IV from file

void To_Hex(char s8Data[],char hexBuffer[], int offset, int nlen)
{
    int j;
    int nSize = (nlen - offset); 
    char finalhash[8192];
    char hexval [] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    for(j=0 ; j < nSize; j++)
    {
        finalhash[j*2] = hexval[(s8Data[j] >> 4) & 0xF];
        finalhash[(j*2) + 1] = hexval[s8Data[j] & 0x0F];
    }

    memset(hexBuffer,0x00,8192);
    memcpy(hexBuffer, finalhash, nSize*2);
}

char * AccessAPDU(char command[], int size)
{
    unsigned char u8Ret;
    int s32Len[1];
    char s8Buffer[512], hexBuffer[8192];

    To_Hex(command, hexBuffer, 0, size);
    //printf ("%s\n%s%s\n", "AccessAPDUCommand:","CMD:" , hexBuffer);
    u8Ret = OT_SmartSDCard_AccessAPDUCommand(size, command, s32Len, s8Buffer, 0);
    if(u8Ret == 0x00)
    {
        printResult(s32Len, s8Buffer);
    }
    else
    {
        printf ("%s%x\n\n", "Error 0x", u8Ret);
    }
    return s8Buffer;
}

void printResult (int s32Len[], char s8Buffer[])
{
    char hexBuffer[8192];
    if(s32Len[0] >= 2)
    {
        To_Hex(s8Buffer, hexBuffer, 0, s32Len[0]);
    //  printf ("%s%s\n", "Ret:", hexBuffer);
    //  printf ("%s%d\n\n", "Len: ", s32Len[0]);
    } 
    else
    {
        printf ("%s%d\n", "Len: ", s32Len[0]);
    }
}

void CopyBuffer(char Dest[], char Source[], unsigned int length){
    while(length){
        Dest[length - 1] = Source[length - 1];
        length--;
    }
}

int ascii_to_hex(char c) // For reading IV from file
{
        int num = (int) c;
        if(num < 58 && num > 47) // Handle numbers (0-9)
        {
                return num - 48;
        }
        if(num < 103 && num > 96) // Handle lowercase alphabets (a-f)
        {
                return num - 87;
        }
        if(num < 71 && num > 64) // Handle uppercase alphabets (A-F)
        {
                return num - 55;
        }
        return num;
}

int main()
{
    unsigned char u8Ret;    
    char SDCard_Path[64];
    char line[64];
    int s32Len[1];
    char s8Buffer[512], hexBuffer[8192];
    int exit = 1;
    int iChoice;
    char * response;
    int test;
    char testchar[32];
    bool flag = true;

    char fileName[100];
    char encrypted[100];
    char decrypted[100];
    int i;
    int j;
    int blockCounter = 0;
    int commandCounter = 0;
    char imageBuffer[1];

    /* APDU commands */
    char AES_encrypt_cmd[APDU_HEADER_SIZE + AES_BLOCK_SIZE] = {0x80, 0x2A, 0x01,0x00, AES_BLOCK_SIZE}; //encryption APDU
    char AES_decrypt_cmd[APDU_HEADER_SIZE + AES_BLOCK_SIZE] = {0x80, 0x2A, 0x02,0x00, AES_BLOCK_SIZE}; //decryption APDU
    char GetResponse_cmd[]                                  = {0x00, 0xC0, 0x00,0x00, 0x00}; //Le to be changed before use
    char SelectAESapplet_cmd[]                              = {0x00, 0xA4, 0x04,0x00, 0x10, 0xA0, 0x00, 0x00, 0x00, 0x77, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x04};
    //char PutKeyAES_cmd[]                                    = {0x80, 0xD8, 0x00,0xF8, 0x20, 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00};
    char PutKeyAES_cmd[]                                    = {0x80, 0xD8, 0x00,0xF8, 0x20, 0xCF,0x10,0xF9,0xBD,0xF6,0xAA,0x15,0xC5,0x0E,0xCD,0x79,0xE6,0x28,0x3D,0xA8,0x0A,0x79,0x7A,0x2D,0x27,0x03,0xAE,0x07,0xD5,0x2F,0x5D,0x8F,0x60,0x1F,0x1E,0xF2,0x6F};

    /* AES variables */
    int  AES_keyIndex = 0;
    char AES_IV[AES_BLOCK_SIZE] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
    //char AES_IV[AES_BLOCK_SIZE] = {0x12,0xFB,0x87,0x11,0x62,0x7E,0xBB,0x55,0x71,0x7B,0x2F,0x70,0xA4,0x97,0x55,0x7B};
    //char AES_IV[AES_BLOCK_SIZE];
    char AES_CBC_vector[AES_BLOCK_SIZE];
    char AES_cmdBuffer[APDU_HEADER_SIZE + AES_BLOCK_SIZE];

    FILE * rFile;
    FILE * wFile;

    FILE *fileptr;char *buffer;long filelen;int i2,i3,i4;char IV_temp[AES_BLOCK_SIZE]; // This line for the file --> byte --> Hex


    printf ("%s\n", "This program will run 1, 2 followed by 6");


    //      case 1 :
                printf ("%s\n", "Initializing: ");
                u8Ret = OT_SmartSDCard_Initialization(SDCARD_PATH);
                if(u8Ret == 0x00)
                    printf ("%s\n\n", "Initialization OK");
                else
                    printf ("%s%x\n\n", "Initialization: Error 0x",u8Ret);

            //  printf ("%s\n\n", "-------------------------------------");

                /* ATR */
                u8Ret = OT_SmartSDCard_Reset(s32Len, s8Buffer);
                if(u8Ret == 0x00)
                {
                    To_Hex(s8Buffer,hexBuffer, 0, s32Len[0]);
          //          printf ("%s%s\n", "ATR : ", hexBuffer);
          //          printf ("%s%d\n\n", "Len : ", s32Len[0]);
                }
                else
                    printf ("%s%x\n\n", "Reset: Error 0x",u8Ret);
          //      printf ("%s\n\n", "-------------------------------------");

                /* Select AES applet */
                printf("%s\n", "Selecting AES applet...");
                response = AccessAPDU(SelectAESapplet_cmd, sizeof(SelectAESapplet_cmd));
                if(response[0] == 0x61){
                    GetResponse_cmd[P3_INDEX] = response[1];
                    AccessAPDU(GetResponse_cmd, sizeof(GetResponse_cmd));
                }
          //      printf ("%s\n\n", "-------------------------------------");


    //      case 2 :
                printf("Putting key...");

                AES_keyIndex = 0;
                memset(line, 0x00, sizeof(line));

                PutKeyAES_cmd[2] = AES_keyIndex;
                printf("putting key on index %d\n", AES_keyIndex);
                response = AccessAPDU(PutKeyAES_cmd, sizeof(PutKeyAES_cmd));

                AES_encrypt_cmd[P2_INDEX] = AES_keyIndex;
                AES_decrypt_cmd[P2_INDEX] = AES_keyIndex;

            //  printf ("%s\n\n", "-------------------------------------");


    //      case 6 :
                printf ("Decrypting in CBC...");
            //  printf ("File Name: /home/pi/test_encrypted\n");
            //    printf ("Encrypted File Name: /home/pi/test_decrypted\n");
                rFile = fopen("/home/pi/test_encrypted","rb");
                wFile = fopen("/home/pi/test_decrypted","wb");

                ////////////////////////////////////////////////////////////////
                // This part to read rFile and store as a byte [WORKING!]

                fseek(rFile, 0, SEEK_END);          // Jump to the end of the file
                filelen = ftell(rFile);             // Get the current byte offset in the file
                rewind(rFile);                      // Jump back to the beginning of the file

                buffer = (char *)malloc((filelen+1)*sizeof(char)); // Enough memory for file + \0
                fread(buffer, filelen, 1, rFile); // Read in the entire file

                // This part to convert buffer to hex value [WORKING!]

                for (i2 = 0; i2 < 100; i2++)
                {
                    if (i2 > 0) printf(" ");
                    printf("%02X", buffer[i2]);
                    IV_temp[i2] = buffer[i2];
                }

                // This part to print stuff [AES_IV not printing out correctly]

                printf("\nAES_IV: ");
                //fwrite(AES_IV, 1, sizeof(AES_IV), stdout);
                for (i3 = 0; i3 < 50; i3++) {
                    printf("%02x", AES_IV[i3]);
                }
                printf("\n");
                /*
                printf("IV_temp: ");
                for (i4 = 0; i4 < AES_BLOCK_SIZE; i4++) {
                    printf("%02x", IV_temp[i4]);
                }
                printf("\n");
                */
                for (i3 = 0; i3 < AES_BLOCK_SIZE; i3++) {
                    AES_IV[i3] = IV_temp[i3];
                }
                printf("\nLength of AES_IV = %d\n", sizeof(AES_IV));
                printf("\nAES_IV: ");

                for (i3 = 0; i3 < 50; i3++) {
                    printf("%02x", AES_IV[i3]);
                }
                printf("\n");

                // Return the file pointer to start of file
                rewind(rFile);
                ////////////////////////////////////////////////////////////////

                if (rFile == NULL || wFile == NULL)
                    perror("Error opening File");
                else{
                    int IsEOF = false;
                    // Initialize the CBC block with IV
                    CopyBuffer(AES_CBC_vector, AES_IV, AES_BLOCK_SIZE);

                    while (IsEOF == false) {
                        i = 0;
                        while(i < AES_BLOCK_SIZE){ // i run from 0 to (AES_BLOCK_SIZE - 1)
                            AES_cmdBuffer[APDU_HEADER_SIZE + i] = fgetc(rFile);
                            if(feof(rFile)) {
                                IsEOF = true;
                                if(i == 0) { // break out of while loop if a new block is not yet in progress
                                    break;
                                } else { // continue to finish the block and pad with zeros
                                    AES_cmdBuffer[APDU_HEADER_SIZE + i] = 0x00; //padding
                                }
                            }

                            i++;
                        }

                        if(i == 0) break; //break out of while loop, nothing to send to card

                        // Fill in the APDU header
                        CopyBuffer(AES_cmdBuffer, AES_decrypt_cmd, APDU_HEADER_SIZE);

                        response = AccessAPDU(AES_cmdBuffer, sizeof(AES_cmdBuffer));

                        if(response[0] == 0x61){
                            if(response[1] != AES_BLOCK_SIZE) {
                                perror("Card returning wrong block size");
                            }

                            GetResponse_cmd[P3_INDEX] = AES_BLOCK_SIZE;
                            response = AccessAPDU(GetResponse_cmd, sizeof(GetResponse_cmd));

                            /* CBC mode */
                            for(i = 0; i < AES_BLOCK_SIZE; i++){
                                response[i] ^= AES_CBC_vector[i];
                            }

                            fwrite(response, sizeof(char), AES_BLOCK_SIZE, wFile);

                            // Take the ciphertext to perform XOR next time
                            CopyBuffer(AES_CBC_vector, &AES_cmdBuffer[APDU_HEADER_SIZE], AES_BLOCK_SIZE);
                        } else {
                            perror("Error decrypting file using the smart card");
                        }
                    }
                }
                fclose (rFile);
                fclose (wFile);
            //  printf ("%s\n\n", "-------------------------------------");

    return 0;
}

最佳答案

正如一条评论已经指出的那样,您应该使用 unsigned char否则每个元素都被视为 signed char默认情况下。更好的是,您可能想使用固定宽度 uint8_t来自#include <stdint.h>相反。

这是一个按预期工作的最小示例:

#include <stdint.h>
#include <stdio.h>

#define AES_BLOCK_SIZE  0x10

uint8_t AES_IV[AES_BLOCK_SIZE] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};

int
main( void )
{
    int i;

    for ( i = 0; i < sizeof(AES_IV); i++ ) {
        printf( "%02x", AES_IV[i] );
    }

    return 0;
}

关于c - 在C中读取包含十六进制值的char数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41847879/

相关文章:

php - 分组多维数组

java - 如何在Java中创建具有随机长度列的多维数组?

php - 使用 CURLOPT_POSTFIELDS 时数组 2 字符串转换

c - 按位与 C 中的 HEX 和 CHAR

c++ - C 中的非常大尺寸的矩阵

c - 如何将已解析的字符串放入 malloc/calloc/动态内存中?

c - C 中的惰性算术

c++ - 为什么不允许使用 "second C linkage of overloaded function"?

python - 重新排序十六进制字符串中的字节顺序(python)

Python,打印十六进制删除第一个 0?