Browse Source

Update AEAD design to rely more on AEAD

pull/2606/head
Shelikhoo 4 years ago
parent
commit
f19f95af35
No known key found for this signature in database
GPG Key ID: C4D5E79D22B25316
  1. 8
      proxy/vmess/aead/consts.go
  2. 152
      proxy/vmess/aead/encrypt.go

8
proxy/vmess/aead/consts.go

@ -12,10 +12,10 @@ const KDFSaltConst_AEADRespHeaderPayloadIV = "AEAD Resp Header IV"
const KDFSaltConst_VMessAEADKDF = "VMess AEAD KDF" const KDFSaltConst_VMessAEADKDF = "VMess AEAD KDF"
const KDFSaltConst_VmessAuthIDCheckValue = "VMess AuthID Check Value"
const KDFSaltConst_VMessLengthMask = "VMess AuthID Mask Value"
const KDFSaltConst_VMessHeaderPayloadAEADKey = "VMess Header AEAD Key" const KDFSaltConst_VMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
const KDFSaltConst_VMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce" const KDFSaltConst_VMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
const KDFSaltConst_VMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
const KDFSaltConst_VMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"

152
proxy/vmess/aead/encrypt.go

@ -4,10 +4,8 @@ import (
"bytes" "bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/hmac"
"crypto/rand" "crypto/rand"
"encoding/binary" "encoding/binary"
"errors"
"io" "io"
"time" "time"
"v2ray.com/core/common" "v2ray.com/core/common"
@ -28,39 +26,54 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen)) common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen))
authidCheckValue := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(generatedAuthID[:]), string(aeadPayloadLengthSerializeBuffer.Bytes()), string(connectionNonce))
aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes() aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()
var payloadHeaderLengthAEADEncrypted []byte
aeadPayloadLengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(generatedAuthID[:]), string(connectionNonce[:]))[:2] {
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))
aeadPayloadLengthSerializedByte[0] = aeadPayloadLengthSerializedByte[0] ^ aeadPayloadLengthMask[0] payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
aeadPayloadLengthSerializedByte[1] = aeadPayloadLengthSerializedByte[1] ^ aeadPayloadLengthMask[1]
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce)) payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
if err != nil {
panic(err.Error())
}
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12] payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey) if err != nil {
if err != nil { panic(err.Error())
panic(err.Error()) }
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
} }
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) var payloadHeaderAEADEncrypted []byte
if err != nil { {
panic(err.Error()) payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
}
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
payloadHeaderAEADEncrypted := payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:]) 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[:])
}
var outputBuffer = bytes.NewBuffer(nil) var outputBuffer = bytes.NewBuffer(nil)
common.Must2(outputBuffer.Write(generatedAuthID[:])) //16 common.Must2(outputBuffer.Write(generatedAuthID[:])) //16
common.Must2(outputBuffer.Write(authidCheckValue)) //16 common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) //2+16
common.Must2(outputBuffer.Write(aeadPayloadLengthSerializedByte)) //2
common.Must2(outputBuffer.Write(connectionNonce)) //8 common.Must2(outputBuffer.Write(connectionNonce)) //8
@ -70,72 +83,93 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
} }
func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, error, int) { func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, error, int) {
var authidCheckValue [16]byte var payloadHeaderLengthAEADEncrypted [18]byte
var headerPayloadDataLen [2]byte
var nonce [8]byte var nonce [8]byte
authidCheckValueReadBytesCounts, err := io.ReadFull(data, authidCheckValue[:]) var bytesRead int
if err != nil {
return nil, false, err, authidCheckValueReadBytesCounts
}
headerPayloadDataLenReadBytesCounts, err := io.ReadFull(data, headerPayloadDataLen[:]) authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:])
bytesRead += authidCheckValueReadBytesCounts
if err != nil { if err != nil {
return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts return nil, false, err, bytesRead
} }
nonceReadBytesCounts, err := io.ReadFull(data, nonce[:]) nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
bytesRead += nonceReadBytesCounts
if err != nil { if err != nil {
return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts return nil, false, err, bytesRead
} }
//Unmask Length //Decrypt Length
var decryptedAEADHeaderLengthPayloadResult []byte
LengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(authid[:]), string(nonce[:]))[:2] {
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
headerPayloadDataLen[0] = headerPayloadDataLen[0] ^ LengthMask[0] payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
headerPayloadDataLen[1] = headerPayloadDataLen[1] ^ LengthMask[1]
authidCheckValueReceivedFromNetwork := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(authid[:]), string(headerPayloadDataLen[:]), string(nonce[:])) payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
if err != nil {
panic(err.Error())
}
if !hmac.Equal(authidCheckValueReceivedFromNetwork, authidCheckValue[:]) { payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
return nil, true, errCheckMismatch, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
if err != nil {
panic(err.Error())
}
decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
if erropenAEAD != nil {
return nil, true, erropenAEAD, bytesRead
}
decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload
} }
var length uint16 var length uint16
common.Must(binary.Read(bytes.NewReader(headerPayloadDataLen[:]), binary.BigEndian, &length)) common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult[:]), binary.BigEndian, &length))
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:])) var decryptedAEADHeaderPayloadR []byte
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12] var payloadHeaderAEADEncryptedReadedBytesCounts int
//16 == AEAD Tag size {
payloadHeaderAEADEncrypted := make([]byte, length+16) payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
payloadHeaderAEADEncryptedReadedBytesCounts, err := io.ReadFull(data, payloadHeaderAEADEncrypted) payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
if err != nil {
return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
}
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey) //16 == AEAD Tag size
if err != nil { payloadHeaderAEADEncrypted := make([]byte, length+16)
panic(err.Error())
}
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock) payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted)
bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts
if err != nil {
return nil, false, err, bytesRead
}
if err != nil { payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
panic(err.Error()) if err != nil {
} panic(err.Error())
}
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:]) payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
if erropenAEAD != nil { if err != nil {
return nil, true, erropenAEAD, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts panic(err.Error())
}
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
if erropenAEAD != nil {
return nil, true, erropenAEAD, bytesRead
}
decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload
} }
return decryptedAEADHeaderPayload, false, nil, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts return decryptedAEADHeaderPayloadR, false, nil, bytesRead
} }
var errCheckMismatch = errors.New("check verify failed")

Loading…
Cancel
Save