Impossible de déchiffrer après AES-GCM + Base64 dans Go

Florian Harwoeck:

Situation

J'essaie d'implémenter une structure (le CryptoService) cachant en / décryptage du flux principal du programme. J'ai implémenté des fonctions "normales" et des variantes en base64 qui devraient coder le chiffrement en son équivalent en base64 et vice-versa lors du déchiffrement. Ceci est fait parce que notre protocole de réseau interne utilise le saut de ligne \ncomme délimiteur.

Voir code d'implémentation ci-dessous

Problème

Après avoir écrit le code ci-dessous, j'ai commencé à le tester. Au début , il est bien passé et a fonctionné et le déchiffrement en- mais bientôt je commencé à remarquer des erreurs « apparaissant au hasard » au cours du processus de décryptage: cipher: message authentication failed. Maintenant, le fait important: les erreurs retournées UNIQUEMENT par le DecryptBase64func. Mais l'utilisation de base64 dans go est assez simple et il n'y a pas grand-chose à craindre, donc je n'ai aucune idée d'où se trouvent les problèmes.

Code

Ci-dessous, vous voyez le code de mon CryptoServiceimplémentation et le fichier de test associé. J'ai essayé de nettoyer le code autant que possible (supprimer les commentaires, les vérifications d'entrée supplémentaires, etc.) sans supprimer le contexte. Néanmoins, c'est beaucoup de code, donc merci à tous ceux qui l'ont lu - appréciez vraiment votre aide!

cryptoservice.go

type CryptoService struct {
    gcm cipher.AEAD
}

func NewCryptoService(key []byte) (cs *CryptoService, err error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }
    return &CryptoService{
        gcm: gcm,
    }, nil
}

func (cs CryptoService) Encrypt(plain []byte) (cipher []byte, err error) {
    nonce := make([]byte, cs.gcm.NonceSize())
    _, err = io.ReadFull(rand.Reader, nonce)
    if err != nil {
        return nil, err
    }

    cipher = cs.gcm.Seal(nil, nonce, plain, nil)
    cipher = append(nonce, cipher...)

    return cipher, nil
}

func (cs CryptoService) EncryptBase64(plain []byte) (base64Cipher []byte, err error) {
    cipher, err := cs.Encrypt(plain)
    if err != nil {
        return nil, err
    }

    base64Cipher = make([]byte, base64.StdEncoding.EncodedLen(len(cipher)))
    base64.StdEncoding.Encode(base64Cipher, cipher)

    return
}

func (cs CryptoService) Decrypt(cipher []byte) (plain []byte, err error) {
    nonce := cipher[0:cs.gcm.NonceSize()]
    ciphertext := cipher[cs.gcm.NonceSize():]

    plain, err = cs.gcm.Open(nil, nonce, ciphertext, nil)
    if err != nil {
        return nil, err
    }

    return
}

func (cs CryptoService) DecryptBase64(base64Cipher []byte) (plain []byte, err error) {
    cipher := make([]byte, base64.StdEncoding.DecodedLen(len(base64Cipher)))
    _, err = base64.StdEncoding.Decode(cipher, base64Cipher)
    if err != nil {
        return nil, err
    }

    return cs.Decrypt(cipher)
}

cryptoservice_test.go

  • TestCryptoService_EncryptDecryptRoundtrip fonctionne bien
  • TestCryptoService_EncryptBase64DecryptBase64Roundtrip échoue "parfois" (notez également qu'il n'échoue pas toujours sur les mêmes cas de test)

Informations supplémentaires: La FastRandomString(n int)fonction de création de cas de test dynamique n'est en fait qu'un copier-coller de la réponse acceptée à: Comment générer une chaîne aléatoire d'une longueur fixe en golang?

func TestCryptoService_EncryptDecryptRoundtrip(t *testing.T) {
    tests := []struct {
        name   string
        aeskey string
        text   string
    }{
        {"Simple 1", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", "Text"},
        {"Simple 2", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", "Some random content"},
        {"Simple 3", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."},

        {"Dynamic 1", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(32)},
        {"Dynamic 2", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(1024)},
        {"Dynamic 3", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(1024 * 64)},
        {"Dynamic 4", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(1024 * 256)},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            for i := 0; i < 1000; i++ {
                key, _ := hex.DecodeString(tt.aeskey)
                cs, _ := NewCryptoService(key)
                cipher, err := cs.Encrypt([]byte(tt.text))
                if err != nil {
                    t.Errorf("CryptoService.Encrypt() error = %v", err)
                    return
                }

                plain, err := cs.Decrypt(cipher)
                if err != nil {
                    t.Errorf("CryptoService.Decrypt() error = %v", err)
                    return
                }

                plainStr := string(plain)
                if plainStr != tt.text {
                    t.Errorf("CryptoService.Decrypt() plain = %v, want = %v", plainStr, tt.text)
                    return
                }
            }
        })
    }
}

func TestCryptoService_EncryptBase64DecryptBase64Roundtrip(t *testing.T) {
    tests := []struct {
        name   string
        aeskey string
        text   string
    }{
        {"Simple 1", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", "Text"},
        {"Simple 2", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", "Some random content"},
        {"Simple 3", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."},

        {"Dynamic 1", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(32)},
        {"Dynamic 2", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(1024)},
        {"Dynamic 3", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(1024 * 64)},
        {"Dynamic 4", "c4cc0dfc4ae0e45c045727f84ffd373127453bc232230bf1386972ac692436c1", FastRandomString(1024 * 256)},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            for i := 0; i < 1000; i++ {
                key, _ := hex.DecodeString(tt.aeskey)
                cs, _ := NewCryptoService(key)
                cipher, err := cs.EncryptBase64([]byte(tt.text))
                if err != nil {
                    t.Errorf("CryptoService.EncryptBase64() error = %v", err)
                    return
                }

                plain, err := cs.DecryptBase64(cipher)
                if err != nil {
                    t.Errorf("CryptoService.DecryptBase64() error = %v", err)
                    return
                }

                plainStr := string(plain)
                if plainStr != tt.text {
                    t.Errorf("CryptoService.DecryptBase64() plain = %v, want = %v", plainStr, tt.text)
                    return
                }
            }
        })
    }
}
Florian Harwoeck:

Un membre de la communauté GopherSlack a proposé la solution:

StdEncodingtampons ses résultats qui dans ce cas provoquaient des problèmes de décryptage lorsque (pendant le processus de cryptage) un remplissage de la sortie était nécessaire. Par conséquent, vous devez utiliser RawStdEncodingdans cet exemple.

Merci pour l'aide! :)

Cet article est collecté sur Internet, veuillez indiquer la source lors de la réimpression.

En cas d'infraction, veuillez [email protected] Supprimer.

modifier le
0

laisse moi dire quelques mots

0commentaires
connexionAprès avoir participé à la revue

Articles connexes

Impossible de déchiffrer le GCM AES-256 avec Java

Impossible de déchiffrer (AES) dans iOS (Swift) à partir de Java

Impossible de déchiffrer la chaîne cryptée AES

impossible de déchiffrer le texte chiffré AES256

Chiffrer dans le front-end JS et déchiffrer dans le backend python à l'aide d'AES GCM

Impossible de déchiffrer le texte xor-base64

impossible d'utiliser l'image base64 de css dans la balise img

Impossible de convertir le chemin base64 en chemin d'image dans Ionic 4

Impossible de lire une image Bitmap que je viens d'enregistrer dans Base64

Problèmes avec le cryptage AES. impossible de déchiffrer avec une clé droite

Impossible de déchiffrer le texte chiffré donné deux fois avec le même objet AES

Gestion des erreurs de décodage base64 dans Go

Impossible de décrypter les données dans NodeJS qui sont cryptées à l'aide de Swift CryptoKit - AES-256-GCM

incapable de déchiffrer les données en arbre qui est crypté en Java en utilisant AES-GCM-256

Décryptage AES lors de l'écriture dans un fichier à l'aide du codage base64

JS: décryptage impossible après stockage dans la base de données (SJCL)

Impossible de récupérer les métadonnées DICOM après le décodage à partir de la chaîne base64

Impossible d'insérer une chaîne base64 dans une colonne de type de données clob

Comment déchiffrer un texte chiffré dans Go qui est chiffré dans vuejs à l'aide du package aes-js

AES CBC Pas de remplissage donne des caractères supplémentaires dans déchiffrer JAVa

impossible d'exécuter le programme de test go après l'installation de go lang

Impossible de décoder la chaîne base64 en uiimage dans iOS Swift mais fonctionne correctement sous Android

impossible de stocker les données d'image base64 dans Cassandra à l'aide du pilote cassandra

Impossible d'ajouter la clé publique base64 dans la nouvelle version du service de facturation

H2 - impossible d'écrire dans la base de données dans le déclencheur 'après insertion'

Dérivation de clé AES GCM rapide

Impossible d'enregistrer le jeton auprès de GCM

Comment déchiffrer les données à partir du résultat d'une opération de chiffrement IE 11 à l'aide d'AES-GCM

Impossible de nous GCM dans mon pays

TOP liste

  1. 1

    Comment changer le navigateur par défaut en Microsoft Edge pour Jupyter Notebook sous Windows 10 ?

  2. 2

    Enregistrer le chemin de l'image de la galerie vers la base de données de la salle et l'afficher dans la liste des recycleurs

  3. 3

    Microsoft.WebApplication.targets

  4. 4

    knn classification 10 plis de l'outil et du tri

  5. 5

    Créer un système Buzzer à l'aide de python

  6. 6

    Quelle est la relation entre le modèle et le tableau ? C'est compliqué

  7. 7

    AutoMapper.Collection.EFCore - Erreur générée lors de la configuration

  8. 8

    comment supprimer "compte de connexion google" à des fins de développement - actions sur google

  9. 9

    Fonction de puissance en Java

  10. 10

    Je continue à obtenir l'objet 'WSGIRequest' n'a pas d'attribut 'Get' sur django

  11. 11

    Spring @RequestParam DateTime format comme ISO 8601 Date Heure facultative

  12. 12

    Comment remplir les valeurs manquantes avec plusieurs colonnes dans R

  13. 13

    Comment puis-je ajouter un UIView sous mon contrôleur de barre d'onglets par programme?

  14. 14

    Comment créer un bot à compte à rebours dans Discord en utilisant Python

  15. 15

    Sélectionnez le bouton radio sur la saisie de texte

  16. 16

    Comment rechercher des éléments dans une ArrayList? - Java

  17. 17

    opérations en virgule flottante dans go

  18. 18

    Yat-il un référentiel maven application Java à démarrer rapidement 11

  19. 19

    Placez le modeBar en haut au centre à l'aide de plotly.js

  20. 20

    Comment définir la couleur de l'intersection dans un diagramme de Venn?

  21. 21

    Récupérer plusieurs dépôts git dans le même espace de travail Jenkins

chaudétiquette

Archive