使用 AES 和 Base64 加密字符串

新手上路,请多包涵

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

我尝试了几种方法,包括第三方库 https://github.com/richard-lyman/lithcrypt 都无济于事。使用以下方法加密/解密 810 项,但似乎在加密/解密的某个时刻留下了一些填充残留物。就目前而言,我的代码是这样的:

 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

原文由 jawr 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 599
2 个回答

这是基于 NewCFBEncrypter / NewCFBDecrypter examples 并且似乎可以满足您的要求:

编辑:根据 Kluyg 关于 IV 创建的评论,我修改了示例代码以使用从密文创建 IV 的推荐方法,与从密文创建 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
}

生产:

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

54618bd6bb10612a7b590c53192df214501e01b685540b012581a0ed9ff3ddaa1f4177cc6186b501fb8cce0c2eb764daff475aab724d4d33e614d7d89cf556d85128fc920

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

操场

希望这有助于查明问题所在。

原文由 Intermernet 发布,翻译遵循 CC BY-SA 3.0 许可协议

加密很难,而且 go 库可能不够高级,所以很容易出错。

对于正在寻找该领域专家(CoreOS 的安全开发人员)正确执行此操作的示例的任何人,这提供了一个很好的 AES 加密示例(以及加密的其他常见用途)。

https://github.com/gtank/cryptopasta

原文由 Kenny Grant 发布,翻译遵循 CC BY-SA 3.0 许可协议

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