如何解码AES-256-CFB?

当我使用openssl命令时,我有一个用aes-256-cfb编码的文件

openssl enc -d -aes-256-cfb -salt -pbkdf2 -pass file:encpass -out x.txz -in encpkg

这个文件被解密没有任何问题,但当我try 用Golang解密这个文件时,我总是得到错误的文件,我不知道我的问题是什么,我希望得到帮助

我的代码是:

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha256"
    "log"
    "os"
)

func main() {
    fiencpkg, err := os.ReadFile("encpkg")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }

    fiencpass, err := os.ReadFile("encpass")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }

    keyb := sha256.Sum256(fiencpass)
    block, err := aes.NewCipher(keyb[:])
    if err != nil {
        panic(err)
    }

    if len(fiencpkg) < aes.BlockSize {
        panic("data too short")
    }

    iv := fiencpkg[:aes.BlockSize]
    decdata := fiencpkg[aes.BlockSize:]
    stream := cipher.NewCFBDecrypter(block, iv)

    stream.XORKeyStream(decdata, fiencpkg[aes.BlockSize:])
    os.WriteFile("x_go.txz", decdata, 0777)

}

推荐答案

OpenSSL语句中的-pbkdf2 option导致使用PBKDF2密钥派生:
在加密过程中,将生成一个随机的8字节SALT,并与密码一起使用此密钥派生来确定密钥和IV.
由于解密需要SALT,因此OpenSSL语句将SALT和密文连接在一起,并使用前缀Salted__表示这一点.

因此,在解密过程中,必须首先将盐和密文分开:

salt := fiencpkg[8:16]
ciphertext := fiencpkg[16:]

则密钥和IV可以通过PBKDF2使用例如pbkdf2 package:

keyIv := pbkdf2.Key(fiencpass, salt, 10000, 48, sha256.New)
key := keyIv[0:32]
iv := keyIv[32:48]

注意迭代计数和摘要的OpenSSL default valuesOpenSSL default values00和SHA256.由于加密是使用AES-256-CFB完成的,因此必须生成48字节(32字节用于密钥,16字节用于IV).

在确定KEY和IV之后,可以照常进行解密.


完整代码:

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha256"
    "log"
    "os"
    
    "golang.org/x/crypto/pbkdf2"
)

func main() {
    fiencpkg, err := os.ReadFile("encpkg")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }

    salt := fiencpkg[8:16]
    ciphertext := fiencpkg[16:]

    fiencpass, err := os.ReadFile("encpass")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }

    keyIv := pbkdf2.Key(fiencpass, salt, 10000, 48, sha256.New)
    key := keyIv[0:32]
    iv := keyIv[32:48]

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    stream := cipher.NewCFBDecrypter(block, iv)
    stream.XORKeyStream(ciphertext, ciphertext)
    os.WriteFile("x_go.txz", ciphertext, 0777)
}

Go相关问答推荐

try 用GitHub操作中的release标签更新version. go文件,但失败了

Go PQ驱动程序无法使用默认架构进行查询

Go-Colly:将数据切片为POST请求

Golang使用Run()执行的命令没有返回

创建服务时云运行触发器执行失败

使用Golang的Lambda自定义al2运行时,初始化阶段超时

理解Golang中的IOTA和常量

如何解析Go-Gin多部分请求中的 struct 切片

这种合并排序的实现有什么问题?

用接口来模拟amqp091go的困难

如何解决构建Docker Compose时的权限被拒绝问题

Golang 中具体类型的错误片段

动态 SQL 集 Golang

在恒等函数中将类型 T 转换为类型 U

来自洪流公告的奇怪同行字段

Golang并发写入多个文件

Golang Echo Labstack 如何在模板视图中调用函数/方法

Go 赋值涉及到自定义类型的指针

如何访问Go 1.18泛型 struct (structs)中的共享字段

Gorilla/Mux 和 Websocket 竞赛条件,这安全吗?