Example #1
0
func (hs *ssDHClientHandshake) parseServerHandshake(resp []byte) (int, []byte, error) {
	if len(resp) < minHandshakeLength {
		return 0, nil, errMarkNotFoundYet
	}

	// The server response is Y | P_S | M_S | MAC(Y | P_S | M_S | E).
	if hs.serverPublicKey == nil {
		y := resp[:uniformdh.Size]

		// Pull out the public key, and derive the server mark.
		hs.serverPublicKey = &uniformdh.PublicKey{}
		if err := hs.serverPublicKey.SetBytes(y); err != nil {
			return 0, nil, err
		}
		hs.mac.Reset()
		hs.mac.Write(y)
		hs.serverMark = hs.mac.Sum(nil)[:macLength]
	}

	// Find the mark+MAC, if it exits.
	endPos := len(resp)
	if endPos > maxHandshakeLength-macLength {
		endPos = maxHandshakeLength - macLength
	}
	pos := bytes.Index(resp[uniformdh.Size:endPos], hs.serverMark)
	if pos == -1 {
		if len(resp) >= maxHandshakeLength {
			// Couldn't find the mark in a maximum length response.
			return 0, nil, ErrInvalidHandshake
		}
		return 0, nil, errMarkNotFoundYet
	} else if len(resp) < pos+2*macLength {
		// Didn't receive the full M_S.
		return 0, nil, errMarkNotFoundYet
	}
	pos += uniformdh.Size

	// Validate the MAC.
	hs.mac.Write(resp[uniformdh.Size : pos+macLength])
	hs.mac.Write(hs.epochHour)
	macCmp := hs.mac.Sum(nil)[:macLength]
	macRx := resp[pos+macLength : pos+2*macLength]
	if !hmac.Equal(macCmp, macRx) {
		return 0, nil, ErrInvalidHandshake
	}

	// Derive the shared secret.
	ss, err := uniformdh.Handshake(hs.keypair, hs.serverPublicKey)
	if err != nil {
		return 0, nil, err
	}
	seed := sha256.Sum256(ss)
	return pos + 2*macLength, seed[:], nil
}
Example #2
0
func (conn *obfs3Conn) handshake() error {
	// The party who opens the connection is the 'initiator'; the one who
	// accepts it is the 'responder'.  Each begins by generating a
	// UniformDH keypair, and a random number PADLEN in [0, MAX_PADDING/2].
	// Both parties then send:
	//
	//  PUB_KEY | WR(PADLEN)
	privateKey, err := uniformdh.GenerateKey(csrand.Reader)
	if err != nil {
		return err
	}
	padLen := csrand.IntRange(0, maxPadding/2)
	blob := make([]byte, uniformdh.Size+padLen)
	publicKey, err := privateKey.PublicKey.Bytes()
	if err != nil {
		return err
	}
	copy(blob[0:], publicKey)
	if err := csrand.Bytes(blob[uniformdh.Size:]); err != nil {
		return err
	}
	if _, err := conn.Conn.Write(blob); err != nil {
		return err
	}

	// Read the public key from the peer.
	rawPeerPublicKey := make([]byte, uniformdh.Size)
	if _, err := io.ReadFull(conn.Conn, rawPeerPublicKey); err != nil {
		return err
	}
	var peerPublicKey uniformdh.PublicKey
	if err := peerPublicKey.SetBytes(rawPeerPublicKey); err != nil {
		return err
	}

	// After retrieving the public key of the other end, each party
	// completes the DH key exchange and generates a shared-secret for the
	// session (named SHARED_SECRET).
	sharedSecret, err := uniformdh.Handshake(privateKey, &peerPublicKey)
	if err != nil {
		return err
	}
	if err := conn.kdf(sharedSecret); err != nil {
		return err
	}

	return nil
}