关于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"里的加解密处理类型即可;