我正在try 加密数据库中的一些文本,以便在程序启动期间加载和解密.

我try 过几种方法,包括第三方库https://github.com/richard-lyman/lithcrypt,但都没有用.使用以下方法对8/10项进行加密/解密,但似乎在加密/解密过程中的某个时间点留下了一些填充残留物.目前,我的代码如下:

package client                                                                                                                                                                                              
import (                                                                                                                                                                                                    
    "encoding/base64"                                                                                                                                                                                       
    "crypto/aes"                                                                                                                                                                                            
    "crypto/cipher"                                                                                                                                                                                         
    "fmt"                                                                                                                                                                                                   
) 

var iv = []byte{34, 35, 35, 57, 68, 4, 35, 36, 7, 8, 35, 23, 35, 86, 35, 23}

func encodeBase64(b []byte) string {                                                                                                                                                                        
    return base64.StdEncoding.EncodeToString(b)                                                                                                                                                             
}                                                                                                                                                                                                           

func decodeBase64(s string) []byte {                                                                                                                                                                        
    data, err := base64.StdEncoding.DecodeString(s)                                                                                                                                                         
    if err != nil { panic(err) }                                                                                                                                                                            
    return data                                                                                                                                                                                             
}                                                                                                                                                                                                           

func Encrypt(key, text string) string {                                                                                                                                                                     
    block, err := aes.NewCipher([]byte(key))                                                                                                                                                                
    if err != nil { panic(err) }                                                                                                                                                                            
    plaintext := []byte(text)                                                                                                                                                                               
    cfb := cipher.NewCFBEncrypter(block, iv)                                                                                                                                                                
    ciphertext := make([]byte, len(plaintext))                                                                                                                                                              
    cfb.XORKeyStream(ciphertext, plaintext)                                                                                                                                                                 
    return encodeBase64(ciphertext)                                                                                                                                                                         
}                                                                                                                                                                                                           

func Decrypt(key, text string) string {                                                                                                                                                                     
    block, err := aes.NewCipher([]byte(key))                                                                                                                                                                
    if err != nil { panic(err) }                                                                                                                                                                            
    ciphertext := decodeBase64(text)                                                                                                                                                                        
    cfb := cipher.NewCFBEncrypter(block, iv)                                                                                                                                                                
    plaintext := make([]byte, len(ciphertext))                                                                                                                                                              
    cfb.XORKeyStream(plaintext, ciphertext)                                                                                                                                                                 
}                          

有人告诉我,我可能需要填充字符串,但是我必须填充流密码,这似乎很奇怪.

以下是此错误的示例:http://play.golang.org/p/4FQBAeHgRs

推荐答案

这是以NewCFBEncrypter / NewCFBDecrypter examples为基础的,似乎可以满足您的要求:

编辑:根据Kluyg关于IV创建的 comments ,我修改了示例代码,以使用推荐的从密文创建IV的方法,与linked个示例从密文创建IV的方法相同.(在生产代码中,每次都应该单独生成IV.感谢RoundSparrow hilltx指出这一点.)

我认为您遇到的问题是由于密钥长度无效,但我不是100%确定.

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "encoding/base64"
    "errors"
    "fmt"
    "io"
    "log"
)

func main() {
    key := []byte("a very very very very secret key") // 32 bytes
    plaintext := []byte("some really really really long plaintext")
    fmt.Printf("%s\n", plaintext)
    ciphertext, err := encrypt(key, plaintext)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%0x\n", ciphertext)
    result, err := decrypt(key, ciphertext)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", result)
}

// See alternate IV creation from ciphertext below
//var iv = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}

func encrypt(key, text []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    b := base64.StdEncoding.EncodeToString(text)
    ciphertext := make([]byte, aes.BlockSize+len(b))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return nil, err
    }
    cfb := cipher.NewCFBEncrypter(block, iv)
    cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
    return ciphertext, nil
}

func decrypt(key, text []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    if len(text) < aes.BlockSize {
        return nil, errors.New("ciphertext too short")
    }
    iv := text[:aes.BlockSize]
    text = text[aes.BlockSize:]
    cfb := cipher.NewCFBDecrypter(block, iv)
    cfb.XORKeyStream(text, text)
    data, err := base64.StdEncoding.DecodeString(string(text))
    if err != nil {
        return nil, err
    }
    return data, nil
}

产生:

一些非常长的明文
54618bd6bb10612a7b590c53192df214501e01b685540b012581a0ed9ff3ddaa1f4177cc6186b501fb8cce0c2eb764daff475aab724d4d33e614d7d89cf556d8512fd920018c090f
一些非常长的明文

Playground

希望这有助于找出问题的症结所在.

Go相关问答推荐

你能帮我优化一个golang代码关于函数CrossPointTwoRect

CGO Linux到Windows交叉编译中的未知类型名称

有没有办法通过Go cmdline或IDE(IntelliJ)找出我的 struct 实现了什么接口?

如何将GoFr筛选器用于查询参数?

GO:如何指定类型约束,使S方法的参数类型与接收方的参数类型相同

使用Go使用Gorm使用外键对数据进行排序

如何使用中间件更改http请求的响应代码?

使用!NOT运算符的Golang文本/模板多个条件

exec的可执行决议.命令+路径

我怎样才能改进这个嵌套逻辑以使其正常工作并提高性能

该文件位于模块.内,该模块不包含在您的工作区中

如何将字节文件高效地读入int64切片?

io.Reader 无限循环与 fmt.Fscan

由于 main.go 文件中的本地包导入导致构建 docker 容器时出错

如何在时间范围内规范化数组的元素?

自定义指标未显示在 prometheus web ui 中,grafana 中也是如此

curl:(56)Recv失败:连接由golang中的对等方与docker重置

如何在 Unmarshal 中使用泛型(转到 1.18)

gob 解码器仅返回数组中的第一个元素

我该如何做错误处理惯用的方式