求一个 go 中的 aes 加密方法

要求如下:

str = `406BF0AD11310101220213481000320000`
key := `ER2Fb6ts3ECX`
通过 AES 加密(加解密算法 AES/工作模式 ECB /填充方式 NoPadding)并根据 base64
转码后字符串位:
rebZn7aj61hD3lfsUrhwFgVzPg4yYo9aseP/a4sNTRIh/Vtb0mziFfoHdOZBZ5uj

google一番,找到一些代码,试了试都不太对

package xaes

import (
    "bytes"
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "crypto/sha256"
    "encoding/base64"
    "errors"
)

type Aes struct {
    key []byte
}

func NewAes(key string) (*Aes) {
    if key == "" {
        panic("aes key empty")
    }
    sum := sha256.Sum256([]byte(key))
    return &Aes{
        key:sum[:],
    }
}

func (a *Aes) Encrypt(encodeBytes []byte) (val string, err error) {
    block, err := aes.NewCipher(a.key)
    if err != nil {
        return
    }
    blockSize := block.BlockSize()
    encodeBytes = zeroPadding(encodeBytes, blockSize)

    iv := make([]byte, blockSize)
    _,err = rand.Read(iv)
    if err != nil {
        return
    }

    blockMode := cipher.NewCBCEncrypter(block, iv)
    crypted := make([]byte, len(encodeBytes))
    blockMode.CryptBlocks(crypted, encodeBytes)

    iv = append(iv,crypted...)
    val = base64.StdEncoding.EncodeToString(iv)
    return
}


func (a *Aes) pkCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

func (a *Aes) Decrypt(decodeBytes []byte) (origData []byte,err error) {
    //decodeBytes, err := base64.StdEncoding.DecodeString(decodeStr)
    //if err != nil {
    //    return
    //}
    block, err := aes.NewCipher(a.key)
    if err != nil {
        return nil, err
    }
    if len(decodeBytes) < block.BlockSize() {
        err = errors.New("decodeBytes 长度不足")
        return
    }
    iv := decodeBytes[:block.BlockSize()]
    decodeBytes = decodeBytes[block.BlockSize():]

    blockMode := cipher.NewCBCDecrypter(block, iv)
    origData = make([]byte, len(decodeBytes))
    blockMode.CryptBlocks(origData, decodeBytes)
    origData = zeroUnPadding(origData)
    return
}

func (a *Aes) pkCS5UnPadding(origData []byte) []byte {
    length := len(origData)
    unpadding := int(origData[length-1])
    return origData[:(length - unpadding)]
}

func zeroPadding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padText := bytes.Repeat([]byte{0}, padding)
    return append(ciphertext, padText...)
}

func zeroUnPadding(origData []byte) []byte {
    return bytes.TrimFunc(origData,
        func(r rune) bool {
            return r == rune(0)
        })
}

调用方式

package main

import (
    "awesomeProject/xaes"
    "fmt"
)

func main()  {
    str := []byte("406BF0AD11310101220213481000320000")
    xa := xaes.NewAes("ER2Fb6ts3ECX")
    b,e:=xa.Encrypt(str)
    if e != nil{
        fmt.Println(e.Error())
        return
    }
    fmt.Println(b)
}
阅读 2.9k
2 个回答
package main

import (
    "crypto/aes"
    "encoding/base64"
    "log"
)

func main() {
    origin := []byte("406BF0AD11310101220213481000320000")
    key := []byte("ER2Fb6ts3ECX")

    encrypted := AesEncryptECB(origin, key)
    log.Println("encrypted: ", encrypted)
    decrypted := AesDecryptECB(encrypted, key)
    log.Println("decrypted: ", string(decrypted))
}

func AesEncryptECB(origData []byte, key []byte) string {
    cipher, _ := aes.NewCipher(generateKey(key))
    length := (len(origData) + aes.BlockSize) / aes.BlockSize
    plain := make([]byte, length*aes.BlockSize)
    copy(plain, origData)

    encrypted := make([]byte, len(plain))
    // Block encryption
    for bs, be := 0, cipher.BlockSize(); bs <= len(origData); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
        cipher.Encrypt(encrypted[bs:be], plain[bs:be])
    }

    return base64.StdEncoding.EncodeToString(encrypted)
}

func AesDecryptECB(str string, key []byte) (decrypted []byte) {
    encrypted, _ := base64.StdEncoding.DecodeString(str)

    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
}

首先要说给你提供这个算法的人压根就不懂密码学。

因为 AES 的要求密钥的字节长度是 64 的倍数,可以是 128、192、256 等等(64 位因为不够安全已经被废弃),当成 ASCII 字符串的话长度就是 16 的倍数。随便给个字符串那不叫密钥,天知道对方用的编程语言或加密库是怎么处理这种不合法的密钥的 —— 是前补 0 了、是前补空了、是后补 0 了、是后补空了、还是怎么着?

而因为密钥的字节长度不确定,所以加密时的一个重要参数 BlockSize 也就不确定了。

得,靠猜吧。当成后补空吧。


下面是答案:

package main

import(
    "fmt"
    "crypto/aes"
    "encoding/base64"
)

func AesEcbEncryptWithNoPadding(plaintext string, key string) (result string, err error){
    plainData := []byte(plaintext)
    keyData := []byte(key)
    
    formattedPlainData := AesFormatPlainDataWithNoPadding(plainData, aes.BlockSize)
    formattedKeyData := AesFormatKeyData(keyData, aes.BlockSize)
    
    cipher, err := aes.NewCipher(formattedKeyData);
    if err != nil {
        return "", err
    }
    
    blockSize := cipher.BlockSize();
    cipherData := make([]byte, len(formattedPlainData))
    for bs, be := 0, blockSize; bs <= len(plainData); bs, be = bs + blockSize, be + blockSize {
        cipher.Encrypt(cipherData[bs:be], formattedPlainData[bs:be])
    }

    return base64.StdEncoding.EncodeToString(cipherData), nil
}

func AesFormatKeyData(keyData []byte, blockSize int) ([]byte) {
    result := make([]byte, blockSize)
    copy(result, keyData)
    
    for i := blockSize; i < len(keyData); {
        for j := 0; j < blockSize && i < len(keyData); j, i = j + 1, i + 1 {
            result[j] ^= keyData[i]
        }
    }
    
    return result
}

func AesFormatPlainDataWithNoPadding(plainData []byte, blockSize int) ([]byte) {
    length := (len(plainData) + blockSize) / blockSize
    result := make([]byte, length * blockSize)
    copy(result, plainData)
    return result
}

func main(){
    plaintext := "406BF0AD11310101220213481000320000"
    secretkey := "ER2Fb6ts3ECX"
    
    encodedCipher, err := AesEcbEncryptWithNoPadding(plaintext, secretkey)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("AES-CBC-NoPadding 加密结果\n明文:%s\n密文:%s", plaintext, encodedCipher)
}

执行结果:

image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题