千家信息网

怎么通过Golang编写一个AES加密解密工具

发表于:2024-11-23 作者:千家信息网编辑
千家信息网最后更新 2024年11月23日,本篇内容主要讲解"怎么通过Golang编写一个AES加密解密工具",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么通过Golang编写一个AES加密解密工
千家信息网最后更新 2024年11月23日怎么通过Golang编写一个AES加密解密工具

本篇内容主要讲解"怎么通过Golang编写一个AES加密解密工具",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么通过Golang编写一个AES加密解密工具"吧!

AES加密介绍及实现原理

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

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-128128位(16字节)10128位(16字节)
AES-192192位(24字节)12128位(16字节)
AES-256256位(32字节)14128位(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将待补足字节数作为填充的字节

// 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加密和解密

// 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源数据用于加密后将密文写入文件,解密则读取密文解密后将源数据写入文件。

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添加命令后,创建命令的匿名函数

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,解密文件需要密码。

# ./scode  encode xpower.tar.gz待处理文件大小: 3397加密后文件为:en_xpower.tar.gz,文件大小为:4545 Byte# ./scode  decode en_xpower.tar.gzENTER PASSWORD: 密码错误# ./scode  decode en_xpower.tar.gzENTER PASSWORD: 待处理文件大小: 4545解密后文件为:de_en_xpower.tar.gz,文件大小为:3159 Byte

到此,相信大家对"怎么通过Golang编写一个AES加密解密工具"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

加密 文件 字节 密钥 大小 工具 数据 明文 矩阵 错误 长度 密文 模式 加密解密 安全 对称 命令 密码 标准 系统 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全运维解决方案 网络安全大赛夺旗赛基础培训 史上最畅销的软件开发书籍 移动公司网络技术员 提高网络技术创新 赴日软件开发靠谱吗 数据库的完整性有系统完整性么 数据库flask 汕头微信软件开发报价 三明市骏马网络技术有限公司 青少年网络安全签名 万亿数据存储及处理用什么数据库 认识到网络安全的重要性 数据库开发 pdf 我的世界服务器吃什么性能 excelvbs连接数据库 对应数据满足条件的个数据库 智慧供应链软件开发定制怎么做 建立疫情分析数据库 信息化软件开发特价 软件开发 功能分解 苏州办公系统软件开发价格表 服务器存储mysql数据库 蔚来嵌入式软件开发笔试 武汉网络安全学院在哪个区 宁波慈溪lenovo塔式服务器 我的世界虚无服务器 软件开发成本换算成人月 戴尔服务器蓝屏进不去怎么办 我的世界网易服务器为什么不能进
0