DES加密算法及其openssl实现

DES加密算法及其openssl实现

目前的密码算法按有无密钥可分为无密钥密码和有密钥密码,无密钥密码主要是hash函数和消息摘要等,而有密钥密码又分为对称密码和非对称密码,也称私钥密码和公钥密码,像RSA算法就属于公钥密码体制,而私钥密码中最重要的一个部分就是分组密码。

分组密码

对于一个明文,我们要将其加密为密文,由于明文长度不确定,所以用一个确定的算法直接加密全部明文是不现实的,所以我们将一个任意的明文分为若干个长度为b个比特的明文块,这样就可以用一个确定的标准化算法对各个明文块进行加密进而实现对全部明文的加密,当明文长度不是分组长度b的整数倍时有一些补充的方案,本文主要讨论DES,所以不予介绍。
对于分组长度为b的分组密码,每个分组经过加密输出的密文一般也是b个比特,而密钥为t比特,t可以等于或小于b。因为明文和密文都是长为b比特的01数据流,将其看做向量则易知明文空间与密文空间是相同的,密文和明文是一个置换的关系。相同的明文一定会加密成相同的密文,而不同的密文一定会解密成不同的明文(否则无法确定真实的明文值)
分组密码的设计原则:
1.扩散:使明文中的每一位影响密文中的许多位,即密文中的一位受明文的许多位影响,也使密钥中的每一位影响密文的多位,防止对密钥的逐字段破译。也使得密文 中的每一位与尽可能多的明文,密钥相关联,也使当改变明文或 密钥的一位会改 变密文的多位。
2.混淆:消除统计特性,使明文密钥与密文的依赖关系变得尽可能的复杂,复杂的非线性代替变换会产生较好的混淆效果。
实现扩散与混淆的基本操作是permutation(排列)和substitution(替换)

DES加密算法

0.历史

1973年美国国家标准局(NBS,现在的美国国家标准和技术协会NIST)开始征集用于政府部门和民间的密码算法,IBM公司提出了Lucifer加密算法,1977年被正式批准,即为DES(data encryption standard)算法,在算法提出早期,NBS估计要花费七千万美元,以及耗费大量的能量。在整个70年代和80年代,DES未被攻破,1994年Matsui第一次恢复了一个DES密钥,用了40天。1997年通过网络进行并行计算恢复了密钥,1998年电子边境基金会(EFF)使用25万美元的计算机在56小时内破译了EDS,1999年EFF仅用22小时就破译了DES。在1998年NBS宣布不再使用DES作为今后的加密标准。

1.feistel结构

feistel结构是使用比较广泛的密码结构之一,是一个多轮加密的算法,流程如下图,首先要被加密的明文首先被分成左右两块,右边的块直接作为下一轮的左边输入,同时我们将右边的块使用一个有轮密钥(由原始密钥经过一个密钥编排的过程生成一系列的子密钥)的轮函数进行处理,将得到的结果与上一轮(若是第一轮则是明文)左边的输入进行一个异或操作,得到的结果作为下一轮的右边输入。这就是feistel的一轮的操作,算法进行r轮,到最后一轮将左右两部分再合并起来得到密文。值得注意的是,在最后一轮得到左右两边的值之后我们不对其进行左右交换的操作,这样是为了方便使用同一结构进行解密。Feistel结构的解密过程与加密过程相同,只是使用轮密钥的顺序不同而已,从图上看,我们可以看到它是上下对称的。

2.DES整体流程

DES加密算法使用的是feistel结构,下面我们对DES的细节进行介绍。
首先,DES的分组长度是64比特,加密后得到的密文也是64比特,密钥长度为64比特,但在密钥的64个比特中,只有56位是有效的,密钥中每7个有效密钥比特后会加一位校验值,即64个比特中的第8,16…64位是校验位而不是用户选取的真实密钥值,即实际的密钥长度只有56比特。
DES的流程图如下在这里插入图片描述
对于一个64比特的明文,首先我们将其进行一个IP置换,置换表如下,表中第一位58的意思是将明文的第58位挪到第1位,将第50位挪到第2位,以此类推即可将64比特的明文进行一个置换,在生成密文之前又做了一个IP的逆置换。由于IP置换是一个线性的变换,所以其在密码安全方面的贡献很小,仅仅起到了一个打乱明文的作用,几乎没有提高安全性的作用,主要用于硬件设备。
在这里插入图片描述
在经过IP置换后明文数据被分为左右两部分,右半部分(32比特)会经过一个轮函数,DES的轮函数中包括E扩展,轮密钥加,S-盒,P置换四个过程,下面我们详细介绍这四个过程。

