v2fly/proxy/vmess/aead/encrypt.go

169 lines
5.1 KiB
Go
Raw Normal View History

2020-06-06 09:11:30 +00:00
package aead
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"io"
"time"
2021-02-16 20:31:50 +00:00
"github.com/v2fly/v2ray-core/v4/common"
2020-06-06 09:11:30 +00:00
)
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
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
aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()
var payloadHeaderLengthAEADEncrypted []byte
2020-06-06 09:11:30 +00:00
{
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))
2020-06-06 09:11:30 +00:00
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
2020-06-06 09:11:30 +00:00
payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
if err != nil {
panic(err.Error())
}
2020-06-06 09:11:30 +00:00
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
if err != nil {
panic(err.Error())
}
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
2020-06-06 09:11:30 +00:00
}
var payloadHeaderAEADEncrypted []byte
2020-06-06 09:11:30 +00:00
{
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
2020-06-06 09:11:30 +00:00
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
if err != nil {
panic(err.Error())
}
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
if err != nil {
panic(err.Error())
}
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
}
2020-06-06 09:11:30 +00:00
2021-05-19 21:28:52 +00:00
outputBuffer := bytes.NewBuffer(nil)
2020-06-06 09:11:30 +00:00
common.Must2(outputBuffer.Write(generatedAuthID[:])) // 16
common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) // 2+16
common.Must2(outputBuffer.Write(connectionNonce)) // 8
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, int, error) {
var payloadHeaderLengthAEADEncrypted [18]byte
2020-06-06 09:11:30 +00:00
var nonce [8]byte
var bytesRead int
2020-06-06 09:11:30 +00:00
authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:])
bytesRead += authidCheckValueReadBytesCounts
2020-06-06 09:11:30 +00:00
if err != nil {
return nil, false, bytesRead, err
2020-06-06 09:11:30 +00:00
}
2020-06-08 05:21:59 +00:00
nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
bytesRead += nonceReadBytesCounts
2020-06-06 09:11:30 +00:00
if err != nil {
return nil, false, bytesRead, err
2020-06-06 09:11:30 +00:00
}
// Decrypt Length
var decryptedAEADHeaderLengthPayloadResult []byte
2020-06-06 09:11:30 +00:00
{
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
2020-06-06 09:11:30 +00:00
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
2020-06-06 09:11:30 +00:00
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
if err != nil {
panic(err.Error())
}
2020-06-06 09:11:30 +00:00
payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
if err != nil {
panic(err.Error())
}
decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
if erropenAEAD != nil {
return nil, true, bytesRead, erropenAEAD
}
decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload
2020-06-06 09:11:30 +00:00
}
var length uint16
common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length))
2020-06-06 09:11:30 +00:00
var decryptedAEADHeaderPayloadR []byte
2020-06-06 09:11:30 +00:00
var payloadHeaderAEADEncryptedReadedBytesCounts int
2020-06-06 09:11:30 +00:00
{
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
2020-06-06 09:11:30 +00:00
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
2020-06-06 09:11:30 +00:00
// 16 == AEAD Tag size
payloadHeaderAEADEncrypted := make([]byte, length+16)
2020-06-06 09:11:30 +00:00
payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted)
bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts
if err != nil {
return nil, false, bytesRead, err
}
2020-06-06 09:11:30 +00:00
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
if err != nil {
panic(err.Error())
}
2020-06-06 09:11:30 +00:00
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
if err != nil {
panic(err.Error())
}
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
if erropenAEAD != nil {
return nil, true, bytesRead, erropenAEAD
}
decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload
2020-06-06 09:11:30 +00:00
}
return decryptedAEADHeaderPayloadR, false, bytesRead, nil
2020-06-06 09:11:30 +00:00
}