mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-04-30 09:18:34 +00:00
v1.0.0
This commit is contained in:
parent
47d23e9972
commit
c7f7c08ead
711 changed files with 82154 additions and 2 deletions
119
proxy/vmess/aead/authid.go
Normal file
119
proxy/vmess/aead/authid.go
Normal file
|
@ -0,0 +1,119 @@
|
|||
package aead
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
rand3 "crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/v1/common"
|
||||
"github.com/xtls/xray-core/v1/common/antireplay"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("user do not exist")
|
||||
ErrReplay = errors.New("replayed request")
|
||||
)
|
||||
|
||||
func CreateAuthID(cmdKey []byte, time int64) [16]byte {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
common.Must(binary.Write(buf, binary.BigEndian, time))
|
||||
var zero uint32
|
||||
common.Must2(io.CopyN(buf, rand3.Reader, 4))
|
||||
zero = crc32.ChecksumIEEE(buf.Bytes())
|
||||
common.Must(binary.Write(buf, binary.BigEndian, zero))
|
||||
aesBlock := NewCipherFromKey(cmdKey)
|
||||
if buf.Len() != 16 {
|
||||
panic("Size unexpected")
|
||||
}
|
||||
var result [16]byte
|
||||
aesBlock.Encrypt(result[:], buf.Bytes())
|
||||
return result
|
||||
}
|
||||
|
||||
func NewCipherFromKey(cmdKey []byte) cipher.Block {
|
||||
aesBlock, err := aes.NewCipher(KDF16(cmdKey, KDFSaltConstAuthIDEncryptionKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return aesBlock
|
||||
}
|
||||
|
||||
type AuthIDDecoder struct {
|
||||
s cipher.Block
|
||||
}
|
||||
|
||||
func NewAuthIDDecoder(cmdKey []byte) *AuthIDDecoder {
|
||||
return &AuthIDDecoder{NewCipherFromKey(cmdKey)}
|
||||
}
|
||||
|
||||
func (aidd *AuthIDDecoder) Decode(data [16]byte) (int64, uint32, int32, []byte) {
|
||||
aidd.s.Decrypt(data[:], data[:])
|
||||
var t int64
|
||||
var zero uint32
|
||||
var rand int32
|
||||
reader := bytes.NewReader(data[:])
|
||||
common.Must(binary.Read(reader, binary.BigEndian, &t))
|
||||
common.Must(binary.Read(reader, binary.BigEndian, &rand))
|
||||
common.Must(binary.Read(reader, binary.BigEndian, &zero))
|
||||
return t, zero, rand, data[:]
|
||||
}
|
||||
|
||||
func NewAuthIDDecoderHolder() *AuthIDDecoderHolder {
|
||||
return &AuthIDDecoderHolder{make(map[string]*AuthIDDecoderItem), antireplay.NewReplayFilter(120)}
|
||||
}
|
||||
|
||||
type AuthIDDecoderHolder struct {
|
||||
decoders map[string]*AuthIDDecoderItem
|
||||
filter *antireplay.ReplayFilter
|
||||
}
|
||||
|
||||
type AuthIDDecoderItem struct {
|
||||
dec *AuthIDDecoder
|
||||
ticket interface{}
|
||||
}
|
||||
|
||||
func NewAuthIDDecoderItem(key [16]byte, ticket interface{}) *AuthIDDecoderItem {
|
||||
return &AuthIDDecoderItem{
|
||||
dec: NewAuthIDDecoder(key[:]),
|
||||
ticket: ticket,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AuthIDDecoderHolder) AddUser(key [16]byte, ticket interface{}) {
|
||||
a.decoders[string(key[:])] = NewAuthIDDecoderItem(key, ticket)
|
||||
}
|
||||
|
||||
func (a *AuthIDDecoderHolder) RemoveUser(key [16]byte) {
|
||||
delete(a.decoders, string(key[:]))
|
||||
}
|
||||
|
||||
func (a *AuthIDDecoderHolder) Match(authID [16]byte) (interface{}, error) {
|
||||
for _, v := range a.decoders {
|
||||
t, z, _, d := v.dec.Decode(authID)
|
||||
if z != crc32.ChecksumIEEE(d[:12]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if t < 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if math.Abs(math.Abs(float64(t))-float64(time.Now().Unix())) > 120 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !a.filter.Check(authID[:]) {
|
||||
return nil, ErrReplay
|
||||
}
|
||||
|
||||
return v.ticket, nil
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
127
proxy/vmess/aead/authid_test.go
Normal file
127
proxy/vmess/aead/authid_test.go
Normal file
|
@ -0,0 +1,127 @@
|
|||
package aead
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCreateAuthID(t *testing.T) {
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
authid := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
fmt.Println(key)
|
||||
fmt.Println(authid)
|
||||
}
|
||||
|
||||
func TestCreateAuthIDAndDecode(t *testing.T) {
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
authid := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
fmt.Println(key)
|
||||
fmt.Println(authid)
|
||||
|
||||
AuthDecoder := NewAuthIDDecoderHolder()
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
AuthDecoder.AddUser(keyw, "Demo User")
|
||||
res, err := AuthDecoder.Match(authid)
|
||||
fmt.Println(res)
|
||||
fmt.Println(err)
|
||||
assert.Equal(t, "Demo User", res)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestCreateAuthIDAndDecode2(t *testing.T) {
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
authid := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
fmt.Println(key)
|
||||
fmt.Println(authid)
|
||||
|
||||
AuthDecoder := NewAuthIDDecoderHolder()
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
AuthDecoder.AddUser(keyw, "Demo User")
|
||||
res, err := AuthDecoder.Match(authid)
|
||||
fmt.Println(res)
|
||||
fmt.Println(err)
|
||||
assert.Equal(t, "Demo User", res)
|
||||
assert.Nil(t, err)
|
||||
|
||||
key2 := KDF16([]byte("Demo Key for Auth ID Test2"), "Demo Path for Auth ID Test")
|
||||
authid2 := CreateAuthID(key2, time.Now().Unix())
|
||||
|
||||
res2, err2 := AuthDecoder.Match(authid2)
|
||||
assert.EqualError(t, err2, "user do not exist")
|
||||
assert.Nil(t, res2)
|
||||
}
|
||||
|
||||
func TestCreateAuthIDAndDecodeMassive(t *testing.T) {
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
authid := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
fmt.Println(key)
|
||||
fmt.Println(authid)
|
||||
|
||||
AuthDecoder := NewAuthIDDecoderHolder()
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
AuthDecoder.AddUser(keyw, "Demo User")
|
||||
res, err := AuthDecoder.Match(authid)
|
||||
fmt.Println(res)
|
||||
fmt.Println(err)
|
||||
assert.Equal(t, "Demo User", res)
|
||||
assert.Nil(t, err)
|
||||
|
||||
for i := 0; i <= 10000; i++ {
|
||||
key2 := KDF16([]byte("Demo Key for Auth ID Test2"), "Demo Path for Auth ID Test", strconv.Itoa(i))
|
||||
var keyw2 [16]byte
|
||||
copy(keyw2[:], key2)
|
||||
AuthDecoder.AddUser(keyw2, "Demo User"+strconv.Itoa(i))
|
||||
}
|
||||
|
||||
authid3 := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
res2, err2 := AuthDecoder.Match(authid3)
|
||||
assert.Equal(t, "Demo User", res2)
|
||||
assert.Nil(t, err2)
|
||||
}
|
||||
|
||||
func TestCreateAuthIDAndDecodeSuperMassive(t *testing.T) {
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
authid := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
fmt.Println(key)
|
||||
fmt.Println(authid)
|
||||
|
||||
AuthDecoder := NewAuthIDDecoderHolder()
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
AuthDecoder.AddUser(keyw, "Demo User")
|
||||
res, err := AuthDecoder.Match(authid)
|
||||
fmt.Println(res)
|
||||
fmt.Println(err)
|
||||
assert.Equal(t, "Demo User", res)
|
||||
assert.Nil(t, err)
|
||||
|
||||
for i := 0; i <= 1000000; i++ {
|
||||
key2 := KDF16([]byte("Demo Key for Auth ID Test2"), "Demo Path for Auth ID Test", strconv.Itoa(i))
|
||||
var keyw2 [16]byte
|
||||
copy(keyw2[:], key2)
|
||||
AuthDecoder.AddUser(keyw2, "Demo User"+strconv.Itoa(i))
|
||||
}
|
||||
|
||||
authid3 := CreateAuthID(key, time.Now().Unix())
|
||||
|
||||
before := time.Now()
|
||||
res2, err2 := AuthDecoder.Match(authid3)
|
||||
after := time.Now()
|
||||
assert.Equal(t, "Demo User", res2)
|
||||
assert.Nil(t, err2)
|
||||
|
||||
fmt.Println(after.Sub(before).Seconds())
|
||||
}
|
14
proxy/vmess/aead/consts.go
Normal file
14
proxy/vmess/aead/consts.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package aead
|
||||
|
||||
const (
|
||||
KDFSaltConstAuthIDEncryptionKey = "AES Auth ID Encryption"
|
||||
KDFSaltConstAEADRespHeaderLenKey = "AEAD Resp Header Len Key"
|
||||
KDFSaltConstAEADRespHeaderLenIV = "AEAD Resp Header Len IV"
|
||||
KDFSaltConstAEADRespHeaderPayloadKey = "AEAD Resp Header Key"
|
||||
KDFSaltConstAEADRespHeaderPayloadIV = "AEAD Resp Header IV"
|
||||
KDFSaltConstVMessAEADKDF = "VMess AEAD KDF"
|
||||
KDFSaltConstVMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
|
||||
KDFSaltConstVMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
|
||||
KDFSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
|
||||
KDFSaltConstVMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"
|
||||
)
|
172
proxy/vmess/aead/encrypt.go
Normal file
172
proxy/vmess/aead/encrypt.go
Normal file
|
@ -0,0 +1,172 @@
|
|||
package aead
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/v1/common"
|
||||
)
|
||||
|
||||
func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
||||
generatedAuthID := CreateAuthID(key[:], time.Now().Unix())
|
||||
|
||||
connectionNonce := make([]byte, 8)
|
||||
if _, err := io.ReadFull(rand.Reader, connectionNonce); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil)
|
||||
|
||||
headerPayloadDataLen := uint16(len(data))
|
||||
|
||||
common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen))
|
||||
|
||||
aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()
|
||||
var payloadHeaderLengthAEADEncrypted []byte
|
||||
|
||||
{
|
||||
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))
|
||||
|
||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
|
||||
payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
|
||||
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
|
||||
}
|
||||
|
||||
var payloadHeaderAEADEncrypted []byte
|
||||
|
||||
{
|
||||
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
|
||||
|
||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
|
||||
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)
|
||||
|
||||
common.Must2(outputBuffer.Write(generatedAuthID[:])) // 16
|
||||
common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) // 2+16
|
||||
common.Must2(outputBuffer.Write(connectionNonce)) // 8
|
||||
common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))
|
||||
|
||||
return outputBuffer.Bytes()
|
||||
}
|
||||
|
||||
func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, int, error) {
|
||||
var payloadHeaderLengthAEADEncrypted [18]byte
|
||||
var nonce [8]byte
|
||||
|
||||
var bytesRead int
|
||||
|
||||
authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:])
|
||||
bytesRead += authidCheckValueReadBytesCounts
|
||||
if err != nil {
|
||||
return nil, false, bytesRead, err
|
||||
}
|
||||
|
||||
nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
|
||||
bytesRead += nonceReadBytesCounts
|
||||
if err != nil {
|
||||
return nil, false, bytesRead, err
|
||||
}
|
||||
|
||||
// Decrypt Length
|
||||
|
||||
var decryptedAEADHeaderLengthPayloadResult []byte
|
||||
|
||||
{
|
||||
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
|
||||
|
||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||
|
||||
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
var length uint16
|
||||
|
||||
common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length))
|
||||
|
||||
var decryptedAEADHeaderPayloadR []byte
|
||||
|
||||
var payloadHeaderAEADEncryptedReadedBytesCounts int
|
||||
|
||||
{
|
||||
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
|
||||
|
||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||
|
||||
// 16 == AEAD Tag size
|
||||
payloadHeaderAEADEncrypted := make([]byte, length+16)
|
||||
|
||||
payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted)
|
||||
bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts
|
||||
if err != nil {
|
||||
return nil, false, bytesRead, err
|
||||
}
|
||||
|
||||
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return decryptedAEADHeaderPayloadR, false, bytesRead, nil
|
||||
}
|
104
proxy/vmess/aead/encrypt_test.go
Normal file
104
proxy/vmess/aead/encrypt_test.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package aead
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOpenVMessAEADHeader(t *testing.T) {
|
||||
TestHeader := []byte("Test Header")
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
sealed := SealVMessAEADHeader(keyw, TestHeader)
|
||||
|
||||
var AEADR = bytes.NewReader(sealed)
|
||||
|
||||
var authid [16]byte
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, _, _, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
|
||||
fmt.Println(string(out))
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
func TestOpenVMessAEADHeader2(t *testing.T) {
|
||||
TestHeader := []byte("Test Header")
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
sealed := SealVMessAEADHeader(keyw, TestHeader)
|
||||
|
||||
var AEADR = bytes.NewReader(sealed)
|
||||
|
||||
var authid [16]byte
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, _, readen, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
assert.Equal(t, len(sealed)-16-AEADR.Len(), readen)
|
||||
assert.Equal(t, string(TestHeader), string(out))
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestOpenVMessAEADHeader4(t *testing.T) {
|
||||
for i := 0; i <= 60; i++ {
|
||||
TestHeader := []byte("Test Header")
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
sealed := SealVMessAEADHeader(keyw, TestHeader)
|
||||
var sealedm [16]byte
|
||||
copy(sealedm[:], sealed)
|
||||
sealed[i] ^= 0xff
|
||||
var AEADR = bytes.NewReader(sealed)
|
||||
|
||||
var authid [16]byte
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, drain, readen, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
assert.Equal(t, len(sealed)-16-AEADR.Len(), readen)
|
||||
assert.Equal(t, true, drain)
|
||||
assert.NotNil(t, err)
|
||||
if err == nil {
|
||||
fmt.Println(">")
|
||||
}
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenVMessAEADHeader4Massive(t *testing.T) {
|
||||
for j := 0; j < 1000; j++ {
|
||||
for i := 0; i <= 60; i++ {
|
||||
TestHeader := []byte("Test Header")
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
var keyw [16]byte
|
||||
copy(keyw[:], key)
|
||||
sealed := SealVMessAEADHeader(keyw, TestHeader)
|
||||
var sealedm [16]byte
|
||||
copy(sealedm[:], sealed)
|
||||
sealed[i] ^= 0xff
|
||||
var AEADR = bytes.NewReader(sealed)
|
||||
|
||||
var authid [16]byte
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, drain, readen, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
assert.Equal(t, len(sealed)-16-AEADR.Len(), readen)
|
||||
assert.Equal(t, true, drain)
|
||||
assert.NotNil(t, err)
|
||||
if err == nil {
|
||||
fmt.Println(">")
|
||||
}
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
}
|
||||
}
|
24
proxy/vmess/aead/kdf.go
Normal file
24
proxy/vmess/aead/kdf.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package aead
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
)
|
||||
|
||||
func KDF(key []byte, path ...string) []byte {
|
||||
hmacf := hmac.New(sha256.New, []byte(KDFSaltConstVMessAEADKDF))
|
||||
|
||||
for _, v := range path {
|
||||
hmacf = hmac.New(func() hash.Hash {
|
||||
return hmacf
|
||||
}, []byte(v))
|
||||
}
|
||||
hmacf.Write(key)
|
||||
return hmacf.Sum(nil)
|
||||
}
|
||||
|
||||
func KDF16(key []byte, path ...string) []byte {
|
||||
r := KDF(key, path...)
|
||||
return r[:16]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue