Go 实现 DES 加密和解密

标签:密码学
发布时间:2018年10月16日 价值:20000.00 / 共识:30

DES加密算法,为对称加密算法中的一种。是以64比特的明文为一个单位来进行加密,超过64比特的数据,要求按固定的64比特的大小分组,分组有很多模式。DES使用的密钥长度为64比特,但由于每隔7个比特设置一个奇偶校验位,因此其密钥长度实际为56比特。奇偶校验为最简单的错误检测码,即根据一组二进制代码中1的个数是奇数或偶数来检测错误。

加密模式

  • ECB模式 全称Electronic Codebook模式,译为电子密码本模式
  • CBC模式 全称Cipher Block Chaining模式,译为密文分组链接模式
  • CFB模式 全称Cipher FeedBack模式,译为密文反馈模式
  • OFB模式 全称Output Feedback模式,译为输出反馈模式。
  • CTR模式 全称Counter模式,译为计数器模式。

填充方式

当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其凑满一个分组长度。

  • NoPadding
    API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充或者空格,然后trim
  • PKCS5Padding
    加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
    解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。
    加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。
  • PKCS7Padding
    PKCS7Padding 的填充方式和PKCS5Padding 填充方式一样。只是加密块的字节数不同。PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。

以下是go 实现的DES加密和解密代码:

本代码采用CBC加密模式,填充方式采用PKCS5Padding

  1. package main
  2. import (
  3. "crypto/des"
  4. "bytes"
  5. "crypto/cipher"
  6. "fmt"
  7. "encoding/base64"
  8. )
  9. //DES加密方法
  10. func MyDESEncrypt (origData,key []byte){
  11. //将字节秘钥转换成block快
  12. block,_ := des.NewCipher(key)
  13. //对明文先进行补码操作
  14. origData = PKCS5Padding(origData,block.BlockSize())
  15. //设置加密方式
  16. blockMode := cipher.NewCBCEncrypter(block,key)
  17. //创建明文长度的字节数组
  18. crypted := make([]byte, len(origData))
  19. //加密明文,加密后的数据放到数组中
  20. blockMode.CryptBlocks(crypted,origData)
  21. //将字节数组转换成字符串
  22. fmt.Println(base64.StdEncoding.EncodeToString(crypted))
  23. }
  24. //实现明文的补码
  25. func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
  26. //计算出需要补多少位
  27. padding := blockSize - len(ciphertext)%blockSize
  28. //Repeat()函数的功能是把参数一 切片复制 参数二count个,然后合成一个新的字节切片返回
  29. // 需要补padding位的padding值
  30. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  31. //把补充的内容拼接到明文后面
  32. return append(ciphertext,padtext...)
  33. }
  34. //解密
  35. func MyDESDecrypt(data string, key []byte) {
  36. //倒叙执行一遍加密方法
  37. //将字符串转换成字节数组
  38. crypted,_ := base64.StdEncoding.DecodeString(data)
  39. //将字节秘钥转换成block快
  40. block, _ := des.NewCipher(key)
  41. //设置解密方式
  42. blockMode := cipher.NewCBCDecrypter(block,key)
  43. //创建密文大小的数组变量
  44. origData := make([]byte, len(crypted))
  45. //解密密文到数组origData中
  46. blockMode.CryptBlocks(origData,crypted)
  47. //去补码
  48. origData = PKCS5UnPadding(origData)
  49. //打印明文
  50. fmt.Println(string(origData))
  51. }
  52. //去除补码
  53. func PKCS5UnPadding(origData []byte) []byte {
  54. length := len(origData)
  55. // 去掉最后一个字节 unpadding 次
  56. unpadding := int(origData[length-1])
  57. //解密去补码时需取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
  58. return origData[:(length - unpadding)]
  59. }
  60. func main () {
  61. //定义明文
  62. data := []byte("hello world")
  63. //密钥
  64. key := []byte("12345678")
  65. //加密
  66. MyDESEncrypt(data,key)
  67. //解密
  68. MyDESDecrypt("CyqS6B+0nOGkMmaqyup7gQ==",key)
  69. }

其中解密只需把加密过程倒叙走一遍。

关于明文补码和去补码操作:

加密前明文补码规则 (cipher.NewCBCEncrypter 调用前操作):

加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8

对应的明文补码代码部分:

  1. //实现明文的补码
  2. func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
  3. //计算出需要补多少位
  4. padding := blockSize - len(ciphertext)%blockSize
  5. //Repeat()函数的功能是把参数一 切片复制 参数二count个,然后合成一个新的字节切片返回
  6. // 需要补padding位的padding值
  7. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  8. //把补充的内容拼接到明文后面
  9. return append(ciphertext,padtext...)
  10. }

解密后去除补码规则(cipher.NewCBCDecrypter调用解密完成后):

解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。

对应的去补码代码部分:

  1. //去除补码
  2. func PKCS5UnPadding(origData []byte) []byte {
  3. length := len(origData)
  4. // 去掉最后一个字节 unpadding 次
  5. unpadding := int(origData[length-1])
  6. //解密去补码时需取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
  7. return origData[:(length - unpadding)]
  8. }
  • 分享 收藏
0 条评论
  • 这篇文章暂无评论,赶紧评论一下吧~