From 99afb1a58bd9532b73f806de008415984f0fa3dc Mon Sep 17 00:00:00 2001 From: Qian Wang Date: Fri, 25 Jan 2019 00:24:47 +0000 Subject: [PATCH] Remove ECDH as an external dependancy and include it as a internal package --- cmd/ck-server/keygen.go | 7 ++-- go.mod | 3 +- internal/client/auth.go | 12 +++--- internal/client/auth_test.go | 10 ++--- internal/client/state.go | 5 +-- internal/ecdh/curve25519.go | 80 ++++++++++++++++++++++++++++++++++++ internal/server/auth.go | 7 ++-- internal/server/auth_test.go | 7 ++-- 8 files changed, 103 insertions(+), 28 deletions(-) create mode 100644 internal/ecdh/curve25519.go diff --git a/cmd/ck-server/keygen.go b/cmd/ck-server/keygen.go index b0f7958..77db0a6 100644 --- a/cmd/ck-server/keygen.go +++ b/cmd/ck-server/keygen.go @@ -3,7 +3,7 @@ package main import ( "crypto/rand" "encoding/base64" - ecdh "github.com/cbeuw/go-ecdh" + "github.com/cbeuw/Cloak/internal/ecdh" ) var b64 = base64.StdEncoding.EncodeToString @@ -15,9 +15,8 @@ func generateUID() string { } func generateKeyPair() (string, string) { - ec := ecdh.NewCurve25519ECDH() - staticPv, staticPub, _ := ec.GenerateKey(rand.Reader) - marshPub := ec.Marshal(staticPub) + staticPv, staticPub, _ := ecdh.GenerateKey(rand.Reader) + marshPub := ecdh.Marshal(staticPub) marshPv := staticPv.(*[32]byte)[:] return b64(marshPub), b64(marshPv) } diff --git a/go.mod b/go.mod index 1599f26..ebe340f 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,9 @@ module github.com/cbeuw/Cloak require ( github.com/boltdb/bolt v1.3.1 - github.com/cbeuw/go-ecdh v0.0.0-20161211032359-48726bab9208 github.com/juju/ratelimit v1.0.1 github.com/kr/pretty v0.1.0 // indirect - golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b // indirect + golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b golang.org/x/sys v0.0.0-20190124100055-b90733256f2e // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) diff --git a/internal/client/auth.go b/internal/client/auth.go index c2e52df..8fee4b2 100644 --- a/internal/client/auth.go +++ b/internal/client/auth.go @@ -5,9 +5,10 @@ import ( "crypto/rand" "crypto/sha256" "encoding/binary" - "github.com/cbeuw/Cloak/internal/util" - ecdh "github.com/cbeuw/go-ecdh" "io" + + "github.com/cbeuw/Cloak/internal/ecdh" + "github.com/cbeuw/Cloak/internal/util" ) type keyPair struct { @@ -37,11 +38,10 @@ func MakeSessionTicket(sta *State) []byte { // The first 16 bytes of the marshalled ephemeral public key is used as the IV // for encrypting the UID tthInterval := sta.Now().Unix() / int64(sta.TicketTimeHint) - ec := ecdh.NewCurve25519ECDH() sta.keyPairsM.Lock() ephKP := sta.keyPairs[tthInterval] if ephKP == nil { - ephPv, ephPub, _ := ec.GenerateKey(rand.Reader) + ephPv, ephPub, _ := ecdh.GenerateKey(rand.Reader) ephKP = &keyPair{ ephPv, ephPub, @@ -50,8 +50,8 @@ func MakeSessionTicket(sta *State) []byte { } sta.keyPairsM.Unlock() ticket := make([]byte, 192) - copy(ticket[0:32], ec.Marshal(ephKP.PublicKey)) - key, _ := ec.GenerateSharedSecret(ephKP.PrivateKey, sta.staticPub) + copy(ticket[0:32], ecdh.Marshal(ephKP.PublicKey)) + key := ecdh.GenerateSharedSecret(ephKP.PrivateKey, sta.staticPub) plainUIDsID := make([]byte, 36) copy(plainUIDsID, sta.UID) binary.BigEndian.PutUint32(plainUIDsID[32:36], sta.sessionID) diff --git a/internal/client/auth_test.go b/internal/client/auth_test.go index 897351c..408517c 100644 --- a/internal/client/auth_test.go +++ b/internal/client/auth_test.go @@ -9,16 +9,16 @@ import ( "encoding/binary" "encoding/hex" "fmt" - ecdh "github.com/cbeuw/go-ecdh" prand "math/rand" "testing" "time" + + "github.com/cbeuw/Cloak/internal/ecdh" ) func TestMakeSessionTicket(t *testing.T) { UID, _ := hex.DecodeString("26a8e88bcd7c64a69ca051740851d22a6818de2fddafc00882331f1c5a8b866c") - ec := ecdh.NewCurve25519ECDH() - staticPv, staticPub, _ := ec.GenerateKey(rand.Reader) + staticPv, staticPub, _ := ecdh.GenerateKey(rand.Reader) mockSta := &State{ Now: time.Now, sessionID: 42, @@ -31,8 +31,8 @@ func TestMakeSessionTicket(t *testing.T) { ticket := MakeSessionTicket(mockSta) // verification - ephPub, _ := ec.Unmarshal(ticket[0:32]) - key, _ := ec.GenerateSharedSecret(staticPv, ephPub) + ephPub, _ := ecdh.Unmarshal(ticket[0:32]) + key := ecdh.GenerateSharedSecret(staticPv, ephPub) // aes decrypt UIDsID := make([]byte, len(ticket[32:68])) diff --git a/internal/client/state.go b/internal/client/state.go index d304c53..2d25cc3 100644 --- a/internal/client/state.go +++ b/internal/client/state.go @@ -10,7 +10,7 @@ import ( "sync" "time" - ecdh "github.com/cbeuw/go-ecdh" + "github.com/cbeuw/Cloak/internal/ecdh" ) type rawConfig struct { @@ -116,8 +116,7 @@ func (sta *State) ParseConfig(conf string) (err error) { if err != nil { return errors.New("Failed to parse Public key: " + err.Error()) } - ec := ecdh.NewCurve25519ECDH() - pub, ok := ec.Unmarshal(pubBytes) + pub, ok := ecdh.Unmarshal(pubBytes) if !ok { return errors.New("Failed to unmarshal Public key") } diff --git a/internal/ecdh/curve25519.go b/internal/ecdh/curve25519.go new file mode 100644 index 0000000..94d066b --- /dev/null +++ b/internal/ecdh/curve25519.go @@ -0,0 +1,80 @@ +// This code is forked from https://github.com/wsddn/go-ecdh/blob/master/curve25519.go +/* +Copyright (c) 2014, tang0th +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of tang0th nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package ecdh + +import ( + "crypto" + "io" + + "golang.org/x/crypto/curve25519" +) + +func GenerateKey(rand io.Reader) (crypto.PrivateKey, crypto.PublicKey, error) { + var pub, priv [32]byte + var err error + + _, err = io.ReadFull(rand, priv[:]) + if err != nil { + return nil, nil, err + } + + priv[0] &= 248 + priv[31] &= 127 + priv[31] |= 64 + + curve25519.ScalarBaseMult(&pub, &priv) + + return &priv, &pub, nil +} + +func Marshal(p crypto.PublicKey) []byte { + pub := p.(*[32]byte) + return pub[:] +} + +func Unmarshal(data []byte) (crypto.PublicKey, bool) { + var pub [32]byte + if len(data) != 32 { + return nil, false + } + + copy(pub[:], data) + return &pub, true +} + +func GenerateSharedSecret(privKey crypto.PrivateKey, pubKey crypto.PublicKey) []byte { + var priv, pub, secret *[32]byte + + priv = privKey.(*[32]byte) + pub = pubKey.(*[32]byte) + secret = new([32]byte) + + curve25519.ScalarMult(secret, priv, pub) + return secret[:] +} diff --git a/internal/server/auth.go b/internal/server/auth.go index 784f55f..f778b45 100644 --- a/internal/server/auth.go +++ b/internal/server/auth.go @@ -7,15 +7,14 @@ import ( "encoding/binary" "log" + "github.com/cbeuw/Cloak/internal/ecdh" "github.com/cbeuw/Cloak/internal/util" - ecdh "github.com/cbeuw/go-ecdh" ) // input ticket, return UID func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) ([]byte, uint32) { - ec := ecdh.NewCurve25519ECDH() - ephPub, _ := ec.Unmarshal(ticket[0:32]) - key, _ := ec.GenerateSharedSecret(staticPv, ephPub) + ephPub, _ := ecdh.Unmarshal(ticket[0:32]) + key := ecdh.GenerateSharedSecret(staticPv, ephPub) UIDsID := util.AESDecrypt(ticket[0:16], key, ticket[32:68]) sessionID := binary.BigEndian.Uint32(UIDsID[32:36]) return UIDsID[0:32], sessionID diff --git a/internal/server/auth_test.go b/internal/server/auth_test.go index a3cab68..b7f0293 100644 --- a/internal/server/auth_test.go +++ b/internal/server/auth_test.go @@ -4,17 +4,16 @@ import ( "bytes" "encoding/hex" "fmt" - ecdh "github.com/cbeuw/go-ecdh" "testing" -) -var ec = ecdh.NewCurve25519ECDH() + "github.com/cbeuw/Cloak/internal/ecdh" +) func TestDecryptSessionTicket(t *testing.T) { UID, _ := hex.DecodeString("26a8e88bcd7c64a69ca051740851d22a6818de2fddafc00882331f1c5a8b866c") sessionID := uint32(42) pvb, _ := hex.DecodeString("083794692e77b28fa2152dfee53142185fd58ea8172d3545fdeeaea97b3c597c") - staticPv, _ := ec.Unmarshal(pvb) + staticPv, _ := ecdh.Unmarshal(pvb) sessionTicket, _ := hex.DecodeString("f586223b50cada583d61dc9bf3d01cc3a45aab4b062ed6a31ead0badb87f7761aab4f9f737a1d8ff2a2aa4d50ceb808844588ee3c8fdf36c33a35ef5003e287337659c8164a7949e9e63623090763fc24d0386c8904e47bdd740e09dd9b395c72de669629c2a865ed581452d23306adf26de0c8a46ee05e3dac876f2bcd9a2de946d319498f579383d06b3e66b3aca05f533fdc5f017eeba45b42080aabd4f71151fa0dfc1b0e23be4ed3abdb47adc0d5740ca7b7689ad34426309fb6984a086") decryUID, decrySessionID := decryptSessionTicket(staticPv, sessionTicket)