首页 > 其他分享 >golang的AES加密

golang的AES加密

时间:2023-01-05 17:45:58浏览次数:43  
标签:AES 加密 len 明文 golang 分组 key byte

AES

常用的加解密的方式无非三种.
对称加密, 加解密都使用的是同一个密钥, 其中的代表就是AES
非对加解密, 加解密使用不同的密钥, 其中的代表就是RSA
签名算法, 如MD5、SHA1、HMAC等, 主要用于验证,防止信息被修改, 如:文件校验、数字签名、鉴权协议

AES:高级加密标准(Advanced Encryption Standard),又称Rijndael加密法,这个标准用来替代原先的DES。AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。

块:对明文进行加密的时候,先要将明文按照128bit进行划分。

填充方式:因为明文的长度不一定总是128的整数倍,所以要进行补位,我们这里采用的是PKCS7填充方式

AES实现的方式多样, 其中包括ECB、CBC、CFB、OFB等

1.电码本模式(Electronic Codebook Book (ECB))
将明文分组加密之后的结果直接称为密文分组。

2.密码分组链接模式(Cipher Block Chaining (CBC))
将明文分组与前一个密文分组进行XOR运算,然后再进行加密。每个分组的加解密都依赖于前一个分组。而第一个分组没有前一个分组,因此需要一个初始化向量

3.计算器模式(Counter (CTR))

4.密码反馈模式(Cipher FeedBack (CFB))
前一个密文分组会被送回到密码算法的输入端。
在CBC和EBC模式中,明文分组都是通过密码算法进行加密的。而在CFB模式中,明文分组并没有通过加密算法直接进行加密,明文分组和密文分组之间只有一个XOR。

5.输出反馈模式(Output FeedBack (OFB))

加密模式 对应加解密方法
CBC NewCBCDecrypter, NewCBCEncrypter
CTR NewCTR
CFB NewCFBDecrypter, NewCFBEncrypter
OFB NewOFB
// cbc模式
package main
import(
    "bytes"
    "crypto/aes"
    "fmt"
    "crypto/cipher"
    "encoding/base64"
)
func main() {
    orig := "hello world"
    key := "0123456789012345"
    fmt.Println("原文:", orig)
    encryptCode := AesEncrypt(orig, key)
    fmt.Println("密文:" , encryptCode)
    decryptCode := AesDecrypt(encryptCode, key)
    fmt.Println("解密结果:", decryptCode)
}
func AesEncrypt(orig string, key string) string {
    // 转成字节数组
    origData := []byte(orig)
    k := []byte(key)
    // 分组秘钥
    // NewCipher该函数限制了输入k的长度必须为16, 24或者32
    block, _ := aes.NewCipher(k)
    // 获取秘钥块的长度
    blockSize := block.BlockSize()
    // 补全码
    origData = PKCS7Padding(origData, blockSize)
    // 加密模式
    blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
    // 创建数组
    cryted := make([]byte, len(origData))
    // 加密
    blockMode.CryptBlocks(cryted, origData)
    return base64.StdEncoding.EncodeToString(cryted)
}
func AesDecrypt(cryted string, key string) string {
    // 转成字节数组
    crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
    k := []byte(key)
    // 分组秘钥
    block, _ := aes.NewCipher(k)
    // 获取秘钥块的长度
    blockSize := block.BlockSize()
    // 加密模式
    blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
    // 创建数组
    orig := make([]byte, len(crytedByte))
    // 解密
    blockMode.CryptBlocks(orig, crytedByte)
    // 去补全码
    orig = PKCS7UnPadding(orig)
    return string(orig)
}
//补码
//AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
    padding := blocksize - len(ciphertext)%blocksize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}
//去码
func PKCS7UnPadding(origData []byte) []byte {
    length := len(origData)
    unpadding := int(origData[length-1])
    return origData[:(length - unpadding)]
}
// ECB模式
package mysqlcrypto

import (
    "crypto/aes"
)

