Cloak/internal/server/auth.go
2019-06-16 11:08:51 +10:00

67 lines
1.7 KiB
Go

package server
import (
"bytes"
"crypto"
"crypto/sha256"
"encoding/binary"
"log"
"github.com/cbeuw/Cloak/internal/ecdh"
"github.com/cbeuw/Cloak/internal/util"
)
// input ticket, return UID
func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) ([]byte, uint32, string, byte, []byte) {
ephPub, _ := ecdh.Unmarshal(ticket[0:32])
key := ecdh.GenerateSharedSecret(staticPv, ephPub)
plain, err := util.AESGCMDecrypt(ticket[0:12], key, ticket[32:117])
if err != nil {
return nil, 0, "", 0x00, nil
}
sessionID := binary.BigEndian.Uint32(plain[16:20])
return plain[0:16], sessionID, string(bytes.Trim(plain[20:36], "\x00")), plain[36], plain[37:69]
}
func validateRandom(random []byte, UID []byte, time int64) bool {
t := make([]byte, 8)
binary.BigEndian.PutUint64(t, uint64(time/(12*60*60)))
rdm := random[0:16]
preHash := make([]byte, 56)
copy(preHash[0:32], UID)
copy(preHash[32:40], t)
copy(preHash[40:56], rdm)
h := sha256.New()
h.Write(preHash)
return bytes.Equal(h.Sum(nil)[0:16], random[16:32])
}
func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte, sessionKey []byte) {
var random [32]byte
copy(random[:], ch.random)
sta.usedRandomM.Lock()
used := sta.usedRandom[random]
sta.usedRandom[random] = int(sta.Now().Unix())
sta.usedRandomM.Unlock()
if used != 0 {
log.Println("Replay! Duplicate random")
return
}
ticket := ch.extensions[[2]byte{0x00, 0x23}]
if len(ticket) < 68 {
return
}
UID, sessionID, proxyMethod, encryptionMethod, sessionKey = decryptSessionTicket(sta.staticPv, ticket)
if len(UID) < 16 {
return
}
isCK = validateRandom(ch.random, UID, sta.Now().Unix())
if !isCK {
return
}
return
}