C语言使用openSSL库AES模块实现加密功能详解

 更新时间:2020年4月25日 17:31  点击:2350

本文实例讲述了C语言使用openSSL库AES模块实现加密功能。分享给大家供大家参考,具体如下:

概述

在密码学里面一共有3中分类:

1.对称加密/解密

对称加密比较常见的有DES/AES。加密方和解密方都持有相同的密钥。对称的意思就是加密和解密都是用相同的密钥。

2.非对称加密/解密

常见的加密算法DSA/RSA。如果做过Google Pay的话,应该不会陌生。非对称意味着加密和解密使用的密钥不是相同的。这种应用的场合是需要保持发起方的权威性,比如Google中一次支付行为,只能Google通过私钥来加密产出来,但是大家都能通过公钥来认证这个是真的。打个更加浅显的比方:私钥可以理解成美联储的印钞机,公钥可以理解成在民间无数的美元验钞机。

还有一个场合也是https使用证书方式登录的时候,也是使用的双向的非对称加密模式来做的。

3.离散

这种只能被称为验签,而不是加密。因为这类算法只能一个方向(将输入数据离散到某个特定的数字,反向解密是无法做到的。)。最常见的算法就是MD5。在写php的时候大量的使用这种验签来做认证。他可以将字符串离散成32byte的16进制的数字。

本次使用AES CBC方式来加密。CBC模式加密是SSL的通讯标准,所以在做游戏的时候经常会使用到。openSSL的基本用法可以参考这个

两个细节

这种加密的需要了解下面两个细节:

1.加密的内存块一般按照16字节(这个也可以调整)对齐;当原始内存块没有对齐字节数的时候,需要填充;

2.加密解密不会引发内存的膨胀或者缩小;

最近在使用Python,Java,c#都去看过AES的接口,最轻松的是c#,java。当使用C来写,才能明显感受到在这些操作过程中,有多少次内存的分配,多少的内存拼接。啥事都有成本,封装良好的语言损失掉的效率可能来自于这些便利。

准备知识

函数接口

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);
// 设置加密key
AES_KEY aes;
AES_set_encrypt_key(key,128,&aes);// 这里填写的128是bit位,128bit=(128/8)bytes=16bytes,这个换算和32bit对应int为内存指针的原理一样。
// 初始化自己的key
char key[16];
// 加密函数
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
// 定义一个加密的初始化向量
unsigned char iv[AES_BLOCK_SIZE];
// 加密
AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_ENCRYPT);
// 解密
AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_DECRYPT);

字串转换

// 16进制的字串转换成16byte存储起来
// 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算法

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算法:
      final_buf[i] = 0;
      or
      // PKCS5Padding算法
      final_buf[i] = pading;
    }
}

完整的代码

c语言代码

// 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;
}

编译scons脚本:

# 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' ) ) )

输出结果:

:!./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

总结

代码中还是有很多地方都是直接malloc内存出来,这些点都能扣得更加细。在每次加密调用的时候IV内存将会改变。

PS:关于加密解密感兴趣的朋友还可以参考本站在线工具:

文字在线加密解密工具(包含AES、DES、RC4等):
http://tools.jb51.net/password/txt_encode

MD5在线加密工具:
http://tools.jb51.net/password/CreateMD5Password

在线散列/哈希算法加密工具:
http://tools.jb51.net/password/hash_encrypt

在线MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools.jb51.net/password/hash_md5_sha

在线sha1/sha224/sha256/sha384/sha512加密工具:
http://tools.jb51.net/password/sha_encode

希望本文所述对大家C语言程序设计有所帮助。

[!--infotagslink--]

相关文章

  • C语言实现放烟花的程序

    这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
  • C语言中的字符(char)详细讲解

    本篇文章主要介绍C语言中char的知识,并附有代码实例,以便大家在学习的时候更好的理解,有需要的可以看一下...2020-04-25
  • 图解PHP使用Zend Guard 6.0加密方法教程

    有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
  • 详解如何将c语言文件打包成exe可执行程序

    这篇文章主要介绍了详解如何将c语言文件打包成exe可执行程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-25
  • C++中四种加密算法之AES源代码

    本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
  • vue接口请求加密实例

    这篇文章主要介绍了vue接口请求加密实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-12
  • C语言中free函数的使用详解

    free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
  • AES加密解密的例子小结

    关于AES加密的算法我们就不说了,这里主要给各位演示了三个关于AES算法实现的加密例子,希望本文章能给你带来帮助。 话不多说,先放上代码,一共有两个文件:AES.php(aes算...2016-11-25
  • C语言中计算正弦的相关函数总结

    这篇文章主要介绍了C语言中计算正弦的相关函数总结,包括正弦和双曲线正弦以及反正弦的函数,需要的朋友可以参考下...2020-04-25
  • 详解C语言中的rename()函数和remove()函数的使用方法

    这篇文章主要介绍了详解C语言中的rename()函数和remove()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
  • node.JS md5加密中文与php结果不一致怎么办

    这次文章要给大家介绍的是node.JS md5加密中文与php结果不一致怎么办,不知道具体解决办法的下面跟小编一起来看看。 因项目需要,需要Node.js与PHP做接口调用,发现nod...2017-07-06
  • C语言中求和、计算平均值、方差和标准差的实例

    这篇文章主要介绍了C语言中求和、计算平均值、方差和标准差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-10
  • NODE.JS加密模块CRYPTO常用方法介绍

    使用require('crypto')调用加密模块。加密模块需要底层系统提供OpenSSL的支持。它提供了一种安全凭证的封装方式,可以用于HTTPS安全网络以及普通HTTP连接。该模块还提供了一套针对OpenSSL的hash(哈希),hmac(密钥哈希),cipher...2014-06-07
  • C语言的基本语法详解

    本篇文章主要讲解C语言 基本语法,这里提供简单的示例和代码来详细讲解C语言的基本语法,开始学习C语言的朋友可以看一下,希望能够给你带来帮助...2021-09-18
  • C#连接加密的Sqlite数据库的方法

    对数据加密分两种,一种是对数据库本身进行加密,另一种是对数据表中的数据进行加密,下面通过本文给大家介绍C#连接加密的Sqlite数据库的方法,感兴趣的朋友一起看看吧...2020-06-25
  • C#实现对文件进行加密解密的方法

    这篇文章主要介绍了C#实现对文件进行加密解密的方法,涉及C#加密与解密的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C语言中send()函数和sendto()函数的使用方法

    这篇文章主要介绍了C语言中send()函数和sendto()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
  • php使用异或实现的加解密的方法

    若a=b ^ c;则b=a ^ c (^是异或的意思),php在处理异或的字符时先把字符转化为二进制的ascii值,对这些值进行异或,获取结果后在将ascii值转化为字符...2013-09-26
  • C语言实现从文件读入一个3*3数组,并计算每行的平均值

    今天小编就为大家分享一篇C语言实现从文件读入一个3*3数组,并计算每行的平均值,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
  • 使用C语言操作文件的基本函数整理

    这篇文章主要介绍了使用C语言操作文件的基本函数整理,包括创建和打开以及关闭文件的操作方法,需要的朋友可以参考下...2020-04-25