脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Golang实现AES对称加密的过程详解

Golang实现AES对称加密的过程详解

2021-06-27 00:46写Golang的小张 Golang

AES是一个对称密码,旨在取代DES成为广泛使用的标准,本文给大家分享Golang实现AES对称加密的过程,本文附有Golang实现AES加密ECB模式的源码,感兴趣的朋友跟随小编一起学习下吧

AES加密

 

AES对称加密简介
AES是一个对称密码,旨在取代DES成为广泛使用的标准。是美国联邦政府采用的一种区块加密标准。

AES对称加密过程
加密解密算法的输入是一个128位分组。这些分组被描述成4×4的字节方阵,这个分组被复制到数组中,并在加密和解密的每一阶段都被修改。在字节方阵中,每一格都是一个字,包含了4字节。在矩阵中字是按列排序的。
加密由N轮构成,轮数依赖于密钥长度:16字节密钥对应10轮,24字节密钥对应12轮,32字节对应14轮。

AES加密模式

1.电码本模式(Electronic Codebook Book (ECB)

ECB模式是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。

2.密码分组链接模式(Cipher Block Chaining (CBC))

这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。

3.密码反馈模式(Cipher FeedBack (CFB))
隐藏了明文模式,分组密码转化为流模式,可以及时加密传送小于分组的数据

4.OFB(Output FeedBack,输出反馈)模式
隐藏了明文模式;,分组密码转化为流模式,可以及时加密传送小于分组的数据

AES填充方式
AES支持支持几种填充:NoPadding,PKCS5Padding,ISO10126Padding,PaddingMode.Zeros,PaddingMode.PKCS7。对于AES来说PKCS5Padding和PKCS7Padding是完全一样的,不同在于PKCS5限定了块大小为8bytes而PKCS7没有限定。因此对于AES来说两者完全相同

Golang实现AES加密解密

 

下面附上Golang实现AES加密ECB模式的源码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package main
import (
    "bytes"
    "crypto/aes"
    "fmt"
    "testing"
)
 
//ECB模式解密
func ECBDecrypt(crypted, key []byte) ([]byte, error) {
    if !validKey(key) {
        return nil, fmt.Errorf("秘钥长度错误,当前传入长度为 %d",len(key))
    }
    if len(crypted) < 1 {
        return nil, fmt.Errorf("源数据长度不能为0")
    }
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    if len(crypted)%block.BlockSize() != 0 {
        return nil, fmt.Errorf("源数据长度必须是 %d 的整数倍,当前长度为:%d",block.BlockSize(), len(crypted))
    }
    var dst []byte
    tmpData := make([]byte, block.BlockSize())
 
    for index := 0; index < len(crypted); index += block.BlockSize() {
        block.Decrypt(tmpData, crypted[index:index+block.BlockSize()])
        dst = append(dst, tmpData...)
    }
    dst, err = PKCS5UnPadding(dst)
    if err != nil {
        return nil, err
    }
    return dst, nil
}
 
//ECB模式加密
func ECBEncrypt(src, key []byte) ([]byte, error) {
    if !validKey(key) {
        return nil, fmt.Errorf("秘钥长度错误, 当前传入长度为 %d",len(key))
    }
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    if len(src) < 1 {
        return nil, fmt.Errorf("源数据长度不能为0")
    }
    src = PKCS5Padding(src, block.BlockSize())
    if len(src)%block.BlockSize() != 0 {
        return nil, fmt.Errorf("源数据长度必须是 %d 的整数倍,当前长度为:%d",block.BlockSize(), len(src))
    }
    var dst []byte
    tmpData := make([]byte, block.BlockSize())
    for index := 0; index < len(src); index += block.BlockSize() {
        block.Encrypt(tmpData, src[index:index+block.BlockSize()])
        dst = append(dst, tmpData...)
    }
    return dst, nil
}
 
// PKCS5填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}
 
// 去除PKCS5填充
func PKCS5UnPadding(origData []byte) ([]byte, error) {
    length := len(origData)
    unpadding := int(origData[length-1])
 
    if length < unpadding {
        return nil, fmt.Errorf("invalid unpadding length")
    }
    return origData[:(length - unpadding)], nil
}
 
// 秘钥长度验证
func validKey(key []byte) bool {
    k := len(key)
    switch k {
    default:
        return false
    case 16, 24, 32:
        return true
    }
}
 
func TestAes(t *testing.T){
    srcData := "hello world !"
    key := []byte("abcdabcdabcdabcdabcdabcdabcdabcd")
    //测试加密
    encData ,err := ECBEncrypt([]byte(srcData),(key))
    if err != nil {
        t.Errorf(err.Error())
        return
    }
 
    //测试解密
    decData ,err := ECBDecrypt(encData,key)
    if err != nil {
        t.Errorf(err.Error())
        return
    }
    t.Log(string(decData))
}

PS:推荐一款相关的在线工具:在线文字加密解密工具:https://tool.zzvips.com/t/txtencode/  在线文字加密解密工具提供在线文本加密/解密,并提供AES、DES、RC4、Rabbit、TripleDes等多种算法。

以上就是Golang实现AES对称加密的过程详解的详细内容,更多关于go AES对称加密的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/weixin_46040684/article/details/116993628

延伸 · 阅读

精彩推荐
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09