web-dev-qa-db-fra.com

Golang, chiffrant une chaîne avec AES et Base64

J'essaie de chiffrer du texte dans une base de données pour le charger et le déchiffrer au démarrage du programme.

J'ai essayé quelques méthodes, y compris une bibliothèque tierce https://github.com/richard-lyman/lithcrypt en vain. En utilisant la méthode suivante, chiffre/déchiffre 8/10 éléments, mais il semble qu’un résidu de remplissage soit laissé à un moment donné dans le chiffrement/déchiffrement. En l'état actuel de mon code est comme ceci:

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

On m'a dit que je devrais peut-être compléter la chaîne, mais il semble étrange que je devrais utiliser un code de flux. 

Voici un exemple de cette erreur: http://play.golang.org/p/4FQBAeHgRs

31
jawr

Ceci est basé sur les exemples NewCFBEncrypter/NewCFBDecrypter et semble faire ce que vous souhaitez:

EDIT: Sur la base du commentaire de Kluyg concernant la création d’IV, j’ai modifié l’exemple de code pour utiliser le méthode recommandée pour créer l'IV à partir du texte chiffré même méthode que l’exemple linked pour créer le vecteur IV à partir du texte chiffré. (Dans le code de production, l'IV doit être généré séparément à chaque fois. Merci à RoundSparrow hilltx pour l'avoir signalé.)

Je pense que le problème que vous rencontrez est dû à une longueur de clé non valide, mais je ne suis pas sûr à 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
}

Produit:

un texte clair vraiment très long
54618bd6bb10612a7b590c53192df214501e01b685540b012581a0ed9ff3ddaa1f4177cc6186b501fb8cce0c2eb764daff475aab724d4d33e614d7d89
un texte clair vraiment très long 

Cour de récréation

J'espère que cela aide à cerner le problème.

52
Intermernet

La crypto est difficile et les bibliothèques accessibles ne sont peut-être pas assez performantes, il est donc facile de faire des erreurs. 

Pour tous ceux qui recherchent un exemple de réussite d'un expert du domaine (développeur de sécurité chez CoreOS), voici un bon exemple du cryptage AES (ainsi que d'autres utilisations courantes de la cryptographie). 

https://github.com/gtank/cryptopasta

7
Kenny Grant

Voici la démonstration de travail que je viens de terminer, elle utilise principalement des exemples de code du document mais elle est conçue pour faire ce que la plupart des applications, y compris mon cas d'utilisation, attendent des méthodes de cryptage.

Il utilise le cryptage AES . Encrypt de chaîne en chaîne base64. Facile à utiliser sur les URL et dbs . Décrypter de la chaîne base64 créée ci-dessus au texte original.

Conversions de texte simples partout.

Gist: Voici le Gist, s'il vous plaît laissez-moi savoir si des améliorations sont nécessaires.

C'est un simple fichier go, prêt à être exécuté.

4
mamu

Il semble que votre ordre des opérations est un peu en arrière. Voici ce que vous semblez faire:

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

Cela devrait ressembler davantage à:

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

Ce qui suit fonctionne pour moi

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

Microservice de chiffrement symétrique (Blowfish) sur golang . https://github.com/kl09/encrypt

0
kl09