github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/kcp/crypt.go (about)

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