mirror of https://github.com/cbeuw/Cloak
Remove psudorandom padding
This commit is contained in:
parent
bb16f92b61
commit
0fbb6011fc
|
|
@ -100,7 +100,7 @@ func makeSession(sta *client.State) *mux.Session {
|
|||
|
||||
sta.UpdateIntervalKeys()
|
||||
|
||||
_, tthKey, _ := sta.GetIntervalKeys()
|
||||
_, tthKey := sta.GetIntervalKeys()
|
||||
sesh := mux.MakeSession(sta.SessionID, mux.UNLIMITED_VALVE, mux.MakeObfs(tthKey, sta.Cipher), mux.MakeDeobfs(tthKey, sta.Cipher), util.ReadTLS)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
|
|
|||
|
|
@ -29,34 +29,28 @@ func MakeRandomField(sta *State) []byte {
|
|||
return ret
|
||||
}
|
||||
|
||||
const SESSION_TICKET_LEN = 192
|
||||
const PUB_KEY_LEN = 32
|
||||
const AUTH_TAG_LEN = 16
|
||||
const STEGANO_LEN = SESSION_TICKET_LEN - PUB_KEY_LEN - AUTH_TAG_LEN
|
||||
|
||||
func MakeSessionTicket(sta *State) []byte {
|
||||
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID 16 bytes, proxy method 16 bytes, encryption method 1 byte][16 bytes authentication tag][padding 111 bytes]
|
||||
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID 16 bytes, proxy method 16 bytes, encryption method 1 byte][reserved 111 bytes][16 bytes authentication tag]
|
||||
// The first 12 bytes of the marshalled ephemeral public key is used as the nonce
|
||||
// for encrypting the UID
|
||||
|
||||
ticket := make([]byte, 192)
|
||||
ticket := make([]byte, SESSION_TICKET_LEN)
|
||||
|
||||
//TODO: error when the interval has expired
|
||||
ephPub, intervalKey, seed := sta.GetIntervalKeys()
|
||||
copy(ticket[0:32], ecdh.Marshal(ephPub))
|
||||
ephPub, intervalKey := sta.GetIntervalKeys()
|
||||
copy(ticket[0:PUB_KEY_LEN], ecdh.Marshal(ephPub))
|
||||
|
||||
plain := make([]byte, 33)
|
||||
plain := make([]byte, STEGANO_LEN)
|
||||
copy(plain, sta.UID)
|
||||
copy(plain[16:32], []byte(sta.ProxyMethod))
|
||||
copy(plain[16:32], sta.ProxyMethod)
|
||||
plain[32] = sta.EncryptionMethod
|
||||
|
||||
cipher, _ := util.AESGCMEncrypt(ticket[0:12], intervalKey, plain)
|
||||
copy(ticket[32:81], cipher)
|
||||
// The purpose of adding sessionID is that, the generated padding of sessionTicket needs to be unpredictable.
|
||||
// As shown in auth.go, the padding is generated by a psudo random generator. The seed
|
||||
// needs to be the same for each TicketTimeHint interval. However the value of epoch/TicketTimeHint
|
||||
// is public knowledge, so is the psudo random algorithm used by math/rand. Therefore not only
|
||||
// can the firewall tell that the padding is generated in this specific way, this padding is identical
|
||||
// for all ckclients in the same TicketTimeHint interval. This will expose us.
|
||||
//
|
||||
// With the sessionID value generated at startup of ckclient and used as a part of the seed, the
|
||||
// sessionTicket is still identical for each TicketTimeHint interval, but others won't be able to know
|
||||
// how it was generated. It will also be different for each client.
|
||||
copy(ticket[81:192], util.PsudoRandBytes(111, seed))
|
||||
copy(ticket[PUB_KEY_LEN:], cipher)
|
||||
return ticket
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"crypto"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
|
|
@ -32,7 +31,6 @@ type tthIntervalKeys struct {
|
|||
ephPv crypto.PrivateKey
|
||||
ephPub crypto.PublicKey
|
||||
intervalKey []byte
|
||||
seed int64
|
||||
}
|
||||
|
||||
// State stores global variables
|
||||
|
|
@ -82,14 +80,13 @@ func (sta *State) UpdateIntervalKeys() {
|
|||
sta.intervalData.interval = currentInterval
|
||||
ephPv, ephPub, _ := ecdh.GenerateKey(rand.Reader)
|
||||
intervalKey := ecdh.GenerateSharedSecret(ephPv, sta.staticPub)
|
||||
seed := int64(binary.BigEndian.Uint64(ephPv.(*[32]byte)[0:8]))
|
||||
sta.intervalData.ephPv, sta.intervalData.ephPub, sta.intervalData.intervalKey, sta.intervalData.seed = ephPv, ephPub, intervalKey, seed
|
||||
sta.intervalData.ephPv, sta.intervalData.ephPub, sta.intervalData.intervalKey = ephPv, ephPub, intervalKey
|
||||
}
|
||||
|
||||
func (sta *State) GetIntervalKeys() (crypto.PublicKey, []byte, int64) {
|
||||
func (sta *State) GetIntervalKeys() (crypto.PublicKey, []byte) {
|
||||
sta.intervalDataM.Lock()
|
||||
defer sta.intervalDataM.Unlock()
|
||||
return sta.intervalData.ephPub, sta.intervalData.intervalKey, sta.intervalData.seed
|
||||
return sta.intervalData.ephPub, sta.intervalData.intervalKey
|
||||
}
|
||||
|
||||
// semi-colon separated value. This is for Android plugin options
|
||||
|
|
|
|||
|
|
@ -10,11 +10,16 @@ import (
|
|||
"log"
|
||||
)
|
||||
|
||||
const SESSION_TICKET_LEN = 192
|
||||
const PUB_KEY_LEN = 32
|
||||
const AUTH_TAG_LEN = 16
|
||||
const USED_STAGNO_LEN = 16 + 16 + 1
|
||||
|
||||
func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) (UID []byte, proxyMethod string, encryptionMethod byte, tthKey []byte) {
|
||||
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID 16 bytes, proxy method 16 bytes, encryption method 1 byte][16 bytes authentication tag][padding 111 bytes]
|
||||
ephPub, _ := ecdh.Unmarshal(ticket[0:32])
|
||||
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID 16 bytes, proxy method 16 bytes, encryption method 1 byte][reserved 111 bytes][padding 111 bytes]
|
||||
ephPub, _ := ecdh.Unmarshal(ticket[0:PUB_KEY_LEN])
|
||||
tthKey = ecdh.GenerateSharedSecret(staticPv, ephPub)
|
||||
plain, err := util.AESGCMDecrypt(ticket[0:12], tthKey, ticket[32:81])
|
||||
plain, err := util.AESGCMDecrypt(ticket[0:12], tthKey, ticket[PUB_KEY_LEN:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -51,7 +56,7 @@ func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID u
|
|||
|
||||
ticket := ch.extensions[[2]byte{0x00, 0x23}]
|
||||
|
||||
if len(ticket) < 81 {
|
||||
if len(ticket) < PUB_KEY_LEN+USED_STAGNO_LEN+AUTH_TAG_LEN {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue