C language USES openSSL library AES module to achieve encryption function

  • 2020-05-19 05:26:23
  • OfStack

This article illustrates an example of how the C language implements encryption using the openSSL library AES module. I will share it with you for your reference as follows:

An overview of the

In cryptography, 1 has 3 categories:

1. Symmetric encryption/decryption

Common examples of symmetric encryption are DES/AES. The encryption party and the decryption party both hold the same key. Symmetry means that both encryption and decryption use the same key.

2. Asymmetric encryption/decryption

Common encryption algorithms DSA/RSA. If you have done Google Pay, you will be familiar with it. Asymmetric means that the encryption and decryption keys are not the same. This kind of application needs to maintain the authority of the initiator. For example, in the case of a payment in Google, only Google can encrypt the output through the private key, but everyone can verify that this is true through the public key. A more obvious analogy is that the private key can be understood as the federal reserve's money-printing machine, and the public key can be understood as the countless private dollar detectors.

Another example is when https logs in with a certificate, using the two-way asymmetric encryption mode.

3. The discrete

This can only be called checkout, not encryption. Because such algorithms can only go in one direction (discrete input data to a specific number, reverse decryption is not possible). . The most common algorithm is MD5. This check sign is heavily used for authentication when writing php. He can discretize a string into the hexadecimal digits of 32byte.

This time, AES CBC is used for encryption. CBC mode encryption is the communication standard of SSL, so it is often used when playing games. Basic usage of openSSL can be referred to this

Two details

This encryption requires two details:

1. Encrypted memory block 1 is normally aligned to 16 bytes (this can also be adjusted); When the original memory block does not align the number of bytes, it needs to be filled.

2. Encryption and decryption will not cause expansion or shrinkage of the memory;

Recently, I have been using Python,Java,c# to check the interface of AES. The easiest one is c#,java. When written using C, it becomes apparent how many memory allocations and how many memory mosaics are involved in these operations. Everything has a cost, and the lost efficiency of a well-encapsulated language may come from these conveniences.

Prepare knowledge

The function interface


int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
//  Set the encryption key
AES_KEY aes;
AES_set_encrypt_key(key,128,&aes);//  I filled in here 128 is bit position 128bit=(128/8)bytes=16bytes This is the sum 32bit The corresponding int For the memory pointer principle 1 The sample. 
//  Initialize your own key
char key[16];
//  Encryption function 
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc);
# define AES_BLOCK_SIZE 16 // aes.h 71 lines
# define AES_ENCRYPT   1 // aes.h 63 lines
# define AES_DECRYPT   0 // aes.h 64 lines
//  define 1 Two encrypted initialization vectors 
unsigned char iv[AES_BLOCK_SIZE];
//  encryption 
AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_ENCRYPT);
//  decryption 
AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_DECRYPT);

String conversion


// 16 The base string is converted to 16byte stored 
// hex string to byte in c
const char hexstring[] = "deadbeef10203040b00b1e50", *pos = hexstring;
unsigned char val[12];
size_t count = 0;
/* WARNING: no sanitization or error-checking whatsoever */
for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) {
    sscanf(pos, "%2hhx", &val[count]);
    pos += 2;
}
printf("0x");
for(count = 0; count < sizeof(val)/sizeof(val[0]); count++)
    printf("%02x", val[count]);
printf("\n");

padding algorithm


char *raw_buf = ...;
int raw_size = ...;
char *final_buf = NULL;
int pidding_size = AES_BLOCK_SIZE - (raw_size % AES_BLOCK_SIZE);
int i;
final_buf = (char *)malloc(raw_size+pidding_size);
if (pidding_size!=0) {
    memcpy( final_buf, raw_buf, raw_size);
    for (i =raw_size;i < (raw_size+pidding_size); i++ ) {
      // zero padding Algorithm: 
      final_buf[i] = 0;
      or
      // PKCS5Padding algorithm 
      final_buf[i] = pading;
    }
}

Complete code

c language code


