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

原创
2017/03/27 20:47
阅读数 2.7K

    关于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.】说明:

  1. 代码中标红部分是针对明文长度为8的整数倍时设置不填充所做的特殊处理,若不做此处理则加密后的密文会因为缺省填充处理比明文多8字节;
  2. 如果需要使用DES_ECB/DES_CFB/DES_OFB或者3DES加密算法,只需要改动上述代码中"EVP_EncryptInit"以及"EVP_DecryptInit"里的加解密处理类型即可;
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部