mirror of https://github.com/cbeuw/Cloak
Add optional encryption
This commit is contained in:
parent
3e9855191b
commit
0dd52d8570
|
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
|
//TODO: take iv into account
|
||||||
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
||||||
// The maximum size of TLS message will be 16396+12. 12 because of the stream header
|
// The maximum size of TLS message will be 16396+12. 12 because of the stream header
|
||||||
// 16408 is the max TLS message size on Firefox
|
// 16408 is the max TLS message size on Firefox
|
||||||
|
|
@ -180,8 +181,21 @@ start:
|
||||||
var UNLIMITED_DOWN int64 = 1e15
|
var UNLIMITED_DOWN int64 = 1e15
|
||||||
var UNLIMITED_UP int64 = 1e15
|
var UNLIMITED_UP int64 = 1e15
|
||||||
valve := mux.MakeValve(1e12, 1e12, &UNLIMITED_DOWN, &UNLIMITED_UP)
|
valve := mux.MakeValve(1e12, 1e12, &UNLIMITED_DOWN, &UNLIMITED_UP)
|
||||||
obfs := mux.MakeObfs(sta.UID)
|
|
||||||
deobfs := mux.MakeDeobfs(sta.UID)
|
var crypto mux.Crypto
|
||||||
|
switch sta.EncryptionMethod {
|
||||||
|
case 0x00:
|
||||||
|
crypto = &mux.Plain{}
|
||||||
|
case 0x01:
|
||||||
|
crypto, err = mux.MakeAESCipher(sta.UID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obfs := mux.MakeObfs(sta.UID, crypto)
|
||||||
|
deobfs := mux.MakeDeobfs(sta.UID, crypto)
|
||||||
sesh := mux.MakeSession(sessionID, valve, obfs, deobfs, util.ReadTLS)
|
sesh := mux.MakeSession(sessionID, valve, obfs, deobfs, util.ReadTLS)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
|
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
|
//TODO: take iv into account
|
||||||
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
||||||
// The maximum size of TLS message will be 16396+12. 12 because of the stream header
|
// The maximum size of TLS message will be 16396+12. 12 because of the stream header
|
||||||
// 16408 is the max TLS message size on Firefox
|
// 16408 is the max TLS message size on Firefox
|
||||||
|
|
@ -69,7 +70,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isCloak, UID, sessionID, proxyMethod := server.TouchStone(ch, sta)
|
isCloak, UID, sessionID, proxyMethod, encryptionMethod := server.TouchStone(ch, sta)
|
||||||
if !isCloak {
|
if !isCloak {
|
||||||
log.Printf("+1 non Cloak TLS traffic from %v\n", conn.RemoteAddr())
|
log.Printf("+1 non Cloak TLS traffic from %v\n", conn.RemoteAddr())
|
||||||
goWeb(data)
|
goWeb(data)
|
||||||
|
|
@ -148,7 +149,23 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sesh, existing, err := user.GetSession(sessionID, mux.MakeObfs(UID), mux.MakeDeobfs(UID), util.ReadTLS)
|
var crypto mux.Crypto
|
||||||
|
switch encryptionMethod {
|
||||||
|
case 0x00:
|
||||||
|
crypto = &mux.Plain{}
|
||||||
|
case 0x01:
|
||||||
|
crypto, err = mux.MakeAESCipher(UID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
goWeb(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
goWeb(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sesh, existing, err := user.GetSession(sessionID, mux.MakeObfs(UID, crypto), mux.MakeDeobfs(UID, crypto), util.ReadTLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
user.DelSession(sessionID)
|
user.DelSession(sessionID)
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"ProxyMethod":"shadowsocks",
|
"ProxyMethod":"shadowsocks",
|
||||||
|
"EncryptionMethod":"plain",
|
||||||
"UID":"iGAO85zysIyR4c09CyZSLdNhtP/ckcYu7nIPI082AHA=",
|
"UID":"iGAO85zysIyR4c09CyZSLdNhtP/ckcYu7nIPI082AHA=",
|
||||||
"PublicKey":"IYoUzkle/T/kriE+Ufdm7AHQtIeGnBWbhhlTbmDpUUI=",
|
"PublicKey":"IYoUzkle/T/kriE+Ufdm7AHQtIeGnBWbhhlTbmDpUUI=",
|
||||||
"ServerName":"www.bing.com",
|
"ServerName":"www.bing.com",
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func MakeRandomField(sta *State) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeSessionTicket(sta *State) []byte {
|
func MakeSessionTicket(sta *State) []byte {
|
||||||
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID+sessionID 36 bytes and proxy method 16 bytes][padding 108 bytes]
|
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID+sessionID 36 bytes, proxy method 16 bytes, encryption method 1 byte][padding 107 bytes]
|
||||||
// The first 16 bytes of the marshalled ephemeral public key is used as the IV
|
// The first 16 bytes of the marshalled ephemeral public key is used as the IV
|
||||||
// for encrypting the UID
|
// for encrypting the UID
|
||||||
tthInterval := sta.Now().Unix() / int64(sta.TicketTimeHint)
|
tthInterval := sta.Now().Unix() / int64(sta.TicketTimeHint)
|
||||||
|
|
@ -52,12 +52,15 @@ func MakeSessionTicket(sta *State) []byte {
|
||||||
ticket := make([]byte, 192)
|
ticket := make([]byte, 192)
|
||||||
copy(ticket[0:32], ecdh.Marshal(ephKP.PublicKey))
|
copy(ticket[0:32], ecdh.Marshal(ephKP.PublicKey))
|
||||||
key := ecdh.GenerateSharedSecret(ephKP.PrivateKey, sta.staticPub)
|
key := ecdh.GenerateSharedSecret(ephKP.PrivateKey, sta.staticPub)
|
||||||
plain := make([]byte, 52)
|
|
||||||
|
plain := make([]byte, 53)
|
||||||
copy(plain, sta.UID)
|
copy(plain, sta.UID)
|
||||||
binary.BigEndian.PutUint32(plain[32:36], sta.sessionID)
|
binary.BigEndian.PutUint32(plain[32:36], sta.sessionID)
|
||||||
copy(plain[36:52], []byte(sta.ProxyMethod))
|
copy(plain[36:52], []byte(sta.ProxyMethod))
|
||||||
|
plain[52] = sta.EncryptionMethod
|
||||||
|
|
||||||
cipher := util.AESEncrypt(ticket[0:16], key, plain)
|
cipher := util.AESEncrypt(ticket[0:16], key, plain)
|
||||||
copy(ticket[32:84], cipher)
|
copy(ticket[32:85], cipher)
|
||||||
// The purpose of adding sessionID is that, the generated padding of sessionTicket needs to be unpredictable.
|
// 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
|
// 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
|
// needs to be the same for each TicketTimeHint interval. However the value of epoch/TicketTimeHint
|
||||||
|
|
@ -68,6 +71,6 @@ func MakeSessionTicket(sta *State) []byte {
|
||||||
// With the sessionID value generated at startup of ckclient and used as a part of the seed, the
|
// 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
|
// 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.
|
// how it was generated. It will also be different for each client.
|
||||||
copy(ticket[84:192], util.PsudoRandBytes(108, tthInterval+int64(sta.sessionID)))
|
copy(ticket[85:192], util.PsudoRandBytes(107, tthInterval+int64(sta.sessionID)))
|
||||||
return ticket
|
return ticket
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import (
|
||||||
type rawConfig struct {
|
type rawConfig struct {
|
||||||
ServerName string
|
ServerName string
|
||||||
ProxyMethod string
|
ProxyMethod string
|
||||||
|
EncryptionMethod string
|
||||||
UID string
|
UID string
|
||||||
PublicKey string
|
PublicKey string
|
||||||
TicketTimeHint int
|
TicketTimeHint int
|
||||||
|
|
@ -38,6 +39,7 @@ type State struct {
|
||||||
keyPairs map[int64]*keyPair
|
keyPairs map[int64]*keyPair
|
||||||
|
|
||||||
ProxyMethod string
|
ProxyMethod string
|
||||||
|
EncryptionMethod byte
|
||||||
TicketTimeHint int
|
TicketTimeHint int
|
||||||
ServerName string
|
ServerName string
|
||||||
BrowserSig string
|
BrowserSig string
|
||||||
|
|
@ -104,11 +106,22 @@ func (sta *State) ParseConfig(conf string) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch preParse.EncryptionMethod {
|
||||||
|
case "plain":
|
||||||
|
sta.EncryptionMethod = 0x00
|
||||||
|
case "aes":
|
||||||
|
sta.EncryptionMethod = 0x01
|
||||||
|
default:
|
||||||
|
return errors.New("Unknown encryption method")
|
||||||
|
}
|
||||||
|
|
||||||
sta.ProxyMethod = preParse.ProxyMethod
|
sta.ProxyMethod = preParse.ProxyMethod
|
||||||
sta.ServerName = preParse.ServerName
|
sta.ServerName = preParse.ServerName
|
||||||
sta.TicketTimeHint = preParse.TicketTimeHint
|
sta.TicketTimeHint = preParse.TicketTimeHint
|
||||||
sta.BrowserSig = preParse.BrowserSig
|
sta.BrowserSig = preParse.BrowserSig
|
||||||
sta.NumConn = preParse.NumConn
|
sta.NumConn = preParse.NumConn
|
||||||
|
|
||||||
uid, err := base64.StdEncoding.DecodeString(preParse.UID)
|
uid, err := base64.StdEncoding.DecodeString(preParse.UID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Failed to parse UID: " + err.Error())
|
return errors.New("Failed to parse UID: " + err.Error())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package multiplex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Crypto interface {
|
||||||
|
encrypt([]byte) []byte
|
||||||
|
decrypt([]byte) []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plain struct{}
|
||||||
|
|
||||||
|
func (p *Plain) encrypt(plaintext []byte) []byte {
|
||||||
|
return plaintext
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plain) decrypt(buf []byte) []byte {
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
type AES struct {
|
||||||
|
cipher cipher.Block
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeAESCipher(key []byte) (*AES, error) {
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := AES{
|
||||||
|
c,
|
||||||
|
}
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AES) encrypt(plaintext []byte) []byte {
|
||||||
|
iv := make([]byte, 16)
|
||||||
|
rand.Read(iv)
|
||||||
|
ciphertext := make([]byte, 16+len(plaintext))
|
||||||
|
stream := cipher.NewCTR(a.cipher, iv)
|
||||||
|
stream.XORKeyStream(ciphertext[16:], plaintext)
|
||||||
|
copy(ciphertext[:16], iv)
|
||||||
|
return ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AES) decrypt(buf []byte) []byte {
|
||||||
|
stream := cipher.NewCTR(a.cipher, buf[0:16])
|
||||||
|
stream.XORKeyStream(buf[16:], buf[16:])
|
||||||
|
return buf[16:]
|
||||||
|
}
|
||||||
|
|
@ -15,15 +15,13 @@ var u32 = binary.BigEndian.Uint32
|
||||||
|
|
||||||
const headerLen = 12
|
const headerLen = 12
|
||||||
|
|
||||||
// For each frame, the three parts of the header is xored with three keys.
|
|
||||||
// The keys are generated from the SID and the payload of the frame.
|
|
||||||
func genXorKeys(key, nonce []byte) (i uint32, ii uint32, iii uint8) {
|
func genXorKeys(key, nonce []byte) (i uint32, ii uint32, iii uint8) {
|
||||||
h := sha1.New()
|
h := sha1.New()
|
||||||
hashed := h.Sum(append(key, nonce...))
|
hashed := h.Sum(append(key, nonce...))
|
||||||
return u32(hashed[0:4]), u32(hashed[4:8]), hashed[8]
|
return u32(hashed[0:4]), u32(hashed[4:8]), hashed[8]
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeObfs(key []byte) Obfser {
|
func MakeObfs(key []byte, algo Crypto) Obfser {
|
||||||
obfs := func(f *Frame) ([]byte, error) {
|
obfs := func(f *Frame) ([]byte, error) {
|
||||||
obfsedHeader := make([]byte, headerLen)
|
obfsedHeader := make([]byte, headerLen)
|
||||||
// header: [StreamID 4 bytes][Seq 4 bytes][Closing 1 byte][Nonce 3 bytes]
|
// header: [StreamID 4 bytes][Seq 4 bytes][Closing 1 byte][Nonce 3 bytes]
|
||||||
|
|
@ -33,22 +31,24 @@ func MakeObfs(key []byte) Obfser {
|
||||||
binary.BigEndian.PutUint32(obfsedHeader[4:8], f.Seq^ii)
|
binary.BigEndian.PutUint32(obfsedHeader[4:8], f.Seq^ii)
|
||||||
obfsedHeader[8] = f.Closing ^ iii
|
obfsedHeader[8] = f.Closing ^ iii
|
||||||
|
|
||||||
|
encryptedPayload := algo.encrypt(f.Payload)
|
||||||
|
|
||||||
// Composing final obfsed message
|
// Composing final obfsed message
|
||||||
// We don't use util.AddRecordLayer here to avoid unnecessary malloc
|
// We don't use util.AddRecordLayer here to avoid unnecessary malloc
|
||||||
obfsed := make([]byte, 5+headerLen+len(f.Payload))
|
obfsed := make([]byte, 5+headerLen+len(encryptedPayload))
|
||||||
obfsed[0] = 0x17
|
obfsed[0] = 0x17
|
||||||
obfsed[1] = 0x03
|
obfsed[1] = 0x03
|
||||||
obfsed[2] = 0x03
|
obfsed[2] = 0x03
|
||||||
binary.BigEndian.PutUint16(obfsed[3:5], uint16(headerLen+len(f.Payload)))
|
binary.BigEndian.PutUint16(obfsed[3:5], uint16(headerLen+len(encryptedPayload)))
|
||||||
copy(obfsed[5:5+headerLen], obfsedHeader)
|
copy(obfsed[5:5+headerLen], obfsedHeader)
|
||||||
copy(obfsed[5+headerLen:], f.Payload)
|
copy(obfsed[5+headerLen:], encryptedPayload)
|
||||||
// obfsed: [record layer 5 bytes][cipherheader 12 bytes][payload]
|
// obfsed: [record layer 5 bytes][cipherheader 12 bytes][payload]
|
||||||
return obfsed, nil
|
return obfsed, nil
|
||||||
}
|
}
|
||||||
return obfs
|
return obfs
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeDeobfs(key []byte) Deobfser {
|
func MakeDeobfs(key []byte, algo Crypto) Deobfser {
|
||||||
deobfs := func(in []byte) (*Frame, error) {
|
deobfs := func(in []byte) (*Frame, error) {
|
||||||
if len(in) < 5+headerLen {
|
if len(in) < 5+headerLen {
|
||||||
return nil, errors.New("Input cannot be shorter than 17 bytes")
|
return nil, errors.New("Input cannot be shorter than 17 bytes")
|
||||||
|
|
@ -58,13 +58,16 @@ func MakeDeobfs(key []byte) Deobfser {
|
||||||
streamID := u32(peeled[0:4]) ^ i
|
streamID := u32(peeled[0:4]) ^ i
|
||||||
seq := u32(peeled[4:8]) ^ ii
|
seq := u32(peeled[4:8]) ^ ii
|
||||||
closing := peeled[8] ^ iii
|
closing := peeled[8] ^ iii
|
||||||
payload := make([]byte, len(peeled)-headerLen)
|
|
||||||
copy(payload, peeled[headerLen:])
|
rawPayload := make([]byte, len(peeled)-headerLen)
|
||||||
|
copy(rawPayload, peeled[headerLen:])
|
||||||
|
decryptedPayload := algo.decrypt(rawPayload)
|
||||||
|
|
||||||
ret := &Frame{
|
ret := &Frame{
|
||||||
StreamID: streamID,
|
StreamID: streamID,
|
||||||
Seq: seq,
|
Seq: seq,
|
||||||
Closing: closing,
|
Closing: closing,
|
||||||
Payload: payload,
|
Payload: decryptedPayload,
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// input ticket, return UID
|
// input ticket, return UID
|
||||||
func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) ([]byte, uint32, string) {
|
func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) ([]byte, uint32, string, byte) {
|
||||||
ephPub, _ := ecdh.Unmarshal(ticket[0:32])
|
ephPub, _ := ecdh.Unmarshal(ticket[0:32])
|
||||||
key := ecdh.GenerateSharedSecret(staticPv, ephPub)
|
key := ecdh.GenerateSharedSecret(staticPv, ephPub)
|
||||||
plain := util.AESDecrypt(ticket[0:16], key, ticket[32:84])
|
plain := util.AESDecrypt(ticket[0:16], key, ticket[32:85])
|
||||||
sessionID := binary.BigEndian.Uint32(plain[32:36])
|
sessionID := binary.BigEndian.Uint32(plain[32:36])
|
||||||
return plain[0:32], sessionID, string(bytes.Trim(plain[36:52], "\x00"))
|
return plain[0:32], sessionID, string(bytes.Trim(plain[36:52], "\x00")), plain[52]
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateRandom(random []byte, UID []byte, time int64) bool {
|
func validateRandom(random []byte, UID []byte, time int64) bool {
|
||||||
|
|
@ -32,7 +32,7 @@ func validateRandom(random []byte, UID []byte, time int64) bool {
|
||||||
h.Write(preHash)
|
h.Write(preHash)
|
||||||
return bytes.Equal(h.Sum(nil)[0:16], random[16:32])
|
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) {
|
func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte) {
|
||||||
var random [32]byte
|
var random [32]byte
|
||||||
copy(random[:], ch.random)
|
copy(random[:], ch.random)
|
||||||
|
|
||||||
|
|
@ -43,17 +43,17 @@ func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID u
|
||||||
|
|
||||||
if used != 0 {
|
if used != 0 {
|
||||||
log.Println("Replay! Duplicate random")
|
log.Println("Replay! Duplicate random")
|
||||||
return false, nil, 0, ""
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticket := ch.extensions[[2]byte{0x00, 0x23}]
|
ticket := ch.extensions[[2]byte{0x00, 0x23}]
|
||||||
if len(ticket) < 68 {
|
if len(ticket) < 68 {
|
||||||
return false, nil, 0, ""
|
return
|
||||||
}
|
}
|
||||||
UID, sessionID, proxyMethod = decryptSessionTicket(sta.staticPv, ticket)
|
UID, sessionID, proxyMethod, encryptionMethod = decryptSessionTicket(sta.staticPv, ticket)
|
||||||
isCK = validateRandom(ch.random, UID, sta.Now().Unix())
|
isCK = validateRandom(ch.random, UID, sta.Now().Unix())
|
||||||
if !isCK {
|
if !isCK {
|
||||||
return false, nil, 0, ""
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ func TestDecryptSessionTicket(t *testing.T) {
|
||||||
staticPv, _ := ecdh.Unmarshal(pvb)
|
staticPv, _ := ecdh.Unmarshal(pvb)
|
||||||
sessionTicket, _ := hex.DecodeString("f586223b50cada583d61dc9bf3d01cc3a45aab4b062ed6a31ead0badb87f7761aab4f9f737a1d8ff2a2aa4d50ceb808844588ee3c8fdf36c33a35ef5003e287337659c8164a7949e9e63623090763fc24d0386c8904e47bdd740e09dd9b395c72de669629c2a865ed581452d23306adf26de0c8a46ee05e3dac876f2bcd9a2de946d319498f579383d06b3e66b3aca05f533fdc5f017eeba45b42080aabd4f71151fa0dfc1b0e23be4ed3abdb47adc0d5740ca7b7689ad34426309fb6984a086")
|
sessionTicket, _ := hex.DecodeString("f586223b50cada583d61dc9bf3d01cc3a45aab4b062ed6a31ead0badb87f7761aab4f9f737a1d8ff2a2aa4d50ceb808844588ee3c8fdf36c33a35ef5003e287337659c8164a7949e9e63623090763fc24d0386c8904e47bdd740e09dd9b395c72de669629c2a865ed581452d23306adf26de0c8a46ee05e3dac876f2bcd9a2de946d319498f579383d06b3e66b3aca05f533fdc5f017eeba45b42080aabd4f71151fa0dfc1b0e23be4ed3abdb47adc0d5740ca7b7689ad34426309fb6984a086")
|
||||||
|
|
||||||
decryUID, decrySessionID, _ := decryptSessionTicket(staticPv, sessionTicket)
|
decryUID, decrySessionID, _, _ := decryptSessionTicket(staticPv, sessionTicket)
|
||||||
if !bytes.Equal(decryUID, UID) {
|
if !bytes.Equal(decryUID, UID) {
|
||||||
t.Error(
|
t.Error(
|
||||||
"For", "UID",
|
"For", "UID",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue