kcp-go icon indicating copy to clipboard operation
kcp-go copied to clipboard

encrypt时并发读写同一个block的encbuf导致重传或超时

Open histalk opened this issue 5 years ago • 3 comments

type aesBlockCrypt struct {
	encbuf [aes.BlockSize]byte
	decbuf [2 * aes.BlockSize]byte
	block  cipher.Block
}
block, _ = kcp.NewAESBlockCrypt(aesKey)
listener, err := kcp.ListenWithOptions(port, block, 0, 0)

由于listener使用了同一个block的encbuf进行encrypt,当多个updSession同时output给客户端时,会并发调用Encrypt,导致encbuf同时被多个goroute读写,encrypt后的数据不对,客户端校验数据失败导致重传或超时

histalk avatar Sep 03 '20 02:09 histalk

后面文档说明一下不能并发

xtaci avatar Sep 08 '20 14:09 xtaci

func TestEncrypt(t *testing.T) {
	block, _ := kcp.NewAESBlockCrypt(make([]byte, 32))

	src := make([]byte, 128)
	for k := range src {
		src[k] = byte(k)
	}
	dst := make([]byte, 128)
	block.Encrypt(dst, src)

	closeCh := make(chan struct{})

	for i := 0; i < 2; i++ {
		go func() {
			for {
				select {
				case <-closeCh:
					return
				default:
					dst1 := make([]byte, 128)
					block.Encrypt(dst1, src)

					if bytes.Compare(dst, dst1) != 0 {
						t.Errorf("not equal")
						close(closeCh)
					}
				}
			}
		}()
	}

	<-closeCh
}

上述TestEncrypt用于测试并发Encrypt;

func (s *UDPSession) output(buf []byte) { 
    ...
    s.block.Encrypt(ecc[k], ecc[k])
    ...
 }

当多个UDPSession同时调用output方法,同样会出现上述‘not equal’

histalk avatar Sep 09 '20 02:09 histalk

UDPSession的WriteBuffers和Close是加了锁的,直接使用UDPSession的接口,不会有你这里提到的并发问题,这也不能算是kcp-go的问题 如果你想自己操作Block,应该由你自己对Block封装的代码来保证一致性

lesismal avatar May 03 '21 08:05 lesismal