1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-29 10:45:22 +00:00
v2fly/proxy/vmess/aead/encrypt.go

142 lines
5.0 KiB
Go
Raw Normal View History

2020-06-06 09:11:30 +00:00
package aead
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"encoding/binary"
"errors"
"io"
"time"
"v2ray.com/core/common"
)
func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
2020-06-08 05:21:59 +00:00
generatedAuthID := CreateAuthID(key[:], time.Now().Unix())
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
connectionNonce := make([]byte, 8)
if _, err := io.ReadFull(rand.Reader, connectionNonce); err != nil {
2020-06-06 09:11:30 +00:00
panic(err.Error())
}
2020-06-08 05:21:59 +00:00
aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil)
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
var headerPayloadDataLen uint16
headerPayloadDataLen = uint16(len(data))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
authidCheckValue := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(generatedAuthID[:]), string(aeadPayloadLengthSerializeBuffer.Bytes()), string(connectionNonce))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
aeadPayloadLengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(generatedAuthID[:]), string(connectionNonce[:]))[:2]
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
aeadPayloadLengthSerializedByte[0] = aeadPayloadLengthSerializedByte[0] ^ aeadPayloadLengthMask[0]
aeadPayloadLengthSerializedByte[1] = aeadPayloadLengthSerializedByte[1] ^ aeadPayloadLengthMask[1]
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
2020-06-06 09:11:30 +00:00
if err != nil {
panic(err.Error())
}
2020-06-08 05:21:59 +00:00
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
2020-06-06 09:11:30 +00:00
if err != nil {
panic(err.Error())
}
2020-06-08 05:21:59 +00:00
payloadHeaderAEADEncrypted := payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
var outputBuffer = bytes.NewBuffer(nil)
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
common.Must2(outputBuffer.Write(generatedAuthID[:])) //16
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
common.Must2(outputBuffer.Write(authidCheckValue)) //16
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
common.Must2(outputBuffer.Write(aeadPayloadLengthSerializedByte)) //2
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
common.Must2(outputBuffer.Write(connectionNonce)) //8
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
return outputBuffer.Bytes()
2020-06-06 09:11:30 +00:00
}
func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, error, int) {
2020-06-08 05:21:59 +00:00
var authidCheckValue [16]byte
var headerPayloadDataLen [2]byte
2020-06-06 09:11:30 +00:00
var nonce [8]byte
2020-06-08 05:21:59 +00:00
authidCheckValueReadBytesCounts, err := io.ReadFull(data, authidCheckValue[:])
2020-06-06 09:11:30 +00:00
if err != nil {
2020-06-08 05:21:59 +00:00
return nil, false, err, authidCheckValueReadBytesCounts
2020-06-06 09:11:30 +00:00
}
2020-06-08 05:21:59 +00:00
headerPayloadDataLenReadBytesCounts, err := io.ReadFull(data, headerPayloadDataLen[:])
2020-06-06 09:11:30 +00:00
if err != nil {
2020-06-08 05:21:59 +00:00
return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts
2020-06-06 09:11:30 +00:00
}
2020-06-08 05:21:59 +00:00
nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
2020-06-06 09:11:30 +00:00
if err != nil {
2020-06-08 05:21:59 +00:00
return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
2020-06-06 09:11:30 +00:00
}
//Unmask Length
2020-06-08 05:21:59 +00:00
LengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(authid[:]), string(nonce[:]))[:2]
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
headerPayloadDataLen[0] = headerPayloadDataLen[0] ^ LengthMask[0]
headerPayloadDataLen[1] = headerPayloadDataLen[1] ^ LengthMask[1]
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
authidCheckValueReceivedFromNetwork := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(authid[:]), string(headerPayloadDataLen[:]), string(nonce[:]))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
if !hmac.Equal(authidCheckValueReceivedFromNetwork, authidCheckValue[:]) {
return nil, true, errCheckMismatch, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
2020-06-06 09:11:30 +00:00
}
var length uint16
2020-06-08 05:21:59 +00:00
common.Must(binary.Read(bytes.NewReader(headerPayloadDataLen[:]), binary.BigEndian, &length))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
2020-06-06 09:11:30 +00:00
//16 == AEAD Tag size
2020-06-08 05:21:59 +00:00
payloadHeaderAEADEncrypted := make([]byte, length+16)
2020-06-06 09:11:30 +00:00
2020-06-08 05:21:59 +00:00
payloadHeaderAEADEncryptedReadedBytesCounts, err := io.ReadFull(data, payloadHeaderAEADEncrypted)
2020-06-06 09:11:30 +00:00
if err != nil {
2020-06-08 05:21:59 +00:00
return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
2020-06-06 09:11:30 +00:00
}
2020-06-08 05:21:59 +00:00
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
2020-06-06 09:11:30 +00:00
if err != nil {
panic(err.Error())
}
2020-06-08 05:21:59 +00:00
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
2020-06-06 09:11:30 +00:00
if err != nil {
panic(err.Error())
}
2020-06-08 05:25:33 +00:00
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
2020-06-06 09:11:30 +00:00
if erropenAEAD != nil {
2020-06-08 05:21:59 +00:00
return nil, true, erropenAEAD, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
2020-06-06 09:11:30 +00:00
}
2020-06-08 05:25:33 +00:00
return decryptedAEADHeaderPayload, false, nil, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
2020-06-06 09:11:30 +00:00
}
var errCheckMismatch = errors.New("check verify failed")