ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-03-09 15:02:44  阅读:288  来源: 互联网

标签:CBC 加密 ECB err 模式 byte data block


 

问题场景:

业务需要对接接口, 采用DES加密方式加密, 于是google一下go的DES加密方式,
go的DES的默认隐藏了ECB模式, 因为go认为ECB不安全, 所以不建议使用,就隐藏了,
然而接口却需要采用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的标准。
    每个密文块依赖于所有的信息明文消息中一个改变会影响所有密文块
  2. 发送方和接收方都需要知道初始化向量
  3. 加密过程是串行的,无法被并行化(在解密时,从两个邻接的密文块中即可得到一个平文块。因此,解密过程可以被并行化。

码
//ECB加密
func EncryptDES_ECB(src, key string) string {
    data := []byte(src)
    keyByte := []byte(key)
    block, err := des.NewCipher(keyByte)
    if err != nil {
        panic(err)    
    }
    bs := block.BlockSize()
    //对明文数据进行补码
    data = PKCS5Padding(data, bs)
    if len(data)%bs != 0 {
        panic("Need a multiple of the blocksize")
    }
    out := make([]byte, len(data))
    dst := out
    for len(data) > 0 {
        //对明文按照blocksize进行分块加密
        //必要时可以使用go关键字进行并行加密
        block.Encrypt(dst, data[:bs])
        data = data[bs:]
        dst = dst[bs:]
    }
    return fmt.Sprintf("%X", out)
}

//ECB解密
func DecryptDES_ECB(src, key string) string {
	data, err := hex.DecodeString(src)
	if err != nil {
		panic(err)
	}
	keyByte := []byte(key)
	block, err := des.NewCipher(keyByte)
	if err != nil {
		panic(err)
	}
	bs := block.BlockSize()
	if len(data)%bs != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	out := make([]byte, len(data))
	dst := out
	for len(data) > 0 {
		block.Decrypt(dst, data[:bs])
		data = data[bs:]
		dst = dst[bs:]
	}
	out = PKCS5UnPadding(out)
	return string(out)
}

//CBC加密
func EncryptDES_CBC(src, key string) string {
	data := []byte(src)
	keyByte := []byte(key)
	block, err := des.NewCipher(keyByte )
	if err != nil {
		panic(err)
	}
	data = PKCS5Padding(data , block.BlockSize())
	//获取CBC加密模式
	iv := keyByte //用密钥作为向量(不建议这样使用)
	mode := cipher.NewCBCEncrypter(block, iv)
	out := make([]byte, len(data))
	mode .CryptBlocks(out, data)
	return fmt.Sprintf("%X", out)
}

//CBC解密
func DecryptDES_CBC(src, key string) string {
	keyByte := []byte(key)
	data, err := hex.DecodeString(src)
	if err != nil {
		panic(err)
	}
	block, err := des.NewCipher(keyByte)
	if err != nil {
		panic(err)
	}
	iv := keyByte //用密钥作为向量(不建议这样使用)
	mode := cipher.NewCBCDecrypter(block, iv)
	plaintext := make([]byte, len(data))
	mode.CryptBlocks(plaintext, data)
	plaintext = PKCS5UnPadding(plaintext)
	return string(plaintext)
}


//明文补码算法
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)]
}

  

转自https://my.oschina.net/imhuayi/blog/1541840

标签:CBC,加密,ECB,err,模式,byte,data,block
来源: https://www.cnblogs.com/leescre/p/10500808.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有