golang加密算法之DES

admin 2019年10月24日09:25:03评论8 views字数 5394阅读17分58秒阅读模式

Go语言的DES加密(CBC模式, ECB模式) ---- 与java加密互通

问题场景:

业务需要对接接口, 采用DES加密方式加密, 于是google一下go的DES加密方式,

go的DES的默认隐藏了ECB模式, 因为go认为ECB不安全, 所以不建议使用,就隐藏了,

然而由于历史遗留问题接口却需要采用ECB模式。

ECB

  • 概念

ECB(电子密本方式)就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。

  • 特点
  1. 简单,有利于并行计算,误差不会被传送;
  2. 不能隐藏明文的模式;在密文中出现明文消息的重复
  3. 可能对明文进行主动攻击;加密消息块相互独立成为被攻击的弱点

CBC

  • 概念

CBC(密文分组链接方式)有向量的概念, 它的实现机制使加密的各段数据之间有了联系。

  • 加密步骤:
  1. 首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)
  2. 第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)
  3. 第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
  4. 之后的数据以此类推,得到Cn
  5. 按顺序连为C1C2C3......Cn即为加密结果。
  • 解密是加密的逆过程:
  1. 首先将数据按照8个字节一组进行分组得到C1C2C3......Cn
  2. 将第一组数据进行解密后与初始化向量I进行异或得到第一组明文D1(注意:一定是先解密再异或)
  3. 将第二组数据C2进行解密后与第一组密文数据进行异或得到第二组数据D2
  4. 之后依此类推,得到Dn
  5. 按顺序连为D1D2D3......Dn即为解密结果。
  • 特点
  1. 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