3.轮函数

(1)E扩展
E的操作是将一个32比特的数据扩展成48比特,具体操作如下表,可以看到E表示一个6*8的表,共48位。将输入数据的第32位作为输出数据的第1位,以此类推。
在这里插入图片描述
(2)密钥加
32比特数据经过E后被扩展成48比特数据,然后将其与48比特的轮密钥进行简单的模加,其中轮密钥由原始密钥生成,后文介绍。

(3)S-盒
S-盒是DES中唯一的非线性结构,是DES算法安全性的保障,同时也是很多其他算法安全性的保障,S-盒有很多种,DES的S-盒是一个6进4出的盒,即输入数据为6比特,输出数据为4比特,S-盒的结构如下(这里是DES的第五个S-盒的结构):

在这里插入图片描述
对于一个输入到S-盒的6比特数据,我们记其为b1,b2,b3,b4,b5,b6,我们将b1和b6组合起来成为一个2个比特的二进制数据,对应一个小于4的十进制数,将这个数作为S-盒结构的行标,将剩下的b2,b3,b4,b5看做是一个4个比特的二进制数,对应一个十六进制数,将其作为S-盒结构的列标,这样就确定了S-盒结构中的一个十六进制的数,即一个4比特的数据,即为输出。例如,对于一个输入数据110111,其输出应该是盒中行标为11列标为1011的数据,即p3行的b列,对应十六进制数9,所以输出为1001。这样就实现了输入6比特的数输出4比特的数的过程。
由此,经过与轮密钥模加的48比特数据会被分成8个部分,每部分6长为比特,这8部分会分别经过8个不同的S-盒编程8个长为4比特的数据,然后再合并起来得到一个长度为32比特的数据。
值得说明的是,尽管S-盒中的数有很多可选择的方式,但研究表明,DES中的S-盒的排列和内容是经过了精心的设计的,对其进行任何改动都会使DES的安全性下降,而S-盒的全部设计准则至今未被公开。下图为DES的全部8个S-盒的结构。
在这里插入图片描述

(4)P置换
P置换即是将S-盒输出的32比特数据进行一个重新排列,置换表如下
在这里插入图片描述
研究表明,S-盒,E扩展,P置换过程都可以有效的抵抗差分攻击和线性攻击,而民间在90年代才提出了差分攻击(这是一类很有效的攻击),可以看出DES的设计者的技术是非常高的,下图是DES算法的轮函数的示意图。
在这里插入图片描述

4.轮密钥的生成

次过程又叫密钥编排,主要介绍DES算法是如何从用户提供的64比特(实际只有56位是有效的)密钥中得到16个轮密钥的,其生成方式如下图:
在这里插入图片描述
(1)PC1
PC1是一个将64比特数据进行挑选并重新排列的过程,PC1的表格在上图中已经给出,
可以看到其是一个8乘7的表,共56个值,这些值中没有8,16等8的倍数的值,因为在原始的64比特的密钥中这些位是校验位,并不是真正的密钥。在经过PC1过程后得到一个56比特的数据,然后将其分为左右两部分,每部分28比特。

(2)行移位
将数据进行循环左移位,具体移位的多少与加密轮数有关,见上图的最后一个表,需要
说明的是这些移位是要叠加的,即第二轮移位是在第一轮移了1位的基础上再移一位,可知一共移位了28次,正好是一个周期。左移时有时移1位有时移2位是为了避免出现大量相同的子密钥。

(3)PC2
在进行左移之后将两部分数据混合起来,在使用PC2的表进行一个置换,即得到了48比特的轮密钥。

在实际操作中,往往使用直接查表而不是计算的方法得到轮密钥,密钥-轮密钥的表如下:
在这里插入图片描述

5.3-DES

DES从发布至今,结构上未发现有明显的安全问题,攻击DES最有效的算法仍然是穷举攻击及其变种。但DES有一个致命的缺陷就是其密钥长度太短,对于现今的计算水平来说穷举攻击恢复DES的56比特长的密钥是比较容易的。所以人们基于DES算法又提出了加强安全性的算法:3-DES,最常用的3-DES模式为:,即使用两个DES密钥,先使用k1进行一次加密,然后使用k2进行解密,再用k1加密,可以看到当k1=k2时3-DES即变为普通的DES算法,转化比较方便。但3-DES相比于DES的缺点就是其效率较低。

以上就是DES的加密流程下面介绍DES的计算机实现

ECB:电子密码本模式,就是将数据按照8个字节一段进行DES加密或解密得到一段段的8个字节的密文或者明文,最后一段不足8个字节(一般补0或者F),按照需求补足8个字节进行计算(并行计算),之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
CBC:
1) 首先将数据按照8个字节一组进行分组得到D1D2…Dn(若数据不是8的整数倍,用指定的PADDING数据补位)
2) 第一组数据D1与初始化向量IV异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)
3) 第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
4) 之后的数据以此类推,得到Cn
5) 按顺序连为C1C2C3…Cn即为加密结果。

DES的ECB模式写法简单,安全性低,所以介绍一下CBC模式。
DES的CBC模式写法:
1.首先创建一个key;这个key 的类型是DES_cblock,这是一个openssl自定义的结构。在头文件中的typedef unsigned char DES_cblock[8]; 可以看出DES_cblock 是一个存储8个字符的char数组。
2.然后创建一个DES_key_schedule,这是个结构体,大概的意思就是加密/解密的计划。也就是理论中的大密钥分解成16个小密钥的过程。这个过程使用 DES_set_key_checked(&key, &key_schedule) 函数
在这里插入图片描述

上图是源码中DES_key_schedule结构体的定义,可以看出它是一个union类型的数组,该数组是DES_cblock或者是error。
3.创建一个临时变量,这个变量的类型是DES_cblock。并将这个变量初始化一下,赋值成0x0000000000000000。对应代码如下。

在这里插入图片描述

4.加密。加密函数调用
DES_ncbc_encrypt(input, output, sizeof(input), &key_schedule, &ivec,1);
第一个参数是加密的字符串,第二个参数是输出的字符串,第三个参数是输入字符串的字节数,第四个是刚才生成的计划,第五个是临时变量,第六个是一个参数,1代表加密,0代表解密。
5.解密
DES_ncbc_encrypt(output, input, len, &key_schedule, &ivec, 0);
加解密调用的是同一个函数,但是函数的最后一个参数是0。
代码结果截图:
两次password相同:
在这里插入图片描述

两次password不相同:会输出乱码
在这里插入图片描述

下面是openssl中的代码

//
//  main.c
//  des
//
//  Created by 文昊代 on 2018/1/23.
//  Copyright © 2018年 文昊代. All rights reserved.
//

#include <openssl/des.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
    unsigned char *keystring =malloc(100*sizeof(char));//分配空间
    DES_cblock key;
    DES_key_schedule key_schedule;
    printf("输入password\n");
    scanf("%s",keystring);
    //生成一个key
    DES_string_to_key(keystring, &key);
    //判断生成key_schedule是否成功
    if (DES_set_key_checked(&key, &key_schedule) != 0) {
        printf("key_schedule failed.\n");
        return -1;
    }
    printf("输入要加密的信息\n");
    //需要加密的字符串
    unsigned char input[100];
    scanf("%s",input);
    size_t len = (sizeof(input)+7)/8 * 8;
    unsigned char *output = malloc(len+1);
    //配置函数参数
    DES_cblock ivec;
    
    //IV设置为0x0000000000000000
    memset((char*)&ivec, 0, sizeof(ivec));
    
    //加密
    DES_ncbc_encrypt(input, output, sizeof(input), &key_schedule, &ivec, DES_ENCRYPT);//DES_ENCRYPT代表1,表示加密
    
    //输出加密以后的内容
    printf("加密后的结果是:");
    for (int i = 0; i < len; ++i)
        printf("%02x", output[i]);
   // printf("\n%d,%d,%d",len,strlen(output),strlen(input));//不用管这一句话
    printf("\n");
    
    
    //进行解密
    DES_cblock key1;
    printf("请再次输入password\n");
    scanf("%s",keystring);
    //生成一个key
    DES_string_to_key(keystring, &key);
    //判断生成key_schedule是否成功
    if (DES_set_key_checked(&key, &key_schedule) != 0) {
        printf("key_schedule failed.\n");
        return -1;
    }
    
    //IV设置为0x0000000000000000
    memset((char*)&ivec, 0, sizeof(ivec));
    //解密
    DES_ncbc_encrypt(output, input, len, &key_schedule, &ivec, 0);
    
    printf("解密后的结果是:%s\n", input);
    
    free(output);
    return EXIT_SUCCESS;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值