前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >通过Go实现AES加密和解密工具

通过Go实现AES加密和解密工具

作者头像
你大哥
发布于 2022-06-08 09:19:16
发布于 2022-06-08 09:19:16
3.3K00
代码可运行
举报
文章被收录于专栏:容器云实践容器云实践
运行总次数:0
代码可运行

本文包含如下两个内容:

  • AES加密介绍及实现原理
  • Go实现AES加密和解密工具

AES加密介绍及实现原理

AES( advanced encryption standard)使用相同密钥进行加密和解密,也就是对称加密。其他的对称加密如DES,由于DES密钥长度只有56位如今的算力甚至可以在5分钟内破解,而AES最高级别达到了256位密钥长度,如果采用穷举法,目前来看AES是一种”无法“被破解的加密存在。

关于非对称加密我们在之前有一篇文章《理解https中的安全及其实现原理》进行了介绍,有兴趣的可翻看查看。

AES用在哪里?

如果你正在浏览本文,那么你就在使用AES(https协议中一部分使用了对称加密)。

  • 绿色上网:通过加密安全地连接到另一台搬石头砸脚的服务器
  • 无线网络WIFI:和WAP2一起使用。
  • 应用程序:wechat、JD、Alipay等使用 AES 加密照片和消息或支付信息。
  • 存档和压缩工具:7z、WinZip 和 RAR。
  • 操作系统组件:一些操作系统组件(如文件系统)使用高级加密标准来确保安全性。
  • 编程语言库: Go、Python 和 C++ 等编码库实现了的AES加密(等会使用到)。
AES加密是如何实现的?

参考:

what-is-the-aes-algorithm?

What is AES encryption and how does it work?

Block cipher mode of operation

从宏观上来看AES加密过程中的一轮(根据不同的密钥长度,轮数不一样,下面会说到)如下:

1.数据分块

首先把明文按照128bit拆分成若干个明文块(图上黄色块),一个字节包含 8 位,布局为 4×4矩阵(上图黄色部分),对最后一块填充至128bit,填充方式有PKCS7Padding(采用)/PKCS5Padding/ZeroPadding,无论咋填充最后解密时都要去除这些多余的填充。

2.密钥扩展

AES通过Rijndael's key schedule 将密钥被扩展为 (n+1) 个密钥,其中 n 是加密过程中要遵循的轮数。AES每个标准规定了所要加密的轮数,对于128位密钥,轮数是 10,要生成的密钥个数为 10+1,总共 11 个密钥。

标准

密钥长度

轮数

分组长度

AES-128

128位(16字节)

10

128位(16字节)

AES-192

192位(24字节)

12

128位(16字节)

AES-256

256位(32字节)

14

128位(16字节)

每一轮所要做的包括:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)、加轮密钥(AddRoundKey)

3.字节替代(SubBytes)

每轮开始,首先进行SubBytes,字节根据预定义的 Rijndael S-box(可以简单认为是一个转换表)规定的规则进行替换。对a[i,j]中的每个字节进行一次转换后得到b[i,j]

4.行移位(ShiftRows)

对上一步得到矩阵进行ShiftRows,第一行不变,第二行移动1位,第三行2位,第四行3位。

5.列混淆(MixColumns)

再对矩阵的每一列和修补矩阵fixed matrix的二维常量数组做矩阵相乘,得到对应的输出列。

6.加轮密钥(AddRoundKey)

先将扩展密钥Kn排列成4×4矩阵,然后让输入数组的每一个字节a[i,j]与密钥对应位置的字节k[i,j]异或一次,得到输出b[i,j]。最后一轮不参与AddRoundKey

经过如上的10轮操作之后,得到了一个明文块的加密字符。解密则进行反向加密。

AES加密模式
ECB

在上面加密过程中每一个明文块都是独立进行加密的,简单且高效,但是如果一个段数据存在相关的明文块,则加密后的密文也会相同,对安全性也有一定影响。

CBC

CBC加密模式如下图所示,初始向量IV和明文异或,每个块的密文作为后续块的“向量”,让每一个密文独一无二。我们待会采用这种模式。


Go实现AES加密工具scode

ok,上面大致了解AES加密是如何工作起来的,接下来通过Go中的crypto/aes和crypto/cipher包实现的AES加密解密工具。

PKCS7Padding将待补足字节数作为填充的字节

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// pkcs7Padding 填充
func pkcs7Padding(data []byte, blockSize int) []byte {
    //判断缺少几位长度。最少1,最多 blockSize
    padding := blockSize - len(data)%blockSize
    //补足位数。把切片[]byte{byte(padding)}复制padding个
    padText := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(data, padText...)
}

// pkcs7UnPadding 移除
func pkcs7UnPadding(data []byte) ([]byte, error) {
    length := len(data)
    if length == 0 {
        return nil, errors.New("加密字符串错误!")
    }
    //获取填充的个数
    unPadding := int(data[length-1])
    return data[:(length - unPadding)], nil
}

使用 cipher的CBC模式对block加密和解密

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// AesEncrypt 加密
func AesEncrypt(data []byte, key []byte) ([]byte, error) {    
    // NewCipher creates and returns a new cipher.Block. The key argument should be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    //判断加密快的大小
    blockSize := block.BlockSize()
    //填充
    encryptBytes := pkcs7Padding(data, blockSize)
    //初始化加密数据接收切片
    crypted := make([]byte, len(encryptBytes))
    //使用cbc加密模式
    blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
    //执行加密
    blockMode.CryptBlocks(crypted, encryptBytes)
    return crypted, nil
}

// AesDecrypt 解密
func AesDecrypt(data []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    //获取块的大小
    blockSize := block.BlockSize()
    //使用cbc
    blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
    //初始化解密数据接收切片
    crypted := make([]byte, len(data))
    //执行解密
    blockMode.CryptBlocks(crypted, data)
    //去填充
    crypted, err = pkcs7UnPadding(crypted)
    if err != nil {
        return nil, err
    }
    return crypted, nil
}

循环从文件中读取100mb源数据用于加密后将密文写入文件,解密则读取密文解密后将源数据写入文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func EncryptFile(fileName string) (err error) {
    f, err := os.Open(fileName)
    if err != nil {
        fmt.Println("未找到文件")
        return
    }
    defer f.Close()

    fInfo, _ := f.Stat()
    fLen := fInfo.Size()
    fmt.Println("待处理文件大小:", fLen)
    maxLen := 1024 * 1024 * 100 //100mb  每 100mb 进行加密一次
    var forNum int64 = 0
    getLen := fLen

    if fLen > int64(maxLen) {
        getLen = int64(maxLen)
        forNum = fLen / int64(maxLen)
        fmt.Println("需要加密次数:", forNum+1)
    }
    // encryptd to file
    ff, err := os.OpenFile("en_"+fileName, os.O_RDWR|os.O_CREATE, 0666)
    if err != nil {
        fmt.Println("文件写入错误")
        return err
    }
    defer ff.Close()
    //循环加密,并写入文件
    for i := 0; i < int(forNum+1); i++ {
        a := make([]byte, getLen)
        n, err := f.Read(a)
        if err != nil {
            fmt.Println("文件读取错误")
            return err
        }
        getByte, err := EncryptByAes(a[:n])
        if err != nil {
            fmt.Println("加密错误")
            return err
        }
        getBytes := append([]byte(getByte), []byte("\n")...)
        //写入
        buf := bufio.NewWriter(ff)
        buf.WriteString(string(getBytes[:]))
        buf.Flush()
    }
    ffInfo, _ := ff.Stat()
    fmt.Printf("加密后文件为:%s,文件大小为:%v Byte \n", ffInfo.Name(), ffInfo.Size())
    return nil
}

参考:Golang AES 加密 解密

通过cobra添加命令后,创建命令的匿名函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func(cmd *cobra.Command, args []string) {
    copy(PwdKey, readPass())
    Pwd := []byte("csgo!gogo")
    if ByteSliceEqual(PwdKey, Pwd) {
        //16字节key
        PwdKey = append(PwdKey, 7, 3, 5, 5, 6, 0, 8)
        if err := DecryptFile(args[0]); err != nil {
            panic(err)
        }
    } else {
        fmt.Println("密码错误")
        os.Exit(1)
    }
}

使用方式看起来如下:

scode工具包含2个命令encode和decode,解密文件需要密码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# ./scode  encode xpower.tar.gz
待处理文件大小: 3397
加密后文件为:en_xpower.tar.gz,文件大小为:4545 Byte

# ./scode  decode en_xpower.tar.gz
ENTER PASSWORD: 
密码错误

# ./scode  decode en_xpower.tar.gz
ENTER PASSWORD: 
待处理文件大小: 4545
解密后文件为:de_en_xpower.tar.gz,文件大小为:3159 Byte

完整代码:source

通过博客查看:iqsing.github.io

通过改进此工具创建一个自己隐私文件加密和解密器。

参考:

[1] what-is-the-aes-algorithm?: https://www.educative.io/edpresso/what-is-the-aes-algorithm

[2]

What is AES encryption and how does it work?: https://cybernews.com/resources/what-is-aes-encryption/

[3]

Block cipher mode of operation: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

[4]

Rijndael's key schedule: https://www.samiam.org/key-schedule.html

[5]

Golang AES 加密 解密: https://www.jianshu.com/p/0caab60fea9f

[6]

iqsing.github.io: https://iqsing.github.io

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 容器云实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Go AES加解密
https://blog.csdn.net/K346K346/article/details/89387460
恋喵大鲤鱼
2019/05/05
12.5K0
Golang AES 加解密
利用 Go 提供的 AES 加解密与 Base64 编解码包,我们可以轻松实现 AES 加解密。实现之前,首先了解一下 AES 的基本知识。
恋喵大鲤鱼
2022/05/09
1.7K0
不背锅运维:Go实现aes加密,并带你手撸一个命令行应用程序
本文转载于(喜欢的盆友关注我们):https://mp.weixin.qq.com/s/FsIfvsuu5jh5_yBXZUS7rA
不背锅运维
2023/02/16
4290
不背锅运维:Go实现aes加密,并带你手撸一个命令行应用程序
对称加密算法和分组密码的模式
由于加密出来的数据很可能有很多不可见字符,因此这里会将加密后的结果进行一次Base64Encode。
linjinhe
2018/06/06
2.6K0
主流加密方式
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),对称加密
酷走天涯
2019/05/26
1.3K0
Go 加密解密算法总结
加密解密在实际开发中应用比较广泛,常用加解密分为:“对称式”、“非对称式”和”数字签名“。
孤烟
2020/09/27
3K0
Golang里的AES加密、解密,支持AES-ECB-PKCS7Padding等多种加密组合,兼容JAVA、PHP等语言
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,这个标准用来替代原先的DES。AES加密数据块分组长度必须为128bit,密钥长度可以是128bit、192bit、256bit中的任意一个。
技术圈
2024/06/11
8250
Golang:加密解密算法
在项目开发过程中,当操作一些用户的隐私信息,诸如密码,帐户密钥等数据时,往往需要加密后可以在网上传输.这时,需要一些高效地,简单易用的加密算法加密数据,然后把加密后的数据存入数据库或进行其他操作;当需要读取数据时,把加密后的数据取出来,再通过算法解密.
OwenZhang
2021/12/08
1.8K0
Golang:加密解密算法
Go 语言实现 AES 算法的加解密操作
AES(Advanced Encryption Standard,高级加密标准)是一种对称加密算法,即在加密和解密过程中使用同一个密钥。AES 算法属于分组加密算法,将数据按块处理,每块固定大小。AES 算法的核心思想是在多轮操作中对数据进行替换和置换,从而有效打乱数据,使其无法被破解。
陈明勇
2024/11/15
1890
Go加密算法总结
它是一种数据编码方式,虽然是可逆的,但是它的编码方式是公开的,无所谓加密。本文也对Base64编码方式做了简要介绍。
iginkgo18
2020/12/22
1.7K0
Go语言 字符串加密
AES加密 CBC模式,最常见的使用方式: package main import ( "bytes" "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func AesEncrypt(str string, key string) string { // 转成字节数组 strData := []byte(str) k := []byte(key) // 分组秘钥
码客说
2022/10/07
9470
[GO]golang实现AES加解密
AesEncrypt是加密,第二个参数是设置的key,key的长度必须是16、24、32
唯一Chat
2021/07/20
5450
AES对称加密算法如何用golang语言实现?
数据的加密算法一般都可以分几类,有对称加密,非对称加密,不可逆加密(也叫hash算法或者散列算法)。
公众号-利志分享
2022/04/25
1.4K0
Golang DES 加解密如何实现?
【导读】本文介绍了 DES 加密原理和作用,和 golang 中 DES 加密解密机制的相应实现。
码农编程进阶笔记
2022/08/18
1.9K0
Golang DES 加解密如何实现?
golang的AES加密和解密的三种模式实现(CBC/ECB/CFB)「建议收藏」
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/128363.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/31
5.8K0
golang的AES加密和解密的三种模式实现(CBC/ECB/CFB)「建议收藏」
Go语言中的加密和解密是如何实现的?
在Go语言中,加密和解密操作是通过标准库中的一些特定包来实现的。这些包提供了丰富的加密和解密算法,包括对称加密、非对称加密、散列函数、Base64编码与解码等。下面,我们将详细解释这些包和它们的功能,并提供一些具体的示例代码。
阿珍
2025/01/13
1040
Go语言中的加密和解密是如何实现的?
Golang与对称加密
DES(Data Encryption Standard)数据加密标准,是目前最为流行的加密算法之一 DES是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准FIPS,并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来
仙人技术
2021/12/27
1K0
Golang与对称加密
Golang语言 加密系列之AES
加密代码: func Encrypt(plantText, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) //选择加密算法 if err != nil { return nil, err } plantText = PKCS7Padding(plantText, block.BlockSize()) blockModel := cipher.NewCBCEncrypter(block,
李海彬
2018/03/21
1.1K0
python-AES加密解密
转载https://www.jianshu.com/p/5d27888e7c93#!/xh
小小咸鱼YwY
2020/06/19
4.3K0
笔记:Go语言中处理字节切片时可能修改传入参数的底层切片序列的问题
笔者在做某项功能特性开发时,需要使用对称加密算法对部分数据做加密,期间将数据以[]byte切片的形式作为入参传入时,发现在加密完成后,原始的明文会发生变化,针对这个问题笔者在 debug 过程中发现是切片与其底层切片变化引起的,于是有了这篇笔记。
bowenerchen
2024/05/24
1722
笔记:Go语言中处理字节切片时可能修改传入参数的底层切片序列的问题
相关推荐
Go AES加解密
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验