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"里的加解密处理类型即可;
示例代码:
****************************************************************************************
"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"里的加解密处理类型即可;
相关文章推荐
- C语言:基于OpenSSL-RSA实现RSA非对称加解密
- Rob Hess的SIFT算法的C语言实现(基于OpenCV)
- 基于C语言的内存池的设计与实现
- 基于POSIX在Linux下C语言实现读取整个目录文件[Get a List of Files in a Directory with C]
- 基于C语言与原始套接字实现Ping程序
- 基于OpenSSL简单实现Shamir基于身份的数字签名算法
- 基于C语言的内存池的设计与实现
- Openssl:构建CA的过程并实现web服务基于https访问的网络架构
- Rob Hess的SIFT算法的C语言实现(基于OpenCV)
- VC++网络安全编程范例(9)-基于OPENSSL实现对称算法与BASE64编码
- 基于OpenSSL安全会话的实现
- 编译Rob Hess基于OpenCV的SIFT算法的C语言实现
- 基于C语言实现的Ping程序
- 基于C语言实现的Ping程序
- Rob Hess的SIFT算法的C语言实现(基于OpenCV)
- 基于数组的队列实现(C语言)
- 基于文本比较的搜索 - C语言实现(有注释)
- 基于C语言实现的Ping程序
- C语言基于对象编程实现封装
- Openssl:构建CA的过程并实现web服务基于https访问的网络架构