I would like to encrypt using tiny AES library (https://github.com/kokke/tiny-AES-c) in C for AES128.
My code is as below:
unsigned char cipher[64];
unsigned char in[] = "THJmaoeuf2jsn4jebc7ak3mUdnyHeklOYopdna/OOndu3bis/E7jTd/enasduR3h"; //64 bits
printf("Size of AES input msg: %d \n", sizeof(in));
unsigned char key[] = "Gns7AauH3dnaod=="; //16 bits
unsigned char IV[] = "vhdNaleuTHenaOlL"; //16 bits
printf("cipher(before): %x \n", cipher);
AES128_CBC_encrypt_buffer(cipher, in, 64, key, IV);
for(int n=0; n<64; n++){
printf("cipher[%d]: %x \n", n, cipher);
}
The function I am using from tiny AES 128 library is this :
void AES128_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
However, the last line of printing 'cipher' is empty. I believe it should print the cipher text of the original input after encryption. Is this the correct way to use the library? Thank you.
EDIT: I updated the code here, in which 'cipher' is now printing characters but in a strange way. It prints the same thing before and after encryption, which should not be the case. This is the same case even when I changed the 'key' and 'IV' to be 16 bits and input message 'in' as 64 bits. Here is a part of the output:
cipher(before): 20003A34
cipher[0]: 20003A34
cipher[1]: 20003A34
cipher[2]: 20003A34
.
.
cipher[63]: 20003A34
Your code has undefined behavior.
This:
unsigned char *cipher = "";
makes cipher into a pointer to a single byte with the value 0 (the string terminator). It's a bit fishy since string literals are not guaranteed to be unsigned char (they're just char which is either signed or unsigned) but I think it will build.
This doesn't give you any writeable space, since string literals are read-only, so trying to write an entire encrypted block in there will give you undefined behavior.
To fix it you need:
unsigned char in[] = "THJmaoeuf2jsn4jebc7ak3mUdnyHeklOYopdna/OOndu3bis/E7jTd/enasduR3h"; //64 bits
unsigned char cipher[sizeof in];
Also, the encrypted data is very likely not a valid C string, it can contain 0-bytes and thus won't print correctly using printf("%s", ...); anyway.
in the line:
printf("cipher[%d]: %x \n", n, cipher);
change that to be:
printf("cipher[%d]: %x \n", n, cipher[n]);
That way, each byte of the cipher is outputted instead of the address of cipher which is what you are getting.
in aes.h select 128 by
#define AES128 1
and below is a sample for Encryption & Decryption
struct AES_ctx ctx;
uint8_t key[] = "aaaaaaaaaaaaaaaa";
uint8_t iv[] = "bbbbbbbbbbbbbbbb";
uint8_t str[] = "This a sample text, Length eq 32";
printf("\n raw buffer \n");
for (int i = 0; i < 32; ++i) {
printf("%.2x", str[i]);
}
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_encrypt_buffer(&ctx, str, 32);
printf("\n Encrypted buffer\n");
for (int i = 0; i < 32; ++i) {
printf("%.2x", str[i]);
}
printf("\n Decrypted buffer\n");
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, str, 32);
for (int i = 0; i < 32; ++i) {
printf("%.2x", str[i]);
}
printf("\n");
*Note: there is no padding is provided so for CBC and ECB, All buffers should be multiples of 16 bytes.
Related
I am working on AES-128/192/256, basically I am getting data from a broker as string, I just need to encrypt that data and I need to verify that.
I already come across these https://github.com/empyreanx/tiny-AES128-C, https://github.com/kokke/tiny-AES-c links.
My code is:
static void test_encrypt_cbc(void)
{
unsigned char input[] =
"So_letmeknowRuinterested/towork#thiscompany.comElsewilllookother";
//64bits
unsigned char cipher[sizeof input];
printf("size of in:%lu\n",strlen(input));
unsigned char key[] = "Gns7AauH3dnaod=="; //16 bits
unsigned char iv[] = "vhdNaleuTHenaOlL"; //16 bits
AES128_CBC_encrypt_buffer(cipher, input, 64, key, iv);
if(0 == memcmp((char*) cipher, (char*) input, 64))
{
printf("SUCCESS!\n");
}
else
{
printf("FAILURE!\n");
}
}
I also printed cipher text after encryption it is printing some undefined character.
I don't know but I am comparing "cipher" with "input", Its FAILURE finally!
Please anyone can tell me where I am doing wrong.
Thanks in advance.
This is logical to cipher to be different from input, isn't?
To check that encryption worked, you should decrypt the encoded message and check that they are equal:
static void test_encrypt_cbc(void)
{
/* 64 bytes, or 512 bits */
unsigned char input[] =
"So_letmeknowRuinterested/towork#thiscompany.comElsewilllookother";
unsigned char cipher[sizeof input];
unsigned char output[sizeof input];
printf("size of in:%lu\n",strlen(input));
/* 16 bytes or 128 bits */
unsigned char key[] = "Gns7AauH3dnaod==";
unsigned char iv[] = "vhdNaleuTHenaOlL";
/* input --> cipher */
AES128_CBC_encrypt_buffer(cipher, input, 64, key, iv);
/* cipher --> output */
AES128_CBC_decrypt_buffer(output, cipher, 64, key, iv);
if(0 == memcmp((char*) output, (char*) input, 64))
{
printf("SUCCESS!\n");
}
else
{
int i;
printf("FAILURE!\nInput and output are different:\n");
for (i = 0; i < sizeof input; ++i)
{
printf("%02x - %02x\n", input[i], output[i]);
}
}
}
I'll say up front, that my aim is not for security, but rather verifying data integrity.
I want to compute a standard hash for several terabytes of data using OpenSSL routines. The data is logically serialized (i.e. one array of bytes), but is distributed over many computers.
Rather than move the huge dataset to a single process (and memory space) for hashing, I want to pass around the hashing "context" so that the hash computation can take place locally everywhere the data is held.
Another way to frame the problem would be, I want to add bytes to the dataset later and continue the hash computation but result in the same hash answer as though all the bytes were available initially.
I've run into a sticking point, because I can't figure out how the "context" is stored by the library. I don't know what I would need to pass around or save to accomplish my intent.
(It is safe to assume that all hashing participants will be using the same version of the OpenSSL library.)
I adapted the documentation example to process two chunks of bytes to facilitate discussion. Now I want to know is there a way to pull the plug on the computer between chunk1 and chunk2 and still get the same answer? Or what if chunk1 and chunk2 are stored on different computers?
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
void print_bytes(const unsigned char * bytes, size_t count, const char * prefix)
{
printf("%s",prefix);
for(size_t i = 0; i < count; ++i) {
printf("%02x", bytes[i]);
}
printf(" (%zd Bytes)\n", count);
}
unsigned int md5_digest_process(const EVP_MD* type, const unsigned char *input, size_t numBytes, unsigned char* hash_out) {
EVP_MD_CTX mdctx;
unsigned int hash_len = 0;
size_t chunk1_size = numBytes/2;
size_t chunk2_size = numBytes - chunk1_size;
EVP_MD_CTX_init(&mdctx);
print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );
EVP_DigestInit_ex(&mdctx, type, NULL);
print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );
// Hash chunk 1:
EVP_DigestUpdate(&mdctx, input, chunk1_size);
print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );
// Hash chunk 2:
EVP_DigestUpdate(&mdctx, input+chunk1_size, chunk2_size);
print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );
EVP_DigestFinal_ex(&mdctx, hash_out, &hash_len);
EVP_MD_CTX_cleanup(&mdctx);
return hash_len;
}
int main(int argc, char *argv[]) {
if (argc!=2) {
fprintf(stderr, "One argument string expected.\n");
return 1;
}
//OpenSSL_add_all_digests();
//const EVP_MD *md = EVP_get_digestbyname("MD5");
const EVP_MD *md = EVP_md5(); //EVP_sha256();
if(!md) {
fprintf(stderr, "Unable to init MD5 digest\n");
return 1;
}
unsigned char hash[EVP_MAX_MD_SIZE];
const unsigned char * allBytes = (const unsigned char *)argv[1];
size_t numBytes = strlen(argv[1]); // skip null terminator, consistent with command line md5 -s [string]
printf("Hashing %zd bytes. EVP_MAX_MD_SIZE is %zd, EVP_MD_CTX size is %zd bytes.\n", numBytes, EVP_MAX_MD_SIZE, sizeof(EVP_MD_CTX));
int hash_len = md5_digest_process(md, allBytes, numBytes, hash);
print_bytes(hash, hash_len, "Hash: " );
return 0;
}
With output:
$ ./a.out foobar
Hashing 6 bytes. EVP_MAX_MD_SIZE is 64, EVP_MD_CTX size is 48 bytes.
EVP_MD_CTX: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (48 Bytes)
EVP_MD_CTX: 609d9d01010000000000000000000000000000000000000080274062cd7f0000000000000000000040de8e0101000000 (48 Bytes)
EVP_MD_CTX: 609d9d01010000000000000000000000000000000000000080274062cd7f0000000000000000000040de8e0101000000 (48 Bytes)
EVP_MD_CTX: 609d9d01010000000000000000000000000000000000000080274062cd7f0000000000000000000040de8e0101000000 (48 Bytes)
Hash: 3858f62230ac3c915f300c664312c63f (16 Bytes)
$ md5 -s foobar
MD5 ("foobar") = 3858f62230ac3c915f300c664312c63f
Since EVP_MD_CTX is not changing after each update, I infer that the algorithm state is actually stored elsewhere and I cannot simply copy the 48 EVP_MD_CTX bytes.
I've seen EVP_MD_CTX_copy_ex() in the manual, but I don't see how to use it for my purpose.
I have wrote a c code which takes the input value of key and message makes call to openssl hmac functions and generate result of mac code.
Input values are collected from NIST Test Vectors
#define KEY_SIZE 11 // in bytes
#define MSG_SIZE 129 // in bytes
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>
void str2hex(char *, char*, int);
int main() {
char *key, *msg;
unsigned char keyy[KEY_SIZE], msgt[MSG_SIZE], temp[4];
unsigned char* result;
unsigned int i, len = 20,Tlen = 10;
key = "";//values specified below
msg ="";//values specified below
/*CONVERT STRING TO HEX DIGITS - KEY*/
str2hex(key, keyy, KEY_SIZE);
//CONVERT STRING TO HEX DIGITS - MSG*//
str2hex(msg, msgt, MSG_SIZE);
result = (unsigned char*)malloc(sizeof(char) * len);
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, keyy, strlen(keyy), EVP_sha1(), NULL);
HMAC_Update(&ctx, (unsigned char*)&msgt, strlen(msgt));
HMAC_Final(&ctx, result, &len);
HMAC_CTX_cleanup(&ctx);
printf("HMAC digest: ");
for (i = 0; i < Tlen; i++)
printf("%02x", result[i]);
printf("\n");
free(result);
return 0;
}
//===================== string to hex conversion
================================//
void str2hex(char *str, char *hex, int len) {
int tt, ss;
unsigned char temp[4];
for (tt = 0, ss = 0; tt < len, ss < 2 * len; tt++, ss += 2) {
temp[0] = '0';
temp[1] = 'x';
temp[2] = str[ss];
temp[3] = str[ss + 1];
hex[tt] = (int) strtol(temp, NULL, 0);
}
}
//---------------------------------------------------------------------------------//
The first input given:
Key = 82f3b69a1bff4de15c33
Msg = fcd6d98bef45ed6850806e96f255fa0c8114b72873abe8f43c10bea7c1df706f10458e6d4e1c9201f057b8492fa10fe4b541d0fc9d41ef839acff1bc76e3fdfebf2235b5bd0347a9a6303e83152f9f8db941b1b94a8a1ce5c273b55dc94d99a171377969234134e7dad1ab4c8e46d18df4dc016764cf95a11ac4b491a2646be1
Output generated:
HMAC digest: 1ba0e66cf72efc349207
Nist_Mac = 1ba0e66cf72efc349207
It matches so success
But for the Second input
Key = 4766e6fe5dffc98a5c50
Msg = d68b828a153f5198c005ee36c0af2ff92e84907517f01d9b7c7993469df5c21078fa356a8c9715ece2414be94e10e547f32cbb8d0582523ed3bb0066046e51722094aa44533d2c876e82db402fbb00a6c2f2cc3487973dfc1674463e81e42a39d9402941f39b5e126bafe864ea1648c0a5be0a912697a87e4f8eabf79cbf130e
Output generated:
HMAC digest: ca96f112a79882074b63
Nist_Mac = 007e4504041a12f9e345
Its failing.If any one could check my code and kindly let me know what am i doing wrong it will be really helpfull.
You have two issues here.
The first is that you're using strlen on an array of characters that may contain a null byte. Since this function counts the number of bytes until it find a null byte, you won't get what you expect if your array contains a null byte (as is the case for your second example).
Instead of using strlen on the byte array to determine the length, use the actual length of the data. Since you're converting a string containing hex digits to bytes, the length of the byte array is half the length of the input string.
HMAC_Init_ex(&ctx, keyy, strlen(key)/2, EVP_sha1(), NULL);
HMAC_Update(&ctx, msgt, strlen(msg)/2);
Note also that you should pass msgt to HMAC_Update, not &msgt, as the latter is a pointer to an array.
The second issue is in your str2hex function. When you construct temp, you don't have enough space for a terminating null byte. This causes strtol, which expects a null-terminated string, to read past the end of the array. This invokes undefined behavior.
In this particular case you're "lucky" that it works, as the byte in memory that follows temp happens to contain either a null byte or a non-digit. You can't however depend on this behavior. Fix this by making temp one byte longer and explicitly setting that byte to 0. And while you're at it, you should also fix the signed / unsigned mismatch in your function arguments and change the type of temp to an unsigned char array.
void str2hex(char *, unsigned char*, int);
...
void str2hex(char *str, unsigned char *hex, int len) {
int tt, ss;
char temp[5];
for (tt = 0, ss = 0; tt < len, ss < 2 * len; tt++, ss += 2) {
temp[0] = '0';
temp[1] = 'x';
temp[2] = str[ss];
temp[3] = str[ss + 1];
temp[4] = 0;
hex[tt] = strtol(temp, NULL, 0);
}
}
At byte position 58 in the message, you have a 0x00 byte (null). Since you're doing an strlen(msgt), this results in 58 instead of 128. Excerpt from the documentation (emphasis mine):
The C library function size_t strlen(const char *str) computes the length of the string str up to, but not including the terminating null character.
Just use the proper length of the message and don't use string operations on char arrays that do not contain printable bytes.
Hello I am using digi dynamic c. I am trying to convert this in to string
char readingreg[4];
readingreg[0] = 4a;
readingreg[1] = aa;
readingreg[2] = aa;
readingreg[3] = a0;
Currently when I do printf statements it has to be like this:
printf("This is element 0: %x\n", readingreg[0]);
But I want this in string so I can use printf statement like this
printf("This is element 0: %s\n", readingreg[0]);
I am essentialy sending the readingreg array over TCP/IP Port, for which I need to have it as string. I cant seem to be able to convert it into string. Thanks for your help.
Also if someone can tell me how to do each element at a time rather than whole array, that would be fine to since there will only be 4 elements.
0xaa overflows when plain char is signed, use unsigned char:
#include <stdio.h>
int main(void)
{
unsigned char readingreg[4];
readingreg[0] = 0x4a;
readingreg[1] = 0xaa;
readingreg[2] = 0xaa;
readingreg[3] = 0xa0;
char temp[4];
sprintf(temp, "%x", readingreg[0]);
printf("This is element 0: %s\n", temp);
return 0;
}
If your machine is big endian, you can do the following:
char str[9];
sprintf(str, "%x", *(uint32_t *)readingreg);
If your machine is little endian you'll have to swap the byte order:
char str[9];
uint32_t host;
host = htonl(*(uint32_t *)readingreg);
sprintf(str, "%x", host);
If portability is a concern, you should use method two regardless of your endianness.
I get the following output:
printf("0x%s\n", str);
0x4aaaaaa0
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.