您的位置:首页 > 编程语言 > C语言/C++

C语言:基于OpenSSL-EVP实现DES对称加解密

2017-03-27 00:00 281 查看
关于DES对称加密算法以及OpenSSL EVP相关介绍在此不做展开,直接进入主题,本篇以DES_CBC加密算法为例,具体DEMO源码如下:

示例代码:

****************************************************************************************

"des.c"

/* DES对称加解密 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>

/* DES_CBC加密
* 输入参数:key-密钥(8字节)|iv-算法向量(8字节)
* 返回:成功则返回密文长度,失败则直接中断 */
static int encryptDes( unsigned char *key, unsigned char *iv,
unsigned char *plain, unsigned char *cipher, int plen )
{
int clen = 0;
int tmplen = 0;
EVP_CIPHER_CTX ctx;

/* 01:加密初始化
* 使用DES_CBC算法加密 */
EVP_EncryptInit( &ctx, EVP_des_cbc(), key, iv );
/* 设置不填充(缺省填充) */
if( 0 == plen % 8 ){
EVP_CIPHER_CTX_set_padding( &ctx, 0 );
}

/* 02:加密 */
if( !EVP_EncryptUpdate( &ctx, cipher, &clen, plain, plen ) ){
ERR_print_errors_fp( stderr );
fprintf( stderr, "EVP_EncryptUpdate error\n" );
return EXIT_FAILURE;
}

/* 03:加密后处理 */
if( !EVP_EncryptFinal( &ctx, cipher + clen, &tmplen ) ){
ERR_print_errors_fp( stderr );
fprintf( stderr, "EVP_EncryptFinal error\n" );
return EXIT_FAILURE;
}
clen += tmplen;

return clen;
}

/* DES_CBC解密
* 输入参数:key-密钥(8字节)|iv-算法向量(8字节)
* 返回:成功则返回密文长度,失败则直接中断 */
static int decryptDes( unsigned char *key, unsigned char *iv,
unsigned char *cipher, unsigned char *plain, int clen )
{
int plen = 0;
int tmplen = 0;
EVP_CIPHER_CTX ctx;

/* 01:解密初始化,算法向量缺省NULL
* 使用DES_CBC算法解密 */
EVP_DecryptInit( &ctx, EVP_des_cbc(), key, iv );

/* 02:解密 */
if( !EVP_DecryptUpdate( &ctx, plain, &plen, cipher, clen ) ){
ERR_print_errors_fp( stderr );
fprintf( stderr, "EVP_DecryptUpdate error\n" );
return EXIT_FAILURE;
}
/* 设置不填充(缺省填充) */
if( 0 == plen % 8 ){
EVP_CIPHER_CTX_set_padding( &ctx, 0 );
plen += 8;
}

/* 03:解密后处理 */
if( !EVP_DecryptFinal( &ctx, plain + plen, &tmplen ) ){
ERR_print_errors_fp( stderr );
fprintf( stderr, "EVP_DecryptFinal error\n" );
return EXIT_FAILURE;
}
plen += tmplen;

return plen;
}

/* 测试程序
* 目标:解密出的明文和最初的明文一致证明功能实现
* 命令行参数:最初的明文 */
int main( int argc, char *argv[] )
{
int i = 0;
int plen = 0;
int clen = 0;
unsigned char key[] = "\x01\x02\x03\x04\x05\x06\x07\x08";
unsigned char iv[] = "\x00\x00\x00\x00\x00\x00\x00\x00";
unsigned char plain[1024 + 1] = {0};
unsigned char cipher[1024 + 1] = {0};

/* 依赖命令行参数输入 */
if( 1 == argc ){
fprintf( stderr, "Usage:[%s <buf>]\n", argv[0] );
exit( EXIT_FAILURE );
}

printf( "【初始明文】[%s]\n", argv[1] );

/* 01:公钥加密 */
clen = encryptDes( key, iv, argv[1], cipher, strlen( argv[1] ) );
/* LOOP:鉴于密文极有可能存在不可打印字符故而转十六进制输出 */
printf( "【加密密文】[" );
for( i = 0; i < clen; i ++ )
{
printf( "%02X", cipher[i] );
}
printf( "]\n" );

/* 02:私钥解密 */
plen = decryptDes( key, iv, cipher, plain, clen );
printf( "【解密明文】[%s]\n", plain );

exit( EXIT_SUCCESS );
}

****************************************************************************************

"Makefile"

#执行文件
bin=ides

#目标文件
objects=des.o

#连接规则
$(bin):$(objects)
gcc -o ~/bin/$(bin) $(objects) -lssl -lcrypto -ldl

#清理对象
.PHONY:clean
clean:
-rm ~/bin/$(bin) $(objects)

****************************************************************************************

验证效果:



【P.S.】说明:

代码中标红部分是针对明文长度为8的整数倍时设置不填充所做的特殊处理,若不做此处理则加密后的密文会因为缺省填充处理比明文多8字节;

如果需要使用DES_ECB/DES_CFB/DES_OFB或者3DES加密算法,只需要改动上述代码中"EVP_EncryptInit"以及"EVP_DecryptInit"里的加解密处理类型即可;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OpenSSL DES C