douju9272 2014-08-23 13:15
浏览 64
已采纳

兼容AES CFB

I am developing a client-side app in Go that relies on AES CFB. The server-side is written in C. My problem is that Go's AES CFB implementation appears to differ from many others (including OpenSSL). I wrote this to test my theory:-

package main

import (
  "fmt"
  "encoding/hex"
  "crypto/cipher"
  "crypto/aes"
)

func encrypt_aes_cfb(plain, key, iv []byte) (encrypted []byte) {
  block, err := aes.NewCipher(key)
  if err != nil {
    panic(err)
  }
  encrypted = make([]byte, len(plain))
  stream := cipher.NewCFBEncrypter(block, iv)
  stream.XORKeyStream(encrypted, plain)
  return
}

func decrypt_aes_cfb(encrypted, key, iv []byte) (plain []byte) {
  block, err := aes.NewCipher(key)
  if err != nil {
    panic(err)
  }
  plain = make([]byte, len(encrypted))
  stream := cipher.NewCFBDecrypter(block, iv)
  stream.XORKeyStream(plain, encrypted)
  return
}

func main() {
  plain := []byte("Hello world.....")
  key := []byte("01234567890123456789012345678901")
  iv := []byte("0123456789012345")
  enc := encrypt_aes_cfb(plain, key, iv)
  dec := decrypt_aes_cfb(enc, key, iv)
  fmt.Println("Key: ", hex.EncodeToString(key))
  fmt.Println("IV:  ", hex.EncodeToString(iv))
  fmt.Println("Enc: ", hex.EncodeToString(enc))
  fmt.Println("In:  ", hex.EncodeToString(plain))
  fmt.Println("Out: ", hex.EncodeToString(dec))
}

When this is run, it appears to work perfectly, however, if the encrypted bytes are pasted into another AES implementation and decrypted using the same key and IV, the plaintext is corrupted (except for the first Byte). http://aes.online-domain-tools.com/ provides a simple means to test this. Any suggestions why this might be happening and how I can resolve it?

Thanks Steve

  • 写回答

2条回答 默认 最新

  • douhu2370 2014-08-23 14:43
    关注

    I investigated this with the following inputs because I was unsure of the bit/byte order for both inputs and outputs :

    Key:  00000000000000000000000000000000
    IV:   00000000000000000000000000000000
    Enc:  66
    In:   00
    Out:  00
    

    http://play.golang.org/p/wl2y1EE6lK

    Which matches the tool you provided, and then this :

    Key:  00000000000000000000000000000000
    IV:   00000000000000000000000000000000
    Enc:  66e94b
    In:   000000
    Out:  000000
    

    http://play.golang.org/p/DNC42m2oU5

    Which doesn't match the tool :

    6616f9
    

    http://aes.online-domain-tools.com/link/63687gDNzymApefh/

    The first byte matches, which indicates there may be a feedback issue.

    So I checked the Go package's code and I think there is a bug here :

    func (x *cfb) XORKeyStream(dst, src []byte) {
        for len(src) > 0 {
            if x.outUsed == len(x.out) {
                x.b.Encrypt(x.out, x.next)
                x.outUsed = 0
            }
    
            if x.decrypt {
                // We can precompute a larger segment of the
                // keystream on decryption. This will allow
                // larger batches for xor, and we should be
                // able to match CTR/OFB performance.
                copy(x.next[x.outUsed:], src)
            }
            n := xorBytes(dst, src, x.out[x.outUsed:])
            if !x.decrypt {
                copy(x.next[x.outUsed:], dst) // BUG? `dst` should be `src`
            }
            dst = dst[n:]
            src = src[n:]
            x.outUsed += n
        }
    }
    

    EDIT

    After a second look at CFB mode it seems that Go's code is fine, so yeah it may be the other implementations are wrong.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?