func AESEncrypt(src []byte, key []byte) (encrypted []byte) {
    cipher, _ := aes.NewCipher(generateKey(key))
    length := (len(src) + aes.BlockSize) / aes.BlockSize
    plain := make([]byte, length*aes.BlockSize)
    copy(plain, src)
    pad := byte(len(plain) - len(src))
    for i := len(src); i < len(plain); i++ {
        plain[i] = pad
    }
    encrypted = make([]byte, len(plain))
    // 分组分块加密 
    for bs, be := 0, cipher.BlockSize(); bs <= len(src); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
        cipher.Encrypt(encrypted[bs:be], plain[bs:be])
    }

    return encrypted
}

func AESDecrypt(encrypted []byte, key []byte) (decrypted []byte) {
    cipher, _ := aes.NewCipher(generateKey(key))
    decrypted = make([]byte, len(encrypted))
    // 
    for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
        cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
    }

    trim := 0
    if len(decrypted) > 0 {
        trim = len(decrypted) - int(decrypted[len(decrypted)-1])
    }

    return decrypted[:trim]
}

func generateKey(key []byte) (genKey []byte) {
    genKey = make([]byte, 16)
    copy(genKey, key)
    for i := 16; i < len(key); {
        for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
            genKey[j] ^= key[i]
        }
    }
    return genKey
}

区别

在 CBC 模式下,每个输入块都与前一个输出块进行异或,以确保相同的明文块对应的密文块不同。这可以有效地隐藏明文的结构信息,从而提高安全性。

在 ECB 模式下,每个输入块都是独立加密/解密的,没有与前一个输出块的关联。这意味着相同的明文块将对应相同的密文块,这可能会使得明文的结构信息更容易被恢复,因此安全性较低。

标签:AES,加密,len,明文,golang,分组,key,byte
From: https://www.cnblogs.com/Harley-Crystal/p/17028383.html

相关文章

  • golang面向对象思想和实现
    golang中并没有明确的面向对象的说法,实在要扯上的话,可以将struct比作其它语言中的class。类声明typePoemstruct{TitlestringAuthorstringintrostring}这......
  • golang web开发获取get、post、cookie参数
    在成熟的语言java、python、php要获取这些参数应该来讲都非常简单,过较新的语言golang用获取这些个参数还是费了不少劲,特此记录一下。golang版本:1.3.1在贴代码之前如果能......
  • 在线客服系统的源码中Golang Gin框架实现IP白名单机制
    我的客服系统有一些接口是专门给内部调用的,只允许其他内部系统来调用,不允许随意访问,可以使用IP白名单机制使用Gin框架实现IP白名单机制可以使用中间件的方式实现。你......
  • Go语言(golang)开源项目大全
    ​​http://www.open-open.com/lib/view/open1396063913278.html#Compression​​内容目录​​Astronomy​​​​构建工具​​​​缓存​​​​云计算​​​​命令行选项解......
  • 在线客服系统源码编译Golang语言下go build命令构建二进制程序
     gobuild 命令好处我开发了一套在线客服系统源码,使用了gobuild进行编译在我的在线客服系统使用gobuild命令的主要好处是,它可以将Go程序编译成可执行文件,这样就......
  • go-dongle 0.2.5 版本发布,一个轻量级、语义化的 golang 编码解码、加密解密库
    dongle是一个轻量级、语义化、对开发者友好的Golang编码解码和加密解密库Dongle已被awesome-go收录,如果您觉得不错,请给个star吧github.com/golang-module/dong......
  • [加密]公钥/私钥/数字签名理解
    公钥,私钥和数字签名一、公钥加密 假设一下,我找了两个数字,一个是1,一个是2。我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥。我有一个文件,不能让......
  • 使用Jmeter轻松实现AES加密测试
    每天进步一点点,关注我们哦,每天分享测试技术文章本文章出自【码同学软件测试】码同学公众号:自动化软件测试,领取资料可加:magetest码同学抖音号:小码哥聊软件测试大家在自......
  • golang linux/windows下根据日期自动备份,恢复mysql数据表
    由于shell不熟,所以用golang进行自动化备份mysql备份某个数据库下指定日期的表。比如’tb_20221210'这样的表名1packagemain23import(4"fmt"5......
  • 合并加密的m3u8
    0x01工具ffmpeg.exe如果没有则使用以下地址下载0x02m3u8格式我的m3u8内容是:#EXTM3U#EXT-X-VERSION:3#EXT-X-TARGETDURATION:6#EXT-X-PLAYLIST-TYPE:VOD#EXT-X-M......