web-dev-qa-db-ja.com

Golang、AESおよびBase64で文字列を暗号化

データベース内のテキストを暗号化して、プログラムの起動時にロードおよび復号化しようとしています。

サードパーティのライブラリを含むいくつかの方法を試しました 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

32
jawr

これは NewCFBEncrypter/NewCFBDecrypterの例 に基づいており、必要なことを行うようです:

編集:IV作成に関するKluygのコメントに基づいて、使用するようにサンプルコードを変更しました 暗号文からIVを作成する推奨方法 暗号文からIVを作成する linked の例と同じ方法。 (製品コードでは、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
いくつかの本当に本当に本当に長い平文

プレイグラウンド

問題を特定するのに役立つことを願っています。

53
Intermernet

暗号は難しく、goライブラリはおそらく十分に高レベルではないので、間違いを犯しやすいです。

この分野の専門家(CoreOSのセキュリティ開発者)が適切に実行する例を探している人にとっては、これは(暗号の他の一般的な使用と一緒に)AES暗号化の良い例を示しています。

https://github.com/gtank/cryptopasta

7
Kenny Grant

ここに書いたばかりの作業デモがあります。ほとんどはgoドキュメントのコードサンプルを使用しますが、私のユースケースを含むほとんどのアプリが暗号化方式に期待することを行うように調整されています。

AES暗号化を使用します。文字列からbase64文字列に暗号化します。 URLとデータベースで使いやすい。上記で作成したbase64文字列から元のテキストに復号化します。

どこでも簡単なテキスト変換。

要点:ここに要点があります。改善の必要があるかどうか教えてください。

これは簡単なgoファイルで、すぐに実行できます。

4
mamu

操作の順序が少し逆になっているようです。あなたがしているように見えるものは次のとおりです。

ct = encrypt(encode(pt))
pt = decode(decrypt(ct))

次のようになります。

ct = encode(encrypt(pt))
pt = decrypt(decode(ct))

私のために次の作品

func Encrypt(key, text []byte) string {
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }
    ciphertext := make([]byte, aes.BlockSize+len(text))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(crand.Reader, iv); err != nil {
        panic(err)
    }
    cfb := cipher.NewCFBEncrypter(block, iv)
    cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)
    return encodeBase64(ciphertext)
}


func Decrypt(key []byte, b64 string) string {
    text := decodeBase64(b64)
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }
    if len(text) < aes.BlockSize {
        panic("ciphertext too short")
    }
    iv := text[:aes.BlockSize]
    text = text[aes.BlockSize:]
    cfb := cipher.NewCFBDecrypter(block, iv)
    cfb.XORKeyStream(text, text)
    return string(text)
}
3
user79854

Golangの対称暗号化(Blowfish)のマイクロサービス。 https://github.com/kl09/encrypt

0
kl09