Golang,使用AES和Base64加密字符串

jaw*_*awr 33 encryption base64 aes go

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

我尝试了一些方法,包括第三方库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)                                                                                                                                                                 
}                          
Run Code Online (Sandbox Code Playgroud)

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

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

Int*_*net 53

这基于NewCFBEncrypter/NewCFBDecrypter示例,似乎可以满足您的需求:

编辑:根据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
}
Run Code Online (Sandbox Code Playgroud)

生产:

一些真的真的真的很长的明文
54618bd6bb10612a7b590c53192df214501e01b685540b012581a0ed9ff3ddaa1f4177cc6186b501fb8cce0c2eb764daff475aab724d4d33e614d7d89cf556d8512fd920018c090f
一些真的真的真的很长的明文

操场

希望有助于确定问题所在.

  • 我只想指出base64在加密之前对数据进行编码没有任何意义.此外,额外的处理将降低性能,base64的数据增加大约33%.在最初的问题中,加密和解密函数处理文本,因此加密数据需要在返回之前进行编码.这里定义的函数处理[]字节,因此没有理由对数据进行base64编码. (2认同)

Ken*_*ant 8

加密很难,go库可能不够高,所以很容易出错.

对于那些正在寻找由该领域的专家(CoreOS的安全开发人员)来做正确的例子的人来说,这给出了AES加密的一个很好的例子(以及加密的其他常见用法).

https://github.com/gtank/cryptopasta