Подтвердить что ты не робот

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

4b9b3361

Ответ 1

Это основано на NewCFBEncrypter/NewCFBDecrypter примерах и, похоже, делает то, что вам нужно:

EDIT: на основе комментария 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
}

Выдает:

какой-то действительно действительно очень длинный открытый текст 54618bd6bb10612a7b590c53192df214501e01b685540b012581a0ed9ff3ddaa1f4177cc6186b501fb8cce0c2eb764daff475aab724d4d33e614d7d89cf556d8512fd920018c090f
действительно действительно очень длинный открытый текст

Игровая площадка

Надеюсь, что это поможет определить проблему.

Ответ 2

Вот рабочая демонстрация, которую я только что закончил писать, она в основном использует образцы кода из документа go, но она предназначена для того, чтобы делать то, что большинство приложений, включая мой прецедент, ожидает от методов шифрования.

Он использует шифрование AES. шифровать строку из строки в base64. Прост в использовании по URL и dbs. расшифровать строку base64, созданную выше, до исходного текста.

Простые преобразования текста везде.

GIST: вот суть, пожалуйста, дайте мне знать, если есть какие-либо улучшения.

Это простой файл go, готовый к запуску.

Ответ 3

Crypto жестко, и библиотеки go, возможно, недостаточно высоки, поэтому легко ошибаться.

Для тех, кто ищет пример того, как это делает эксперт в этой области (разработчик безопасности в CoreOS), это дает хороший пример шифрования AES (наряду с другими распространенными криптовальными применениями).

https://github.com/gtank/cryptopasta

Ответ 4

Кажется, ваш порядок операций немного назад. Вот что вы делаете:

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)
}