对称加密--(cbc)DES原理及完整源码

前言

在csdn上找了几份关于des的源码,要么不支持cbc要么转换出来结果不对(观看源码大多是填补的方式不同,多样)。所以自己用c写了一个支持大数据的cbc-des库。
使用时候修改.h,进行裁剪,在文件里放入明文就行了。亲测可行,链接https://download.csdn.net/download/qq_35651984/12447007

/*
======================SIMPLE_DES======================
------------------------------------------------------
----------------------vision:1.0----------------------
----------------------edtor:川大门口贴膜小哥 ----------
----------------------time:19/4/10--------------------
功能(1.0):
      支持des的cbc,ecb模式
	  支持大数据加密(文件操作)
	  支持十进制字符和十六进制字符的加密输出/解密输入
操作流程:
      配置#define
      DES_Contr con;
	  DES_Init(&con);
	  DES_EN_File(&con);
	  DES_DE_File(&con);
注意事项:
      使用文件加密/解密时候,需在当前目录创建需要加密/解密的文件
	  DES_EN_File( )--->  EN.txt---加密---DE.txt
	  DES_DE_File( )--->  DE.txt---解密---EN2.txt
*/
#define DES_MODE CBC  //CBC OR ECB
#define OUTPUT_MODE  16//16 OR 10  10:10_ENTO_10,10_DETO_10,16:10_ENTO_16,16_DETO_10
#define _IV  "\0\0\0\0\0\0\0\0"//CBC模式下偏移量
#define _KEY  "12345678"  //key
typedef struct st
{
	int  	status;//控制器状态
	char    subkey[16][64];//子密钥
	char    en_again[8];//加密时候,上一分组加密数据
	char    de_again[8];//解密时候,上一分组解密数据
}DES_Contr;
//PUBLIC API
int DES_Init(DES_Contr  *des_contr);
int DES_EN_File(DES_Contr *con);//大数据加密
int DES_DE_File(DES_Contr *con);//大数据解密
int DES_EN(DES_Contr *des_contr,char data[8],char en_data[8]);//一个分组加密,data:输入,endata:输出密文
int DES_DE(DES_Contr *des_contr,char data[8], char de_data[8]);//一个分组解密,data:输入密文,endata:输出明文

DES 原理

一输入输出

加密:
输入: 一组不定长n的明文
输入:8字节的key
可选输入:模式,IV,填充方式等
输出:一组不定长n+i (i<=8,n+i能被8整除)的密文
解密:
同理,输入一组不定长n+i (i<=8,n+i能被8整除)的密文,输出 一组不定长n的明文

二 运算步骤

des分为三个步骤:

一:密钥步骤

首先通过一个8字节的密钥生成16个48字节的子密钥。(本质上是64位密钥生成16个48位的子密钥,我程序中将bit转换位字符利于计算)

二:整体步骤

将一个不定长的明文,填充一定的字节(小于9字节),使其能够被8字节整除。每8字节为一个分组,每一个分组运行一次分组步骤。(在ecb模式下,每个分组相互独立运算,互不影响。而cbc模式也叫密文分组链接方式,相互分组有联系,一个分组出错,则后面全部运算错误)
所以cbc模式下在整体步骤中会多一个分组链接的功能,具体实现方式:
加密:明文分组N(n>1)与上一个密文分组N-1进行异或后,替代明文分组N,N再进行加密。
解密:解密后得到明文N(n>1),与上一个密文分组N-1进行异或后,替代明文分组N。
当N=1时:与IV进行异或,IV基本都时"\0\0\0\0\0\0\0\0",异或后等于分组1本身

三:分组步骤

分组步骤是des算法的核心,也就是通过置换,迭代,移位等操作,输入8字节数据,输出8字节密文

具体运算步骤

具体运算步骤我就不重复造轮子了,可以参考此处参考博文

移位

const int MOV[16] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };

通过MOV表左移一位或者两位获得16个子密钥

扩展/替换
const int PC_2[56] = { 13,16,10,23,0,4,2,27,
14,5,20,9,22,18,11,3,
25,7,15,6,26,19,12,1,
40,51,30,36,46,54,29,39,
50,44,32,47,43,48,38,55,
33,52,45,41,49,35,28,31 };
const int IP[64] = { 57,49,41,33,25,17,9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7,
56,48,40,32,24,16,8,0,
58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6 };

通过pc,ip,e,s盒等,替换对应位的数据,如48位扩展为64位,48位替换为32位。

异或

在分组链接和f()函数中均有异或操作

		for (int i = 0; i < 8; i++)
		{
			de_buffer[i] = de_buffer[i] ^ con->de_again[i];
		}

填充方式

填充方式也就是补齐为8字节该怎么填充。

Zero padding

网上找的源码大多都错在这里,Zero padding是在后面填充0,但不确定正确数据后面是否有零,删除填充时候,误删正确数据。

PKCS5Padding

也有的错在这里,填充填充的长度。如“abc”填充“abc55555”,但填充的是‘5’是错误的,正确的填充方式是“abc\5\5\5\5\5”.

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工农村贴膜小哥

我倒是要看看是那个憨憨在给我打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值