admin管理员组文章数量:1639675
参照<<密码学引论>> 第二版 张焕国 王张宜编著这本书,用MFC编写的框架,实现的使用3DES对文件进行加解密的程序
转载请说明来源 : enjoy5512的博客 http://blog.csdn/enjoy5512
DES加密算法简介
1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式数据加密标准(DESData Encryption Standard) 。
目前在国内,随着三金工程尤其是金卡工程的启动,DES算法在POS、ATM、磁卡及智能卡(IC卡)、加油站、高速公路收费站等领域被广泛应用,以此来实现关键数据的保密,如信用卡持卡人的PIN的加密传输,IC卡与POS间的双向认证、金融交易数据包的MAC校验等,均用到DES算法。
DES算法的入口参数有三个:Key、Data、Mode。
其中Key为8个字节共64位,是DES算法的工作密钥;
Data也为8个字节64位,是要被加密或被解密的数据;
Mode为DES的工作方式,有两种:加密或解密。
DES算法是这样工作的:
如Mode为加密,则用Key 去把数据Data进行加密, 生成Data的密码形式(64位)作为DES的输出结果;
如Mode为解密,则用Key去把密码形式的数据Data解密,还原为Data的明码形式(64位)作为DES的输出结果。
在通信网络的两端,双方约定一致的Key,在通信的源点用Key对核心数据进行DES加密,然后以密码形式在公共通信网(如电话网)中传输到通信网络的终点,数据到达目的地后,用同样的Key对密码数据进行解密,便再现了明码形式的核心数据。这样,便保证了核心数据(如PIN、MAC等)在公共通信网中传输的安全性和可靠性。
通过定期在通信网络的源端和目的端同时改用新的Key,便能更进一步提高数据的保密性,这正是现在金融交易网络的流行做法。
3DES简介
3DES是DES加密算法的一种模式,它使用3条64位的密钥对数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法。
3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。
设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代表密表,这样,
3DES加密过程为:C=Ek3(Dk2(Ek1(P)))
3DES解密过程为:P=Dk1((EK2(Dk3(C)))
K1、K2、K3决定了算法的安全性,若三个密钥互不相同,本质上就相当于用一个长为168位的密钥进行加密。多年来,它在对付强力攻击时是比较安全的。若数据对安全性要求不那么高,K1可以等于K3。在这种情况下,密钥的有效长度为112位
3DES加密流程图
子密钥产生
16轮加密
3DES加解密
代码实现
(所有源码在我的github上可以得到github/whu-enjoy/3DES)
因为注释挺详细了,这里就不细说
下面是我作的一个函数调用图
其中对八字节的数据,调用EncryptBlock()三次
加密
解密
我的密钥一跟密钥三用的一样的
加解密的类的实现
/////////////////////////////////////////////////////////////////////////////
// DES class used for Encrypt/Decrypt
class DES : public CDialog{
public:
//公共静态成员数组
static int s_ia56PC_1[56]; //子密钥产生算法中的PC1矩阵
static int s_ia16MoveTimes[16]; //子密钥产生算法中的左移次数表
static int s_ia48PC_2[48]; //子密钥产生算法中的PC2矩阵
static int s_ia64IP[64]; //加密算法中的初始置换IP矩阵
static int s_ia48E[48]; //加密算法中的扩展置换E矩阵
static int s_ia8_4_16S_Box[8][4][16]; //加密算法中的S盒
static int s_ia32P[32]; //加密算法中的P矩阵
static int s_ia64IP_1[64]; //加密算法中的逆初始置换IP^-1矩阵
int ia2_16_48K[2][16][48]; //子密钥
public:
//程序说明开始
//==================================================================================
// 功能 : 将输入的无符号字符数组转化为相应的二进制,转换c_iCount个字节
// 参数 : const unsigned char c_ucaByte[], int iaBin[], const int c_iCount
// (入口) c_ucaByte : 需要转换的无符号字符数组
// c_iCount : 需要转换的字节数
// (出口) iaBin : 转换后的二进制流,用整型数组保存结果
// 返回 : 无
// 主要思路 : 对每个字节循环八次,第j次循环左移j次,再将最高位提取出来,就能获取这个
// 字节的八位上的所有数据
// 调用举例 : unsigned char uca5Pwd[5] = "test";
// int ia32Bin[32];
// ByteToBin(uca5Pwd, ia32Bin, 4);
// 日期 : 2016年5月30日 19:17:10(注释日期)
//==================================================================================
//程序说明结束
void ByteToBin(const unsigned char c_ucaByte[], int iaBin[], const int c_iCount)
{
int i = 0;
int j = 0;
//循环转化c_iCount个字节
for ( i = 0; i < c_iCount; i++)
{
for(j = 0; j < 8; j++)
{
//第j次循环时,左移j次,再检查最高位是否是1,如果是,则赋值为1,否则赋值为0
if (0x80 == ((c_ucaByte[i]<<j)&0x80))
{
iaBin[i*8+j] = 1;
}
else
{
iaBin[i*8+j] = 0;
}
}
}
}
//程序说明开始
//==================================================================================
// 功能 : 将输入的二进制转化为相应的无符号字符数组,转换c_iCount个字节
// 参数 : const int c_iaBin[], unsigned char ucaByte[], const int c_iCount
// (入口) c_iaBin : 需要转换的二进制流
// c_iCount : 需要转换的字节数
// (出口) ucaByte : 转换后的无符号字符数组
// 返回 : 无
// 主要思路 : 对每个字节循环八次,第j次循环将原来的值左移一位,并将新的值加到最低位
// 调用举例 : unsigned char uca5Pwd[5] = "";
// int ia32Bin[32] = {0,0,1,1,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,1,0,0};
// BinToByte(ia32Bin, uca5Pwd, 4);
// 日期 : 2016年5月30日 19:24:25(注释日期)
//==================================================================================
//程序说明结束
void BinToByte(const int c_iaBin[], unsigned char ucaByte[], const int c_iCount)
{
int i = 0;
int j = 0;
//转换c_iCount个字节
for ( i = 0; i < c_iCount; i++)
{
for(j = 0; j < 8; j++)
{
//每次将原来的值左移一位,并加上新提取的
ucaByte[i] = ucaByte[i] * 2 + c_iaBin[i*8+j];
}
}
}
//程序说明开始
//==================================================================================
// 功能 : 根据输入的第二个矩阵将第一个矩阵进行转换,转换的结果保存在第三个矩阵里,
// 转换c_iCount个数据
// 参数 : const int c_iaSource[], const int c_iaReplaceTable[]
// int iaReplaced[], const int c_iCount
// (入口) c_iaSource : 需要转换的矩阵
// c_iaDisplaceTable : 转换参考矩阵
// c_iCount : 需要转换的数据个数
// (出口) iaReplaced : 转换后的矩阵
// 返回 : 无
// 主要思路 : iaReplaced矩阵的第i个位置上的数是c_iaSource矩阵中
// 第c_iaReplaceTable[i]个位置的数据
// 调用举例 : int ia64Source[64] = {xxxxx};
// int ia48Replace[48] = {xxxx};
// int ia48Replaced[48] = {0};
// Replacement(ia64Source, ia48Replace, ia48Replaced, 48);
// 日期 : 2016年5月30日 19:39:24(注释日期)
//==================================================================================
//程序说明结束
void Replacement(const int c_iaSource[], const int c_iaReplaceTable[], int iaReplaced[], const int c_iCount)
{
int i = 0;
//循环c_iCount次
for (i = 0; i < c_iCount; i++)
{
//根据c_iaReplaceTable[]置换原表
iaReplaced[i] = c_iaSource[c_iaReplaceTable[i]-1];
}
}
//程序说明开始
//==================================================================================
// 功能 : 将输入矩阵里面的数据左移c_iCount次,用ia28Output保存左移后的结果
// 参数 : const int c_ia28Input[28], int ia28Output[28], const int c_iCount
// (入口) c_ia28Input : 需要左移的数组
// c_iCount : 需要左移的数据个数
// (出口) ia28Output : 左移后的数组
// 返回 : 无
// 主要思路 : 先将原数组前c_iCount个数据保存在局部变量i2Temp中,然后输出数组的
// 前28-c_iCount数据左移c_iCount位,再将i2Temp中的数据接到输出数组中
// 这样做的时候,输入数组盒输出数组可以是同一个数组,减少内存空间使用量
// 调用举例 : int ia28C[28] = {xxxxx};
// LeftMove(ia28C, ia28C, 2);
// 日期 : 2016年5月30日 19:49:46(注释日期)
//==================================================================================
版权声明:本文标题:3DES文件加密程序 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1729293295a1194430.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论