Cloak/internal/client/auth.go

59 lines
2.1 KiB
Go
Raw Normal View History

2018-10-07 17:09:45 +00:00
package client
import (
"crypto/rand"
"encoding/binary"
"github.com/cbeuw/Cloak/internal/ecdh"
"github.com/cbeuw/Cloak/internal/util"
2019-08-02 00:01:19 +00:00
"sync/atomic"
2018-10-07 17:09:45 +00:00
)
2019-08-12 21:43:16 +00:00
const (
UNORDERED_FLAG = 0x01 // 0000 0001
)
type chHiddenData struct {
2019-09-01 00:33:34 +00:00
fullRaw []byte // pubkey, ciphertext, tag
chRandom []byte
chSessionId []byte
chX25519KeyShare []byte
chExtSNI []byte
}
2019-08-20 21:43:04 +00:00
// makeHiddenData generates the ephemeral key pair, calculates the shared secret, and then compose and
// encrypt the Authentication data. It also composes SNI extension.
func makeHiddenData(sta *State) (ret chHiddenData, sharedSecret []byte) {
2019-08-02 00:01:19 +00:00
// random is marshalled ephemeral pub key 32 bytes
2019-08-20 21:43:04 +00:00
/*
Authentication data:
+----------+----------------+---------------------+-------------+--------------+--------+------------+
| _UID_ | _Proxy Method_ | _Encryption Method_ | _Timestamp_ | _Session Id_ | _Flag_ | _reserved_ |
+----------+----------------+---------------------+-------------+--------------+--------+------------+
| 16 bytes | 12 bytes | 1 byte | 8 bytes | 4 bytes | 1 byte | 6 bytes |
+----------+----------------+---------------------+-------------+--------------+--------+------------+
*/
// The authentication ciphertext and its tag are then distributed among SessionId and X25519KeyShare
2019-08-02 00:01:19 +00:00
ephPv, ephPub, _ := ecdh.GenerateKey(rand.Reader)
ret.chRandom = ecdh.Marshal(ephPub)
2019-08-02 00:01:19 +00:00
plaintext := make([]byte, 48)
copy(plaintext, sta.UID)
copy(plaintext[16:28], sta.ProxyMethod)
plaintext[28] = sta.EncryptionMethod
2019-08-20 21:48:01 +00:00
binary.BigEndian.PutUint64(plaintext[29:37], uint64(sta.Now().Unix()))
2019-08-02 00:01:19 +00:00
binary.BigEndian.PutUint32(plaintext[37:41], atomic.LoadUint32(&sta.SessionID))
2019-08-12 21:43:16 +00:00
if sta.Unordered {
plaintext[41] |= UNORDERED_FLAG
}
2019-08-02 00:01:19 +00:00
sharedSecret = ecdh.GenerateSharedSecret(ephPv, sta.staticPub)
nonce := ret.chRandom[0:12]
2019-08-20 21:43:04 +00:00
ciphertextWithTag, _ := util.AESGCMEncrypt(nonce, sharedSecret, plaintext)
2019-09-01 00:33:34 +00:00
ret.fullRaw = append(ret.chRandom, ciphertextWithTag...)
2019-08-20 21:43:04 +00:00
ret.chSessionId = ciphertextWithTag[0:32]
ret.chX25519KeyShare = ciphertextWithTag[32:64]
ret.chExtSNI = makeServerName(sta.ServerName)
2019-08-02 00:01:19 +00:00
return
2018-10-07 17:09:45 +00:00
}