auth.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package encoding
  2. import (
  3. "crypto/md5"
  4. "hash/fnv"
  5. "golang.org/x/crypto/sha3"
  6. "v2ray.com/core/common/serial"
  7. )
  8. // Authenticate authenticates a byte array using Fnv hash.
  9. func Authenticate(b []byte) uint32 {
  10. fnv1hash := fnv.New32a()
  11. fnv1hash.Write(b)
  12. return fnv1hash.Sum32()
  13. }
  14. type NoOpAuthenticator struct{}
  15. func (NoOpAuthenticator) NonceSize() int {
  16. return 0
  17. }
  18. func (NoOpAuthenticator) Overhead() int {
  19. return 0
  20. }
  21. // Seal implements AEAD.Seal().
  22. func (NoOpAuthenticator) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
  23. return append(dst[:0], plaintext...)
  24. }
  25. // Open implements AEAD.Open().
  26. func (NoOpAuthenticator) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
  27. return append(dst[:0], ciphertext...), nil
  28. }
  29. // FnvAuthenticator is an AEAD based on Fnv hash.
  30. type FnvAuthenticator struct {
  31. }
  32. // NonceSize implements AEAD.NonceSize().
  33. func (v *FnvAuthenticator) NonceSize() int {
  34. return 0
  35. }
  36. // Overhead impelements AEAD.Overhead().
  37. func (v *FnvAuthenticator) Overhead() int {
  38. return 4
  39. }
  40. // Seal implements AEAD.Seal().
  41. func (v *FnvAuthenticator) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
  42. dst = serial.Uint32ToBytes(Authenticate(plaintext), dst)
  43. return append(dst, plaintext...)
  44. }
  45. // Open implements AEAD.Open().
  46. func (v *FnvAuthenticator) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
  47. if serial.BytesToUint32(ciphertext[:4]) != Authenticate(ciphertext[4:]) {
  48. return dst, newError("invalid authentication")
  49. }
  50. return append(dst, ciphertext[4:]...), nil
  51. }
  52. // GenerateChacha20Poly1305Key generates a 32-byte key from a given 16-byte array.
  53. func GenerateChacha20Poly1305Key(b []byte) []byte {
  54. key := make([]byte, 32)
  55. t := md5.Sum(b)
  56. copy(key, t[:])
  57. t = md5.Sum(key[:16])
  58. copy(key[16:], t[:])
  59. return key
  60. }
  61. type ShakeSizeParser struct {
  62. shake sha3.ShakeHash
  63. buffer [2]byte
  64. }
  65. func NewShakeSizeParser(nonce []byte) *ShakeSizeParser {
  66. shake := sha3.NewShake128()
  67. shake.Write(nonce)
  68. return &ShakeSizeParser{
  69. shake: shake,
  70. }
  71. }
  72. func (s *ShakeSizeParser) SizeBytes() int {
  73. return 2
  74. }
  75. func (s *ShakeSizeParser) next() uint16 {
  76. s.shake.Read(s.buffer[:])
  77. return serial.BytesToUint16(s.buffer[:])
  78. }
  79. func (s *ShakeSizeParser) Decode(b []byte) (uint16, error) {
  80. mask := s.next()
  81. size := serial.BytesToUint16(b)
  82. return mask ^ size, nil
  83. }
  84. func (s *ShakeSizeParser) Encode(size uint16, b []byte) []byte {
  85. mask := s.next()
  86. return serial.Uint16ToBytes(mask^size, b[:0])
  87. }