// main.c
#include <aes.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
unsigned char* str2hex(char *str) {
    unsigned char *ret = NULL;
    int str_len = strlen(str);
    int i = 0;
    assert((str_len%2) == 0);
    ret = (char *)malloc(str_len/2);
    for (i =0;i < str_len; i = i+2 ) {
        sscanf(str+i,"%2hhx",&ret[i/2]);
    }
    return ret;
}
char *padding_buf(char *buf,int size, int *final_size) {
    char *ret = NULL;
    int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE);
    int i;
    *final_size = size + pidding_size;
    ret = (char *)malloc(size+pidding_size);
    memcpy( ret, buf, size);
    if (pidding_size!=0) {
        for (i =size;i < (size+pidding_size); i++ ) {
            ret[i] = 0;
        }
    }
    return ret;
}
void printf_buff(char *buff,int size) {
    int i = 0;
    for (i=0;i<size;i ++ ) {
        printf( "%02X ", (unsigned char)buff[i] );
        if ((i+1) % 8 == 0) {
            printf("\n");
        }
    }
    printf("\n\n\n\n");
}
void encrpyt_buf(char *raw_buf, char **encrpy_buf, int len ) {
    AES_KEY aes;
    unsigned char *key = str2hex("8cc72b05705d5c46f412af8cbed55aad");
    unsigned char *iv = str2hex("667b02a85c61c786def4521b060265e8");
    AES_set_encrypt_key(key,128,&aes);
    AES_cbc_encrypt(raw_buf,*encrpy_buf,len,&aes,iv,AES_ENCRYPT);
    free(key);
    free(iv);
}
void decrpyt_buf(char *raw_buf, char **encrpy_buf, int len ) {
    AES_KEY aes;
    unsigned char *key = str2hex("8cc72b05705d5c46f412af8cbed55aad");
    unsigned char *iv = str2hex("667b02a85c61c786def4521b060265e8");
    AES_set_decrypt_key(key,128,&aes);
    AES_cbc_encrypt(raw_buf,*encrpy_buf,len,&aes,iv,AES_DECRYPT);
    free(key);
    free(iv);
}
int main(int argn, char *argv[] ) {
    char *raw_buf = NULL;
    char *after_padding_buf = NULL;
    int padding_size = 0;
    char *encrypt_buf = NULL;
    char *decrypt_buf = NULL;
    // 1
    raw_buf = (char *)malloc(17);
    memcpy(raw_buf,"life's a struggle",17);
    printf("------------------raw_buf\n");
    printf_buff(raw_buf,17);
    // 2
    after_padding_buf = padding_buf(raw_buf,17,&padding_size);
    printf("------------------after_padding_buf\n");
    printf_buff(after_padding_buf,padding_size);
    // 3
    encrypt_buf = (char *)malloc(padding_size);
    encrpyt_buf(after_padding_buf,&encrypt_buf, padding_size);
    printf("------------------encrypt_buf\n");
    printf_buff(encrypt_buf,padding_size);
    // 4
    decrypt_buf = (char *)malloc(padding_size);
    decrpyt_buf(encrypt_buf,&decrypt_buf,padding_size);
    printf("------------------decrypt_buf\n");
    printf_buff(decrypt_buf,padding_size);
    free(raw_buf);
    free(after_padding_buf);
    free(encrypt_buf);
    free(decrypt_buf);
    return 0;
}

Compile the scons script:


# SConstruct
import glob
env = Environment()
env["CPPPATH"] = [ '/usr/include/openssl' ]
env['LIBPATH'] = [ '/home/abel/lib/openssl-1.0.2f' ]
env['CPPDEFINES'] = ['LINUX', '_DEBUG' ]
env['CCFLAGS'] = '-g -std=gnu99'
env['LIBS'] = [ 'm', 'crypto', 'dl' ]
env.Program( target = "./test_aes", source = ( glob.glob( './*.c' ) ) )

Output results:


:!./test_aes
------------------raw_buf
6C 69 66 65 27 73 20 61
20 73 74 72 75 67 67 6C
65

------------------after_padding_buf
6C 69 66 65 27 73 20 61
20 73 74 72 75 67 67 6C
65 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

------------------encrypt_buf
DB 63 28 C5 2C 6A 3F 1B
FD 4B C5 47 94 4E 24 9D
D2 15 4C F2 6B 3B 1D C0
E7 D2 7B D6 1E 78 60 EA

------------------decrypt_buf
6C 69 66 65 27 73 20 61
20 73 74 72 75 67 67 6C
65 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

conclusion

There are still a lot of places in the code that are directly out of malloc memory, and the dots can be clipped more tightly. The IV memory will change with each encryption call.

PS: about encryption and decryption interested friends can also refer to the website online tools:

Text online encryption and decryption tools (including AES, DES, RC4, etc.) :
http://tools.ofstack.com/password/txt_encode

MD5 online encryption tool:
http://tools.ofstack.com/password/CreateMD5Password

Online hash/hash algorithm encryption tool:
http://tools.ofstack.com/password/hash_encrypt

MD5/hash/ SHA-1 / SHA-2 / SHA-256 / SHA-512 / SHA-3 / RIPEMD-160 encryption tools:
http://tools.ofstack.com/password/hash_md5_sha

Online sha1 sha224 / sha256 sha384 / sha512 encryption tools:
http://tools.ofstack.com/password/sha_encode

I hope this article has been helpful to you in the programming of C language.


Related articles: