github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/transport/internet/kcp/crypt.go (about)

     1  package kcp
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"encoding/binary"
     6  	"hash/fnv"
     7  
     8  	"github.com/v2fly/v2ray-core/v5/common"
     9  )
    10  
    11  // SimpleAuthenticator is a legacy AEAD used for KCP encryption.
    12  type SimpleAuthenticator struct{}
    13  
    14  // NewSimpleAuthenticator creates a new SimpleAuthenticator
    15  func NewSimpleAuthenticator() cipher.AEAD {
    16  	return &SimpleAuthenticator{}
    17  }
    18  
    19  // NonceSize implements cipher.AEAD.NonceSize().
    20  func (*SimpleAuthenticator) NonceSize() int {
    21  	return 0
    22  }
    23  
    24  // Overhead implements cipher.AEAD.NonceSize().
    25  func (*SimpleAuthenticator) Overhead() int {
    26  	return 6
    27  }
    28  
    29  // Seal implements cipher.AEAD.Seal().
    30  func (a *SimpleAuthenticator) Seal(dst, nonce, plain, extra []byte) []byte {
    31  	dst = append(dst, 0, 0, 0, 0, 0, 0) // 4 bytes for hash, and then 2 bytes for length
    32  	binary.BigEndian.PutUint16(dst[4:], uint16(len(plain)))
    33  	dst = append(dst, plain...)
    34  
    35  	fnvHash := fnv.New32a()
    36  	common.Must2(fnvHash.Write(dst[4:]))
    37  	fnvHash.Sum(dst[:0])
    38  
    39  	dstLen := len(dst)
    40  	xtra := 4 - dstLen%4
    41  	if xtra != 4 {
    42  		dst = append(dst, make([]byte, xtra)...)
    43  	}
    44  	xorfwd(dst)
    45  	if xtra != 4 {
    46  		dst = dst[:dstLen]
    47  	}
    48  	return dst
    49  }
    50  
    51  // Open implements cipher.AEAD.Open().
    52  func (a *SimpleAuthenticator) Open(dst, nonce, cipherText, extra []byte) ([]byte, error) {
    53  	dst = append(dst, cipherText...)
    54  	dstLen := len(dst)
    55  	xtra := 4 - dstLen%4
    56  	if xtra != 4 {
    57  		dst = append(dst, make([]byte, xtra)...)
    58  	}
    59  	xorbkd(dst)
    60  	if xtra != 4 {
    61  		dst = dst[:dstLen]
    62  	}
    63  
    64  	fnvHash := fnv.New32a()
    65  	common.Must2(fnvHash.Write(dst[4:]))
    66  	if binary.BigEndian.Uint32(dst[:4]) != fnvHash.Sum32() {
    67  		return nil, newError("invalid auth")
    68  	}
    69  
    70  	length := binary.BigEndian.Uint16(dst[4:6])
    71  	if len(dst)-6 != int(length) {
    72  		return nil, newError("invalid auth")
    73  	}
    74  
    75  	return dst[6:], nil
    76  }