This is my code (the errors checking were deliberately omitted for code readability):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gcrypt.h>
#define GCRYPT_VERSION "1.5.0"
#define GCRY_CIPHER GCRY_CIPHER_AES128
int main(void){
if(!gcry_check_version(GCRYPT_VERSION)){
fputs("libgcrypt version mismatch\n", stderr);
exit(2);
}
gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0);
gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
int algo = -1;
size_t i;
const char *name = "aes128";
char plain_text[16] = {0x80};
char key[16] = {0};
char iniVector[16] = {0};
size_t txtLenght = strlen(plain_text);
char *encBuffer = malloc(txtLenght);
gcry_cipher_hd_t hd;
algo = gcry_cipher_map_name(name);
size_t blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
gcry_cipher_open(&hd, algo, GCRY_CIPHER_MODE_CBC, 0);
gcry_cipher_setkey(hd, key, keyLength);
gcry_cipher_setiv(hd, iniVector, blkLength);
gcry_cipher_encrypt(hd, encBuffer, txtLenght, plain_text, txtLenght);
printf("encBuffer = ");
for(i = 0; i < txtLenght; i++){
printf("%02x", (unsigned char) encBuffer[i]);
}
printf("\n");
gcry_cipher_close(hd);
free(encBuffer);
return 0;
}
Expected result:
KEY = 00000000000000000000000000000000
IV = 00000000000000000000000000000000
PLAINTEXT = 80000000000000000000000000000000
CIPHERTEXT = 3ad78e726c1ec02b7ebfe92b23d9ec34
My result:
KEY = 00000000000000000000000000000000
IV = 00000000000000000000000000000000
PLAINTEXT = 80000000000000000000000000000000
CIPHERTEXT = 42
Why i got this output? What am I doing wrong?
You are using ASCII values but the AES test vectors are given as hexadecimal values.
Try with hex values instead (the remaining values of the array are initialized by 0 in C):
char plain_text[16] = {0x80};
char key[16] = {0};
char iniVector[16] = {0};
size_t txtLenght = sizeof plain_text;
Related
This question already has answers here:
Function returning address of local variable error in C
(3 answers)
Closed 5 years ago.
I'm trying to construct and return a string in C, but running into a function returns address of local variable [-Wreturn-local-addr] compiler warning. I get that returning packet like I'm trying to do won't work, because packet is a pointer to the beginning of my chars of size packet_size, and that memory address isn't valid outside my function. I'm running on an AVR chip and don't want to use malloc. How should I go about solving this problem?
#include <stdio.h>
#include <string.h>
#include <stdint.h>
const char* construct_packet(const char* data);
void append(char* str, char c);
int main()
{
const char* my_packet = construct_packet("QERT");
printf("%s", my_packet);
return 0;
}
const char* construct_packet(const char* data)
{
const char training_chars[] = "___";
const char start_char = '>';
uint8_t checksum = 0;
for(uint16_t i = 0; i < strlen(data); i++) {
checksum += data[i];
}
const char checksum_char = checksum;
uint8_t packet_size = strlen(training_chars) + strlen(data) + 2; // Plus 2 for start byte and checksum byte
char packet[packet_size];
strcat(packet, training_chars);
append(packet, start_char);
strcat(packet, data);
append(packet, checksum_char);
return packet;
}
void append(char* str, char c)
{
str[strlen(str) + 1] = c;
}
If you don't want to use dynamic memory allocation, and don't want to use a static buffer, then you might try calculating and providing the memory buffer on the stack:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
const char* construct_packet(const char* data, const char* training_chars, const char start_char, char* packet);
void append(char* str, char c);
int main()
{
const char data[] = "QERT";
const char training_chars[] = "___";
const char start_char = '>';
const uint8_t packet_size = strlen(training_chars) + strlen(data) + 2; // Plus 2 for start byte and checksum byte
char packet[packet_size];
const char* my_packet = construct_packet(data, training_chars, start_char, packet);
printf("%s", my_packet); // same as printf("%s", packet);
return 0;
}
const char* construct_packet(const char* data, const char* training_chars, const char start_char, char* packet)
{
uint8_t checksum = 0;
for(uint16_t i = 0; i < strlen(data); i++) {
checksum += data[i];
}
const char checksum_char = checksum;
strcat(packet, training_chars);
append(packet, start_char);
strcat(packet, data);
append(packet, checksum_char);
return packet;
}
void append(char* str, char c)
{
str[strlen(str) + 1] = c;
}
Phil Brubaker: If you don't want to use dynamic memory allocation, and don't want to use a static buffer, then you might try calculating and providing the memory buffer on the stack:
I will not say better, my implementation:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
// in some header file
const char *construct_packet(char *packet, const char* data);
size_t size_packet(const char* data);
int main(void)
{
const char *data = "QERT";
size_t packet_size = size_packet(data);
char packet[packet_size];
construct_packet(packet, data);
printf("%s", packet);
}
// can be on a other file of course `training_chars` and `start_char` could be give in parameter
// of course cause there are static `size_packet()` and `contruct_packet()` must be in the same file
static const char * const training_chars = "___";
static const char start_char = '>';
size_t size_packet(const char* data)
{
// you forgot nul terminate byte
return sizeof training_chars - 1 + 1 + strlen(data) + 1 + 1;
}
const char *construct_packet(char *packet, const char* data)
{
size_t i = 0;
// I replace strcat because I supose you want speed note they are better method that this one
for (size_t j = 0; training_chars[j] != '\0'; j++) {
packet[i++] = training_chars[j];
}
packet[i++] = start_char;
// maybe this should be a char but you don't give information about checksum so I can't be sure
uint8_t checksum = 0;
for (size_t j = 0; data[j] != '\0'; j++) {
packet[i++] = data[j];
checksum += data[j];
}
packet[i++] = (char)checksum;
// you forgot nul terminate byte
packet[i] = '\0';
return packet;
}
Of course, you could just not calculate the size and give a maximum:
char packet[256];
construct_packet(packet, data, 256);
im trying to convert a string message to hex value in C.
For example if i have a message like "abc" i want to have it by 162636 etc. My code is below. In this code, i have to do some concat operation to store them all but now i can store only 36. How can i store them?
unsigned char swapNibbles(char x)
{
return ( (x & 0x0F)<<4 | (x & 0xF0)>>4 );
}
void encode(char *message, char password[40]) {
unsigned char *reversedInput = malloc(strlen(message));
for (int i = 0; i < strlen(message); ++i) {
reversedInput=swapNibbles(message[i]);
}
printf("%2x TERS ",reversedInput);
//unsigned char *bitwiseMessage = (unsigned char*)message;
//printf("DÜZ %s\n",bitwiseMessage);
//printf("TERS %u\n", swapNibbles(bitwiseMessage));
}
Edit
My solution for hex-encoding: IDEOne
If you want your text to be hex-encoded, you will have to allocate twice as much space as the original message:
"abc" (3 bytes) ==> "616263" (6 bytes)
So you will need:
unsigned char *reversedInput = malloc(2*strlen(message)+1); // +1 for the final NULL-terminator
#include <string.h>
#include <malloc.h>
char* HexEncode(char* txt)
{
char* hexTxt = calloc(2*strlen(txt)+1,1);
for(char* p=hexTxt; *txt; p+=2)
{
sprintf(p, "%02x", *txt++);
}
return hexTxt;
}
int main() {
char* hexText = HexEncode("Hello World");
printf("Hexed is %s\n", hexText);
free(hexText);
return 0;
}
Output
Hexed is 48656c6c6f20576f726c64
Here is a basic code of encryping and decrypting a message:
#include <stdio.h>
#include <openssl/blowfish.h>
#include <string.h>
//gcc cryptage.c -o cryptage -lcrypto
int main(){
BF_KEY *key = malloc(sizeof(BF_KEY));
unsigned char *crypt_key = "Key of encryption";
const unsigned char *in = "Message to encrypt";
int len = strlen(crypt_key);
unsigned char *out = malloc(sizeof(char)*len);
unsigned char *result = malloc(sizeof(char)*len);
//Defining encryption key
BF_set_key(key, len, crypt_key);
//Encryption
BF_ecb_encrypt(in, out, key, BF_ENCRYPT);
//Décryption
BF_ecb_encrypt(out, result, key, BF_DECRYPT);
fprintf(stdout,"Result: %s\n",result);
return 0;
}
My problem is the result i get. It's always a String of 8 caracters, no more.
Can you please help me encrypt and decrypt the full message?
Thank you!
As #WhozCraig says, do things 8 bytes at a time.
The data to encrypt should be viewed as a byte array and not a C string.
So consider the string to encrypt with the \0 and padded with random data to form a byte array that is a multiple of 8.
Call encrypt multiple times, encrypting 8 bytes per iteration.
To decrypt, call decryption the same number of iterations. Note that the result buffer may need to be sized up to a multiple of 8.
const unsigned char *in = "Message to encrypt";
size_t InSize = strlen(in) + 1;
int KeyLen = strlen(crypt_key);
size_t OutSize = (InSize + 7) & (~7);
unsigned char *out = malloc(Outsize);
unsigned char *outnext = out;
//Defining encryption key
BF_set_key(key, KeyLen, crypt_key);
//Encryption
while (InSize >= 8) {
BF_ecb_encrypt(in, outnext, key, BF_ENCRYPT);
in += 8;
outnext += 8;
InSize -= 8;
}
if (Insize > 0) { // Cope with non-octal length
unsigned char buf8[8];
memcpy(buf8, in, InSize);
for (i=InSize; i<8; i++) {
buf8[i] = rand();
}
BF_ecb_encrypt(buf8, outnext, key, BF_ENCRYPT);
}
//Décryption
unsigned char *result = malloc(OutSize);
unsigned char *resultNext = result;
while (OutSize) {
BF_ecb_encrypt(out, resultNext, key, BF_DECRYPT);
out += 8;
resultNext += 8;
OutSize -= 8;
}
fprintf(stdout,"Result: %s\n",result);
// No need to print the random bytes that were generated.
return 0;
}
Not quite comfortable have a known byte (\0) encoded in the last block. A different length indication may be prudent.
How do I work with msgpack_pack_raw and msgpack_pack_raw_body to send an unsigned char array to more importantly, how to retrieve (unpack) it?
What I have done is as follows:
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
msgpack_sbuffer_clear(buffer);
msgpack_pack_array(pk, 10);
unsigned char a[10] = "0123456789";
msgpack_pack_raw(pk, 10);
msgpack_pack_raw_body(pk,a,10);
and in the receiver part I have:
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL);
msgpack_object obj = msg.data;
msgpack_object* p = obj.via.array.ptr;
int length = (*p).via.raw.size;
IDPRINT(length);
unsigned char* b = (unsigned char*) malloc(length);
memcpy(b,(*p).via.raw.ptr,length);
But it throws seg fault when executing "int length = (*p).via.raw.size;".
Any idea why?
Any idea why?
This is because msgpack_pack_array(pk, 10); is not required here, since you pack your data as a raw buffer of a given size. In other words msgpack_pack_raw and msgpack_pack_raw_body are sufficient.
At unpack time, you must access its fields as follow:
length: obj.via.raw.size
data: obj.via.raw.ptr
see: msgpack_object_raw in object.h.
Here's a recap of how to proceed:
#include <stdio.h>
#include <assert.h>
#include <msgpack.h>
int main(void) {
unsigned char a[10] = "0123456789";
char *buf = NULL;
int size;
/* -- PACK -- */
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pck;
msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write);
msgpack_pack_raw(&pck, 10);
msgpack_pack_raw_body(&pck, a, 10);
size = sbuf.size;
buf = malloc(sbuf.size);
memcpy(buf, sbuf.data, sbuf.size);
msgpack_sbuffer_destroy(&sbuf);
/* -- UNPACK -- */
unsigned char *b = NULL;
int bsize = -1;
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
if (msgpack_unpack_next(&msg, buf, size, NULL)) {
msgpack_object root = msg.data;
if (root.type == MSGPACK_OBJECT_RAW) {
bsize = root.via.raw.size;
b = malloc(bsize);
memcpy(b, root.via.raw.ptr, bsize);
}
}
/* -- CHECK -- */
assert(bsize == 10);
assert(b != NULL);
for (int i = 0; i < bsize; i++)
assert(b[i] == a[i]);
printf("ok\n");
free(buf);
free(b);
return 0;
}
Although I've used C++ a lot, I'm struggling with the C differences (mainly in strings).
Could you please show me a simple single function that encrypts a message with a key using XOR comparison.
Thank-you
EDIT:
Both the key and the message are char*
OK, I hacked around for a minute and came up with this (only vaguely tested):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * xorencrypt(char * message, char * key) {
size_t messagelen = strlen(message);
size_t keylen = strlen(key);
char * encrypted = malloc(messagelen+1);
int i;
for(i = 0; i < messagelen; i++) {
encrypted[i] = message[i] ^ key[i % keylen];
}
encrypted[messagelen] = '\0';
return encrypted;
}
int main(int argc, char * argv[]) {
char * message = "test message";
char * key = "abc";
char * encrypted = xorencrypt(message, key);
printf("%s\n", encrypted);
free(encrypted);
return 0;
}
Note that the function xorencrypt allocates and returns a new string, so it's the caller's responsibility to free it when done.
C is very close to Assembler, so this example is short:
while (*string)
*string++ ^= key;
assuming char *string; and char key.
For what it's worth, combine the answers from #ott-- & #Tim to form Xortron.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *xor(char *string, const char *key)
{
char *s = string;
size_t length = strlen(key), i = 0;
while (*s) {
*s++ ^= key[i++ % length];
}
return string;
}
int main(int argc, char **argv)
{
const char *key = "abc";
if (argc < 2) {
fprintf(stderr, "%s: no input\n", argv[0]);
return EXIT_FAILURE;
}
printf("%s\n", xor(xor(argv[1], key), key));
return EXIT_SUCCESS;
}