Maison > développement back-end > Golang > Pourquoi Go et Pycrypto produisent-ils des textes chiffrés différents lors de l'utilisation d'AES-CFB, et comment cela peut-il être résolu ?

Pourquoi Go et Pycrypto produisent-ils des textes chiffrés différents lors de l'utilisation d'AES-CFB, et comment cela peut-il être résolu ?

Susan Sarandon
Libérer: 2024-12-07 15:37:10
original
608 Les gens l'ont consulté

Why do Go and Pycrypto produce different ciphertexts when using AES-CFB, and how can this be resolved?

Différents résultats dans Go et Pycrypto lors de l'utilisation d'AES-CFB

Le problème présenté ici concerne le cryptage de données à l'aide d'AES-CFB avec Go et Pycrypto , ce qui donne lieu à des textes chiffrés différents. Les exemples Python et Go fournis utilisent des clés, des IV et des textes en clair identiques, mais produisent des données chiffrées très distinctes :

Python : dbf6b1877ba903330cb9cf0c4f530d40bf77fe2bf505820e993741c7f698ad6b
Go : db70cd9e6904359cb848410bfa38d7d0a47b594f7eff72d547d3772c9d4f5dbe

Chaque langue peut déchiffrer son propre texte chiffré mais ne parvient pas à déchiffrer la sortie de l'autre, ce qui gêne interopérabilité.

Résolution

La disparité provient des différentes tailles de segments de bits utilisées pour le mode CFB par Python et Go. Python utilise CFB8, où les données sont traitées par segments de 8 bits, tandis que l'implémentation par défaut de Go traite les données par blocs de 128 bits.

Pour résoudre le problème et garantir que Go puisse déchiffrer les textes chiffrés cryptés à l'aide des paramètres AES-CFB de Pycrypto, il faut modifier CFBEncrypter / CFBDecrypter de Go pour être compatible avec les segments 8 bits. L'exemple Go fourni s'appuie sur le code de ces fonctions pour effectuer le chiffrement CFB.

Cette personnalisation implique :

  1. La mise en œuvre d'une fonction NewCFBDecrypter personnalisée qui définit la taille du segment à 8. :

    func NewCFBDecrypter(block cipher.Block, iv []byte) cipher.Stream {
     if len(block.BlockSize()) != aes.BlockSize {
         panic("cipher: NewCFBDecrypter: invalid block size")
     }
     cfb := cfbDecrypter{
         blockSize:  block.BlockSize(),
         iv:         iv,
         segmentSize: 8,
         enc:        block,
         ofb:        copyBlock(block),
     }
     resetOfb(&cfb)
     return &cfb
    }
    Copier après la connexion
  2. Modification de la fonction XORKeyStream pour traiter les données dans Morceaux de 8 bits au lieu de blocs de 128 bits :

    func (x *cfbDecrypter) XORKeyStream(dst, src []byte) {
     dst = dst[:len(src)]
     switch {
     case len(src) == 0:
         return
     case len(src) < x.segmentSize:
         x.segBuf[0:len(src)] = src
         x.segPos = len(src)
     default:
         segmentSize := x.segmentSize
         for i := 0; i < len(src)-segmentSize+1; i += segmentSize {
             j := i + segmentSize
             xorBytes(dst[i:j], src[i:j], x.iv[x.segI:])
             x.encryptLogical(x.iv[x.segI:], x.segBuf[:segmentSize])
             copy(x.iv[x.segI:], dst[i:j])
             x.segI += segmentSize
             if x.segI >= x.blockSize {
                 x.segI = 0
             }
         }
         n := len(src) - len(src)%x.segmentSize
         x.segBuf[0:len(src[n:])] = src[n:]
         x.segPos = len(src[n:])
     }
    }
    Copier après la connexion

Avec ces modifications, l'exemple Go devrait produire le même texte chiffré que l'implémentation Python :

payload, err1 := hex.DecodeString("abababababababababababababababababababababababababababababababab")
password, err2 := hex.DecodeString("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
iv, err3 := hex.DecodeString("00000000000000000000000000000000")

if err1 != nil {
    fmt.Printf("error 1: %v", err1)
    return
}

if err2 != nil {
    fmt.Printf("error 2: %v", err2)
    return
}

if err3 != nil {
    fmt.Printf("error 3: %v", err3)
    return
}

aesBlock, err4 := aes.NewCipher(password)
iv = iv[0:aes.BlockSize] // Trim the IV if it's longer than the AES block size

fmt.Printf("IV length:%v\n", len(iv))
fmt.Printf("password length:%v\n", len(password))

if err4 != nil {
    fmt.Printf("error 4: %v", err4)
    return
}

cfbDecrypter := cipher.NewCFBDecrypter(aesBlock, iv)
cfbDecrypter.XORKeyStream(payload, payload)

fmt.Printf("%v\n", hex.EncodeToString(payload)) // dbf6b1877ba903330cb9cf0c4f530d40bf77fe2bf505820e993741c7f698ad6b
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal