github.com/xraypb/Xray-core@v1.8.1/proxy/vmess/aead/encrypt.go (about) 1 package aead 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "crypto/rand" 8 "encoding/binary" 9 "io" 10 "time" 11 12 "github.com/xraypb/Xray-core/common" 13 ) 14 15 func SealVMessAEADHeader(key [16]byte, data []byte) []byte { 16 generatedAuthID := CreateAuthID(key[:], time.Now().Unix()) 17 18 connectionNonce := make([]byte, 8) 19 if _, err := io.ReadFull(rand.Reader, connectionNonce); err != nil { 20 panic(err.Error()) 21 } 22 23 aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil) 24 25 headerPayloadDataLen := uint16(len(data)) 26 27 common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen)) 28 29 aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes() 30 var payloadHeaderLengthAEADEncrypted []byte 31 32 { 33 payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce)) 34 35 payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12] 36 37 payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey) 38 if err != nil { 39 panic(err.Error()) 40 } 41 42 payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock) 43 if err != nil { 44 panic(err.Error()) 45 } 46 47 payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:]) 48 } 49 50 var payloadHeaderAEADEncrypted []byte 51 52 { 53 payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce)) 54 55 payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12] 56 57 payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey) 58 if err != nil { 59 panic(err.Error()) 60 } 61 62 payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) 63 if err != nil { 64 panic(err.Error()) 65 } 66 67 payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:]) 68 } 69 70 outputBuffer := bytes.NewBuffer(nil) 71 72 common.Must2(outputBuffer.Write(generatedAuthID[:])) // 16 73 common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) // 2+16 74 common.Must2(outputBuffer.Write(connectionNonce)) // 8 75 common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted)) 76 77 return outputBuffer.Bytes() 78 } 79 80 func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, int, error) { 81 var payloadHeaderLengthAEADEncrypted [18]byte 82 var nonce [8]byte 83 84 var bytesRead int 85 86 authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:]) 87 bytesRead += authidCheckValueReadBytesCounts 88 if err != nil { 89 return nil, false, bytesRead, err 90 } 91 92 nonceReadBytesCounts, err := io.ReadFull(data, nonce[:]) 93 bytesRead += nonceReadBytesCounts 94 if err != nil { 95 return nil, false, bytesRead, err 96 } 97 98 // Decrypt Length 99 100 var decryptedAEADHeaderLengthPayloadResult []byte 101 102 { 103 payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:])) 104 105 payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12] 106 107 payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey) 108 if err != nil { 109 panic(err.Error()) 110 } 111 112 payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) 113 if err != nil { 114 panic(err.Error()) 115 } 116 117 decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:]) 118 119 if erropenAEAD != nil { 120 return nil, true, bytesRead, erropenAEAD 121 } 122 123 decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload 124 } 125 126 var length uint16 127 128 common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length)) 129 130 var decryptedAEADHeaderPayloadR []byte 131 132 var payloadHeaderAEADEncryptedReadedBytesCounts int 133 134 { 135 payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:])) 136 137 payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12] 138 139 // 16 == AEAD Tag size 140 payloadHeaderAEADEncrypted := make([]byte, length+16) 141 142 payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted) 143 bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts 144 if err != nil { 145 return nil, false, bytesRead, err 146 } 147 148 payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey) 149 if err != nil { 150 panic(err.Error()) 151 } 152 153 payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) 154 if err != nil { 155 panic(err.Error()) 156 } 157 158 decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:]) 159 160 if erropenAEAD != nil { 161 return nil, true, bytesRead, erropenAEAD 162 } 163 164 decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload 165 } 166 167 return decryptedAEADHeaderPayloadR, false, bytesRead, nil 168 }