每个密文块依赖于所有的信息明文消息中一个改变会影响所有密文块

  1. 发送方和接收方都需要知道初始化向量
  2. 加密过程是串行的,无法被并行化(在解密时,从两个邻接的密文块中即可得到一个平文块。因此,解密过程可以被并行化。

代码:

//des_ecb_pkcs5padding.go

package main

 

import (

"bytes"

"crypto/des"

"encoding/base64"

"errors"

)

//明文补码算法

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {

padding := blockSize - len(ciphertext) % blockSize

padtext := bytes.Repeat([]byte{byte(padding)}, padding)

return append(ciphertext, padtext...)

}

//明文减码算法

func PKCS5UnPadding(origData []byte) []byte {

length := len(origData)

unpadding := int(origData[length - 1])

return origData[:(length - unpadding)]

}

 

func ZeroPadding(ciphertext []byte, blockSize int) []byte {

padding := blockSize - len(ciphertext)%blockSize

padtext := bytes.Repeat([]byte{0}, padding)

return append(ciphertext, padtext...)

}

 

func ZeroUnPadding(origData []byte) []byte {

return bytes.TrimFunc(origData,

func(r rune) bool {

return r == rune(0)

})

}

 

func DesEncrypt(src, key []byte) ([]byte, error) {

block, err := des.NewCipher(key)

if err != nil {

return nil, err

}

bs := block.BlockSize()

//对明文数据进行补码

src = PKCS5Padding(src, bs)

if len(src) % bs != 0 {

return nil, errors.New("Need a multiple of the blocksize")

}

out := make([]byte, len(src))

dst := out

//对明文按照blocksize进行分块加密

//必要时可以使用go关键字进行并行加密

for len(src) > 0 {

block.Encrypt(dst, src[:bs])

src = src[bs:]

dst = dst[bs:]

}

dstBase64 := make([]byte, base64.StdEncoding.EncodedLen(len(out)))

base64.StdEncoding.Encode(dstBase64, out)

return dstBase64, nil

}

 

func DesDecrypt(src, key []byte) ([]byte, error) {

srcBase64 := make([]byte, base64.StdEncoding.DecodedLen(len(src)))

n, err := base64.StdEncoding.Decode(srcBase64, src)

if err != nil {

return nil, err

}

srcUnBase64 := srcBase64[:n]

block, err := des.NewCipher(key)

if err != nil {

return nil, err

}

out := make([]byte, len(srcUnBase64))

dst := out

bs := block.BlockSize()

if len(srcUnBase64) % bs != 0 {

return nil, errors.New("crypto/cipher: input not full blocks")

}

for len(srcUnBase64) > 0 {

block.Decrypt(dst, srcUnBase64[:bs])

srcUnBase64 = srcUnBase64[bs:]

dst = dst[bs:]

}

out = PKCS5UnPadding(out)

return out, nil

}

 

//main.go 使用DES算法来加密电话号码

package main

 

import (

"bufio"

"flag"

"fmt"

"io"

"os"

"runtime"

"sync"

)

 

const (

GPNUM = 1000

//key只能是8位,不能少于8位也不能多于8位.

KEY = "ImDesKey"

)

 

var (

inputFile, outputFile string

)

 

type outputWriter struct {

file *os.File

fWriter *bufio.Writer

rwMutex *sync.RWMutex

ch chan []byte

wg *sync.WaitGroup

}

 

func (ow *outputWriter) Write(row []byte) {

ow.rwMutex.Lock()

ow.fWriter.Write(row)

ow.rwMutex.Unlock()

}

 

func (ow *outputWriter) Flush() {

ow.rwMutex.Lock()

ow.fWriter.Flush()

ow.rwMutex.Unlock()

}

 

func (ow *outputWriter) Close() {

ow.file.Close()

}

 

func NewOutputWriter(dstFile string, gp int) (*outputWriter, error) {

f, err := os.OpenFile(dstFile,os.O_WRONLY|os.O_CREATE|os.O_TRUNC,0644)

if err != nil {

return nil, err

}

w := bufio.NewWriter(f)

ch := make(chan []byte, gp)

return &outputWriter{file:f, fWriter:w, rwMutex:&sync.RWMutex{}, ch:ch, wg:&sync.WaitGroup{}}, nil

}

 

func init() {

runtime.GOMAXPROCS(runtime.NumCPU())

flag.StringVar(&inputFile, "srcfile", "tel.txt", "src file")

flag.StringVar(&outputFile, "dstfile", "tel_en.txt", "dst file")

flag.Parse()

}

func concurrentProcess(gp int, src string) {

//ch := make(chan []byte, gp)

//wg := &sync.WaitGroup{}

fReader, err := os.Open(src)

if err != nil {

fmt.Errorf("Error: %vn", err)

os.Exit(1)

}

//defer fReader.Close()

reader := bufio.NewReader(fReader)

 

writer, err := NewOutputWriter(outputFile, gp)

if err != nil {

fmt.Errorf("Error: %vn", err)

}

//defer writer.Close()

for {

lineBytes, _, err := reader.ReadLine()

if err == io.EOF {

break

}

//tab键的ascii码为9

//lineBytesSlice := bytes.Split(lineBytes, []byte{9})

//telBytes := lineBytesSlice[0]

//provBytes := lineBytesSlice[1]

//cityBytes := lineBytesSlice[2]

writer.wg.Add(1)

go func(ch chan []byte) {

lineWriteBytes := make([]byte,0,45)

telBytes := make([]byte,0,11)

for i:=0;i<=10;i++{

telBytes = append(telBytes, lineBytes[i])

}

//注意:这里不能使用telEnBytes, telEnErr := DesEncrypt(lineBytes[:11], []byte(KEY))来加密电话号码,否则会修改lineBytes[11:]中的内容

telEnBytes, telEnErr := DesEncrypt(telBytes, []byte(KEY))

if telEnErr != nil {

fmt.Errorf("Error: %vn", telEnErr)

//os.Exit(1)

}

for i:=0;i<=11;i++ {

lineWriteBytes = append(lineWriteBytes,lineBytes[i])

}

for i:=0;i<=23;i++{

lineWriteBytes = append(lineWriteBytes, telEnBytes[i])

}

for i:=11;i<len(lineBytes);i++{

lineWriteBytes = append(lineWriteBytes, lineBytes[i])

}

//换行的ascii码为10lineBytes[:11]

lineWriteBytes = append(lineWriteBytes,10)

//writer.Write(lineWriteBytes)

//writer.Flush()

ch <- lineWriteBytes

defer writer.wg.Done()

}(writer.ch)

writer.wg.Add(1)

go func(ch chan []byte) {

writer.Write(<-ch)

writer.Flush()

defer writer.wg.Done()

}(writer.ch)

}

//writer.Flush()

writer.wg.Wait()

fReader.Close()

writer.Close()

}

 

func main() {

concurrentProcess(GPNUM, inputFile)

}

 

//tel.txt 电话号码文件

13615660000    551    0566

13665660000    551    0566

13615580000    551    0566

13615670000    551    0566

13615680000    551    0566

13615510000    551    0566

13615600000    551    0566

13615690000    551    0566

13645640000    551    0566

13665540000    551    0566

 

 

 

原文始发于微信公众号(糖果的实验室):时代新秀golang--golang加密算法之DES

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2019年10月24日09:25:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   golang加密算法之DEShttps://cn-sec.com/archives/2499945.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息