github.com/v2fly/v2ray-core/v4@v4.45.2/transport/internet/kcp/crypt.go (about)

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