欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DES加密算法

程序员文章站 2022-05-15 14:59:20
...

一、对称加密算法

网络安全通信中要用到两类密码算法,一类是对称密码算法,另一类是非对称密码算法。对称密码算法有时又叫传统密码算法、秘***算法或单**算法,非对称密码算法也叫公开**密码算法或双**算法。
对称加密的加***能够从解***中推算出来,同时解***也可以从加***中推算出来。而在大多数的对称算法中,加***和解***是相同的,所以也称这种加密算法为秘***算法或单**算法。它要求发送方和接收方在安全通信之前,商定一个**。对称算法的安全性依赖于**,泄漏**就意味着任何人都可以对他们发送或接收的消息解密,所以**的保密性对通信的安全性至关重要。
对称算法又可分为两类。一次只对明文中的单个位(有时对字节)运算的算法称为序列算法或序列密码。另一类算法是对明文的一组位进行运算,这些位组称为分组,相应的算法称为分组算法或分组密码。现代计算机密码算法的典型分组长度为64位――这个长度既考虑到分析破译密码的难度,又考虑到使用的方便性。后来,随着破译能力的发展,分组长度又提高到128位或更长。
在对称加密算法中,加密算法一般如下所示:
DES加密算法
明文:待需要加密的原始文件
**:加密所需要的key值
加密算法:以**为参数,对明文进行多种置换和转换的规则和步骤,变换结果为密文
密文:对明文进行变换的结果
解密算法:加密算法的逆变换,以密文为输入、**为参数,变换结果为明文

二、.对称密码常用的数学运算

对称密码当中有几种常用到的数学运算。这些运算的共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。

  • 移位和循环移位
    移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。

  • 置换
    就是将数码中的某一位的值根据置换表的规定,用另一位代替。通过置换将原文彻底打乱,加大解密难度。

  • 扩展
    就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。

  • 压缩
    就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。

  • 异或
    参加异或的数如果相同为0,不同为1。
    1⊕1 = 0
    0⊕0 = 0
    1⊕0 = 1
    0⊕1 = 1

  • 迭代
    迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以**。

三、DES算法简介

1. DES是一种将64比特的明文加密成64比特密文的对称密码算法,它的**长度是56位,尽管从本质上说它的**是64bit,但是由于每隔7位会设置一个用于错误检查的比特,奇偶校验位,因此实质上**长度是56比特。

2. DES以64比特明文为一个单位进行加密。

3. DES每次只能加密64比特的数据,如果待加密的数据比较长,就需要对DES加密进行迭代,迭代的具体方案称之为模式。如果数据长度不足64比特的倍数就需要进行填充。

四、DES算法的理论原理

DES算法的主要流程如下图所示
DES加密算法

1. IP置换

IP置换目的是将输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位。
置换规则如下表所示:
DES加密算法

表中的数字代表原数据中此位置的数据在新数据中的位置,即原数据块的第1位放到新数据的第58位,第2位放到第50位,……依此类推,第64位放到第7位。置换后的数据分为L0和R0两部分,L0为新数据的左32位,R0为新数据的右32位。

2. **置换

不考虑每个字节的第8位,DES的**由64位减至56位,每个字节的第8位作为奇偶校验位。产生的56位**由下表生成(注意表中没有8,16,24,32,40,48,56和64这8位):
DES加密算法
 在DES的每一轮中,从56位**产生出不同的48位子**,确定这些子**的方式如下:
  (1).将56位的**分成两部分,每部分28位。

  (2).根据轮数,这两部分分别循环左移1位或2位。每轮移动的位数如下表:
  DES加密算法

移动后,从56位中选出48位。这个过程中,既置换了每位的顺序,又选择了子**,因此称为压缩置换。压缩置换规则如下表(注意表中没有9,18,22,25,35,38,43和54这8位):
DES加密算法
置换方法同上,此处省略。

3.扩展置换

 扩展置置换目标是IP置换后获得的右半部分R0,将32位输入扩展为48位(分为4位×8组)输出。

  扩展置换目的有两个:生成与**相同长度的数据以进行异或运算;提供更长的结果,在后续的替代运算中可以进行压缩。

  扩展置换原理如下表:
DES加密算法

表中的数字代表位,两列黄色数据是扩展的数据,可以看出,扩展的数据是从相邻两组分别取靠近的一位,4位变为6位。靠近32位的位为1,靠近1位的位为32。表中第二行的4取自上组中的末位,9取自下组中的首位。

4.S盒代替

压缩后的**与扩展分组异或以后得到48位的数据,将这个数据送人S盒,进行替代运算。替代由8个不同的S盒完成,每个S盒有6位输入4位输出。48位输入分为8个6位的分组,一个分组对应一个S盒,对应的S盒对各组进行代替操作。
DES加密算法

5. P盒置换

 S盒代替运算的32位输出按照P盒进行置换。该置换把输入的每位映射到输出位,任何一位不能被映射两次,也不能被略去,映射规则如下表:
 DES加密算法
表中的数字代表原数据中此位置的数据在新数据中的位置,即原数据块的第16位放到新数据的第1位,第7位放到第2位,……依此类推,第25位放到第32位。

 最后,P盒置换的结果与最初的64位分组左半部分L0异或,然后左、右半部分交换,接着开始另一轮。

6.IP末置换

末置换是初始置换的逆过程,DES最后一轮后,左、右两半部分并未进行交换,而是两部分合并形成一个分组做为末置换的输入。末置换规则如下表:
DES加密算法

五、Go语言使用DES算法实例

package main

import (
    "crypto/des"
    "bytes"
    "crypto/cipher"
    "fmt"
)

//为最后一组填充数据
func PaddingText(src []byte,blockSize int)[]byte{
    length := len(src)%blockSize
    //获取需要填充的字节数
    padding := blockSize-length
    //填充数据
    paddText := bytes.Repeat([]byte{byte(padding)},padding)
    //将填充数据追加到原始数据
    newText := append(src,paddText...)

    return newText
}

func UnPaddingText(src []byte) []byte{
    length := len(src)
    //取出原始数据最后一个字节
    number := int(src[length-1])
    //去除填充数据
    newText := src[:length-number]

    return newText
}

//使用DES算法对文件进行加密
//src:需要被加密的明文
//key:秘钥
func EncryptDES(src,key []byte)([]byte,error){
    //生成加密用的block
    block,err :=des.NewCipher(key)
    if err!=nil{
        return []byte(""),err
    }

    length := block.BlockSize()
    //拼接数据
    src = PaddingText(src,length)
    //NewCBCEncrypter第二个参数是初始化向量,长度要求和块大小一样,内容随意(需要和解密初始化向量相同)
    //根据块和向量创建CBC加密模式
    blockMode := cipher.NewCBCEncrypter(block,key[:block.BlockSize()])
    //创建切片,用于存储加密之后的密文
    dest := make([]byte,len(src))
    //加密

    blockMode.CryptBlocks(dest,src)

    return dest,nil
}

//使用DES算法解密
//src:需要被加密的密文
//key:秘钥,需要和加密时使用的秘钥相同
func DecryptDES(src,key []byte)([]byte,error){
    block,err :=des.NewCipher(key)
    if err != nil{
        return []byte(""),err
    }

    //准备初始化向量
    //创建解密模式
    blockMode := cipher.NewCBCDecrypter(block,key[:block.BlockSize()])
    //创建切片,用于存储解密之后的明文
    dest := make([]byte,len(src))
    //解密
    blockMode.CryptBlocks(dest,src)

    NewText := UnPaddingText(dest)

    return NewText,nil
}

func main(){
    src := []byte("单枪匹马你别怕,一腔孤勇又如何!")
    key := []byte("00001111")

    ciphertext,err := EncryptDES(src,key)
    if err != nil{
        fmt.Println("Encrypt err:",err)
        return
    }
    fmt.Println(ciphertext)

    plaintext,err := DecryptDES(ciphertext,key)
    if err != nil{
        fmt.Println("Decrypt err:",err)
        return
    }

    fmt.Println(string(plaintext))
}