I'm currently using the following to print uint8_t to hex:
for(int j = 0; j < len; j++) {
printf("%02X ", bytes[j]);
}
Is it possible to do this without a for-loop and simply assign the result to a variable?
Here's one simple way:
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
bool to_hex(char* dest, size_t dest_len, const uint8_t* values, size_t val_len) {
if(dest_len < (val_len*2+1)) /* check that dest is large enough */
return false;
*dest = '\0'; /* in case val_len==0 */
while(val_len--) {
/* sprintf directly to where dest points */
sprintf(dest, "%02X", *values);
dest += 2;
++values;
}
return true;
}
int main() {
uint8_t values[256];
char buf[sizeof(values)*2+1]; /* one extra for \0 */
for(size_t i=0; i<256; ++i)
values[i] = i;
if(to_hex(buf, sizeof(buf), values, sizeof(values)))
printf("%s\n", buf);
}
Output:
000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
For completeness, here's a self contained version using a lookup table instead of sprintf:
bool to_hex(char* dest, size_t dest_len, const uint8_t* values, size_t val_len) {
static const char hex_table[] = "0123456789ABCDEF";
if(dest_len < (val_len*2+1)) /* check that dest is large enough */
return false;
while(val_len--) {
/* shift down the top nibble and pick a char from the hex_table */
*dest++ = hex_table[*values >> 4];
/* extract the bottom nibble and pick a char from the hex_table */
*dest++ = hex_table[*values++ & 0xF];
}
*dest = 0;
return true;
}
Personally, I'd go for the sprintf approach, but if you badly do not want to use one of the library api, you could use something like this:
char HexLookUp[] = "0123456789abcdef";
void bytes2hex (unsigned char *src, char *out, int len)
{
while(len--)
{
*out++ = HexLookUp[*src >> 4];
*out++ = HexLookUp[*src & 0x0F];
src++;
}
*out = 0;
}
Test code:
int main(void)
{
unsigned char bytes[] = {0x00, 0x01, 0x02, 0x03, 0xDE, 0xAD, 0xBE, 0xEF, 0xCC};
char buffer[sizeof(bytes)*2 + 1];
bytes2hex(bytes, buffer, sizeof(bytes));
printf("%s\n",buffer);
return 0;
}
Output:
00010203deadbeefcc
How I can decrypt by DES_ENCRYPT in c using openssl library.
I found the following function to decrypt and it worked fine when the lengh of key is 8 byte! But when I use 16 byte key, it results wrong value!
int CBC_3Des_Decrypt(char *data, char *okey)
{
DES_key_schedule ks;
DES_cblock ivec = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int i = 0;
int len = 0;
int nlen = 0;
unsigned char ch = '\0';
unsigned char *ptr = NULL;
unsigned char src[16] = {0};
unsigned char dst[16] = {0};
unsigned char block[8] = {0};
ptr = hex2bin(okey, strlen(okey), &nlen);
memcpy(block, ptr, 8);
free(ptr);
DES_set_key_unchecked((const_DES_cblock*)block, &ks);
len = strlen((char *)data);
ptr = hex2bin(data, len, &nlen);
len = (nlen / 8 + (nlen % 8 ? 1: 0)) * 8;
memcpy(src, ptr, len);
free(ptr);
ch = 8 - nlen % 8;
memset(src + nlen, ch, 8 - nlen % 8);
for (i = 0; i < len; i++) {
TRACE(("%.2X", *(src + i)));
}
DES_ncbc_encrypt(src, dst, sizeof(src), &ks, &ivec, DES_DECRYPT);
for (i = 0; i < len; i++) {
TRACE(("%.2X", *(dst + i)));
}
return 0;
}
How I can decrypt or encrypt using this library with 16 byte key?
The call you're making (DES_ncbc_encrypt) is the DES algorithm, not 3DES. I suspect you meant to call DES_ede3_cbc_encrypt.
It's important not to confuse DES and 3DES ("triple DES"). They're related algorithms, but not the same. Inside of OpenSSL, 3DES is generally called EDE3. EDE3 is a specific way of implementing Triple DES (and is the one everyone uses, so in practice they're generally synonymous).
I am trying to use this code to compute CRC16 bypass. For regular characters it works but for a hex sequence like 0xA0 0x00 0x01 0x01 it fails, not returning the correct value. Go easy on me, usually I do not write C code.
#include <stdio.h>
#include <string.h>
unsigned short CalculateCRC(unsigned char* a_szBuffuer, short a_sBufferLen){
unsigned short usCRC = 0;
for (short j = 0; j < a_sBufferLen; j++)
{
unsigned char* pucPtr = (unsigned char *)&usCRC;
*(pucPtr + 1) = *(pucPtr + 1) ^ *a_szBuffuer++;
for (short i = 0; i <= 7; i++)
{
if (usCRC & ((unsigned short) 0x8000))
{
usCRC = usCRC << 1;
usCRC = usCRC ^ ((unsigned short) 0x8005);
}
else
usCRC = usCRC << 1;
}
}
return (usCRC);
}
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
int main() {
char d = (char)0xA0;
char d1 = (char)0x00;
char d2 = (char)0x01;
char d3 = (char)0x01;
char sss[256]="";
append(sss, d);
append(sss, d1);
append(sss, d2);
append(sss, d3);
unsigned char* uCB1 = (unsigned char*)sss;
unsigned short CRC= CalculateCRC(uCB1,4);
printf("CRC = %i\n", CRC);
printf("%s\n", sss);
printf("%x\n", CRC);
}
strlen(s); is for finding the length of a string, not for finding the length of a character array that is used, especially if it that may contain '\0'. #Eugene Sh.
Code needs to keep track of the array size used with another variable.
// void append(char* s, char c) {
void append(char* s, size_t *sz, char c) {
s[*sz] = c;
(*sz)++;
}
...
size_t size = 0;
append(sss, &size, d);
append(sss, &size, d1);
append(sss, &size, d2);
append(sss, &size, d3);
unsigned char* uCB1 = (unsigned char*)sss;
unsigned short CRC= CalculateCRC(uCB1, size);
// printf("%s\n", sss);
write a loop to print each `sss[]`.
This is part of a program that I use to decrypt AES in C. The program is supposed to take in an IV from an external file, read it then set as the IV. Unfortunately the IV is declared as a char array in the code (which I cannot change) so what I tried to do is to read the external file as byte[], then convert it to char[].
One of the issues I am currently facing is regarding the AES_IV variable as seen below:
#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};
When I try to print out the AES_IV using the code
printf("\nAES_IV: ");
for (i3 = 0; i3 < AES_BLOCK_SIZE; i3++) {
printf("%02x", AES_IV[i3]);
}
printf("\n");
The output is:
AES_IV: 0c0a513398f1eda13ed2fc7213b50b10
Which is different from the AES_IV I declared.
I changed the for loop to
for (i3 = 0; i3 < 50; i3++) {
and the resultant output is much longer
AES_IV: 0c0a513398f1eda13ed2fc7213b50b105369a...(100 chars in total)
I checked the length of AES_IV and it is still 16, but why does my for loop returns such a long result? Also why did the value of AES_IV change? I have checked and there are no reference to AES_IV anywhere before this part.
Your help is much appreciated.
Source code for reference:
#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;
}
As one comment already stated you should use unsigned char otherwise each element is treated as a signed char by default. Better yet you might want to use fixed-width uint8_t from #include <stdint.h> instead.
Here is a minimal example that works as expected:
#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;
}
How do I create a string that contain multiple '\x41' or with arbitrary '\xnn' by copy from some give string for example:
char * string1 = "4141414141414141";
or char * string2 = "bde54d7ee10a2122";
And I would like my char * string3 become something like:
char * string3 = "\xbd\xe5\x4d\x7e\xe1\x0a\x21\x22";
or char * string3 = "\x41\x41\x41\x41\x41\x41\x41\x41";
Here is the code that I am trying to do, but it doesn't work.
char * string1 = "4141414141414141";
char c;
char * slash_x = "\\x";
int len = strlen(string1);
char * string3 = (char *) malloc(9);
for (i = 0; i < len; i++) {
if (0 == i % 2) {
printf("start\n");
j = i;
strcat(salt_empty, slash_x);
c = string[j];
printf("%c\n", c);
strncat(salt_empty, &c, 1);
j++;
c = string[j];
printf("%c\n", c);
strncat(salt_empty, &c, 1);
}
}
printf("%s\n", string3);
So the output with string3 will be "\x41\x41\x41\x41\x41\x41\x41\x41" instead of "AAAAAAAA" at console.
How could I fix the code in order to get "AAAAAAAA"
If the string1 is "bde54d7ee10a2122", then the string3 output at console would be ��M~
!"
You cannot convert the string by re-interpreting it from its source form. Use this instead (inefficient, but simple):
char *string1 = "4141414141414141";
int i, j, len = strlen(string1) & ~1;
char string3[len / 2 + 1];
for (i = j = 0; i < len; i += 2, j++) {
char buf[3];
memcpy(buf, string1 + i, 2);
buf[2] = '\0';
string3[j] = strtol(buf, NULL, 16);
}
string3[j] = '\0';
printf("%s\n", string3);
You want:
char string1[] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0};
For each pair of characters in the source string, determine the hex value of each character in the pair, combine them to come up with the encoded character, then store the result in your destination string.