crypt.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package kcp
  2. import (
  3. "crypto/cipher"
  4. "hash/fnv"
  5. "v2ray.com/core/common/errors"
  6. "v2ray.com/core/common/serial"
  7. )
  8. var (
  9. errInvalidAuth = errors.New("Invalid auth.")
  10. )
  11. // SimpleAuthenticator is a legacy AEAD used for KCP encryption.
  12. type SimpleAuthenticator struct{}
  13. // NewSimpleAuthenticator creates a new SimpleAuthenticator
  14. func NewSimpleAuthenticator() cipher.AEAD {
  15. return &SimpleAuthenticator{}
  16. }
  17. // NonceSize implements cipher.AEAD.NonceSize().
  18. func (v *SimpleAuthenticator) NonceSize() int {
  19. return 0
  20. }
  21. // Overhead implements cipher.AEAD.NonceSize().
  22. func (v *SimpleAuthenticator) Overhead() int {
  23. return 6
  24. }
  25. // Seal implements cipher.AEAD.Seal().
  26. func (v *SimpleAuthenticator) Seal(dst, nonce, plain, extra []byte) []byte {
  27. dst = append(dst, 0, 0, 0, 0)
  28. dst = serial.Uint16ToBytes(uint16(len(plain)), dst)
  29. dst = append(dst, plain...)
  30. fnvHash := fnv.New32a()
  31. fnvHash.Write(dst[4:])
  32. fnvHash.Sum(dst[:0])
  33. len := len(dst)
  34. xtra := 4 - len%4
  35. if xtra != 4 {
  36. dst = append(dst, make([]byte, xtra)...)
  37. }
  38. xorfwd(dst)
  39. if xtra != 4 {
  40. dst = dst[:len]
  41. }
  42. return dst
  43. }
  44. // Open implements cipher.AEAD.Open().
  45. func (v *SimpleAuthenticator) Open(dst, nonce, cipherText, extra []byte) ([]byte, error) {
  46. dst = append(dst, cipherText...)
  47. dstLen := len(dst)
  48. xtra := 4 - dstLen%4
  49. if xtra != 4 {
  50. dst = append(dst, make([]byte, xtra)...)
  51. }
  52. xorbkd(dst)
  53. if xtra != 4 {
  54. dst = dst[:dstLen]
  55. }
  56. fnvHash := fnv.New32a()
  57. fnvHash.Write(dst[4:])
  58. if serial.BytesToUint32(dst[:4]) != fnvHash.Sum32() {
  59. return nil, errInvalidAuth
  60. }
  61. length := serial.BytesToUint16(dst[4:6])
  62. if len(dst)-6 != int(length) {
  63. return nil, errInvalidAuth
  64. }
  65. return dst[6:], nil
  66. }