From 5684fa2362e42f2f7e6224ded0c6874b2f6c345a Mon Sep 17 00:00:00 2001 From: Juan Batiz-Benet <juan@benet.ai> Date: Sun, 14 Sep 2014 04:19:43 -0700 Subject: [PATCH] removed old identify --- identify/identify.go | 311 ------------------------------------------- 1 file changed, 311 deletions(-) delete mode 100644 identify/identify.go diff --git a/identify/identify.go b/identify/identify.go deleted file mode 100644 index b6b89678..00000000 --- a/identify/identify.go +++ /dev/null @@ -1,311 +0,0 @@ -// Package identify handles how peers identify with eachother upon -// connection to the network -package identify - -import ( - "bytes" - "errors" - "strings" - - "crypto/aes" - "crypto/cipher" - "crypto/hmac" - "crypto/rand" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "hash" - - proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" - ci "github.com/jbenet/go-ipfs/crypto" - peer "github.com/jbenet/go-ipfs/peer" - u "github.com/jbenet/go-ipfs/util" -) - -// List of supported protocols--each section in order of preference. -// Takes the form: ECDH curves : Ciphers : Hashes -var SupportedExchanges = "P-256,P-224,P-384,P-521" -var SupportedCiphers = "AES-256,AES-128" -var SupportedHashes = "SHA256,SHA512,SHA1" - -// ErrUnsupportedKeyType is returned when a private key cast/type switch fails. -var ErrUnsupportedKeyType = errors.New("unsupported key type") - -// Performs initial communication with this peer to share node ID's and -// initiate communication. (secureIn, secureOut, error) -func Handshake(self, remote *peer.Peer, in <-chan []byte, out chan<- []byte) (<-chan []byte, chan<- []byte, error) { - // Generate and send Hello packet. - // Hello = (rand, PublicKey, Supported) - nonce := make([]byte, 16) - _, err := rand.Read(nonce) - if err != nil { - return nil, nil, err - } - - hello := new(Hello) - - myPubKey, err := self.PubKey.Bytes() - if err != nil { - return nil, nil, err - } - - hello.Rand = nonce - hello.Pubkey = myPubKey - hello.Exchanges = &SupportedExchanges - hello.Ciphers = &SupportedCiphers - hello.Hashes = &SupportedHashes - - encoded, err := proto.Marshal(hello) - if err != nil { - return nil, nil, err - } - - out <- encoded - - // Parse their Hello packet and generate an Exchange packet. - // Exchange = (EphemeralPubKey, Signature) - resp := <-in - - helloResp := new(Hello) - err = proto.Unmarshal(resp, helloResp) - if err != nil { - return nil, nil, err - } - - remote.PubKey, err = ci.UnmarshalPublicKey(helloResp.GetPubkey()) - if err != nil { - return nil, nil, err - } - - remote.ID, err = IDFromPubKey(remote.PubKey) - if err != nil { - return nil, nil, err - } - - exchange, err := selectBest(SupportedExchanges, helloResp.GetExchanges()) - if err != nil { - return nil, nil, err - } - - cipherType, err := selectBest(SupportedCiphers, helloResp.GetCiphers()) - if err != nil { - return nil, nil, err - } - - hashType, err := selectBest(SupportedHashes, helloResp.GetHashes()) - if err != nil { - return nil, nil, err - } - - epubkey, done, err := ci.GenerateEKeyPair(exchange) // Generate EphemeralPubKey - if err != nil { - return nil, nil, err - } - - var handshake bytes.Buffer // Gather corpus to sign. - handshake.Write(encoded) - handshake.Write(resp) - handshake.Write(epubkey) - - exPacket := new(Exchange) - - exPacket.Epubkey = epubkey - exPacket.Signature, err = self.PrivKey.Sign(handshake.Bytes()) - if err != nil { - return nil, nil, err - } - - exEncoded, err := proto.Marshal(exPacket) - if err != nil { - return nil, nil, err - } - - out <- exEncoded - - // Parse their Exchange packet and generate a Finish packet. - // Finish = E('Finish') - resp1 := <-in - - exchangeResp := new(Exchange) - err = proto.Unmarshal(resp1, exchangeResp) - if err != nil { - return nil, nil, err - } - - var theirHandshake bytes.Buffer - _, err = theirHandshake.Write(resp) - if err != nil { - return nil, nil, err - } - _, err = theirHandshake.Write(encoded) - if err != nil { - return nil, nil, err - } - _, err = theirHandshake.Write(exchangeResp.GetEpubkey()) - if err != nil { - return nil, nil, err - } - - ok, err := remote.PubKey.Verify(theirHandshake.Bytes(), exchangeResp.GetSignature()) - if err != nil { - return nil, nil, err - } - - if !ok { - return nil, nil, errors.New("Bad signature!") - } - - secret, err := done(exchangeResp.GetEpubkey()) - if err != nil { - return nil, nil, err - } - - cmp := bytes.Compare(myPubKey, helloResp.GetPubkey()) - mIV, tIV, mCKey, tCKey, mMKey, tMKey := ci.KeyStretcher(cmp, cipherType, hashType, secret) - - secureIn := make(chan []byte) - secureOut := make(chan []byte) - - go secureInProxy(in, secureIn, hashType, tIV, tCKey, tMKey) - go secureOutProxy(out, secureOut, hashType, mIV, mCKey, mMKey) - - finished := []byte("Finished") - - secureOut <- finished - resp2 := <-secureIn - - if bytes.Compare(resp2, finished) != 0 { - return nil, nil, errors.New("Negotiation failed.") - } - - u.DOut("[%s] identify: Got node id: %s\n", self.ID.Pretty(), remote.ID.Pretty()) - - return secureIn, secureOut, nil -} - -func makeMac(hashType string, key []byte) (hash.Hash, int) { - switch hashType { - case "SHA1": - return hmac.New(sha1.New, key), sha1.Size - case "SHA512": - return hmac.New(sha512.New, key), sha512.Size - default: - return hmac.New(sha256.New, key), sha256.Size - } -} - -func secureInProxy(in <-chan []byte, secureIn chan<- []byte, hashType string, tIV, tCKey, tMKey []byte) { - theirBlock, _ := aes.NewCipher(tCKey) - theirCipher := cipher.NewCTR(theirBlock, tIV) - - theirMac, macSize := makeMac(hashType, tMKey) - - for { - data, ok := <-in - if !ok { - close(secureIn) - return - } - - if len(data) <= macSize { - continue - } - - mark := len(data) - macSize - buff := make([]byte, mark) - - theirCipher.XORKeyStream(buff, data[0:mark]) - - theirMac.Write(data[0:mark]) - expected := theirMac.Sum(nil) - theirMac.Reset() - - hmacOk := hmac.Equal(data[mark:], expected) - - if hmacOk { - secureIn <- buff - } else { - secureIn <- nil - } - } -} - -func secureOutProxy(out chan<- []byte, secureOut <-chan []byte, hashType string, mIV, mCKey, mMKey []byte) { - myBlock, _ := aes.NewCipher(mCKey) - myCipher := cipher.NewCTR(myBlock, mIV) - - myMac, macSize := makeMac(hashType, mMKey) - - for { - data, ok := <-secureOut - if !ok { - close(out) - return - } - - if len(data) == 0 { - continue - } - - buff := make([]byte, len(data)+macSize) - - myCipher.XORKeyStream(buff, data) - - myMac.Write(buff[0:len(data)]) - copy(buff[len(data):], myMac.Sum(nil)) - myMac.Reset() - - out <- buff - } -} - -// IDFromPubKey returns Nodes ID given its public key -func IDFromPubKey(pk ci.PubKey) (peer.ID, error) { - b, err := pk.Bytes() - if err != nil { - return nil, err - } - hash, err := u.Hash(b) - if err != nil { - return nil, err - } - return peer.ID(hash), nil -} - -// Determines which algorithm to use. Note: f(a, b) = f(b, a) -func selectBest(myPrefs, theirPrefs string) (string, error) { - // Person with greatest hash gets first choice. - myHash, err := u.Hash([]byte(myPrefs)) - if err != nil { - return "", err - } - - theirHash, err := u.Hash([]byte(theirPrefs)) - if err != nil { - return "", err - } - - cmp := bytes.Compare(myHash, theirHash) - var firstChoiceArr, secChoiceArr []string - - if cmp == -1 { - firstChoiceArr = strings.Split(theirPrefs, ",") - secChoiceArr = strings.Split(myPrefs, ",") - } else if cmp == 1 { - firstChoiceArr = strings.Split(myPrefs, ",") - secChoiceArr = strings.Split(theirPrefs, ",") - } else { // Exact same preferences. - myPrefsArr := strings.Split(myPrefs, ",") - return myPrefsArr[0], nil - } - - for _, secChoice := range secChoiceArr { - for _, firstChoice := range firstChoiceArr { - if firstChoice == secChoice { - return firstChoice, nil - } - } - } - - return "", errors.New("No algorithms in common!") -} -- GitLab