123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package aead
- import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "encoding/binary"
- "io"
- "time"
- "github.com/xtls/xray-core/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[:])
- }
- 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
- }
|