예제 #1
0
// verifyChallengeResponse is a kademlia.ResponseFunc, hence the elaborate signature
// remote is the room requester
// c is the challenge issuer, and also the verifier
func (c *client) verifyChallengeResponse(remote *kademlia.RemoteNode, token string, source kademlia.NodeID, data interface{}) {
	defer delete(c.Network.AwaitingResponse, token)
	defer delete(c.Network.ExtraInfo, token)

	response, ok := data.(string)
	if !ok {
		// shit
	}

	var answer answerPacket
	err := msgpack.Unmarshal([]byte(response), &answer)

	if err != nil {
		// shit - TODO
	}

	chatRoomID, ok := c.Network.ExtraInfo[token].(string)
	if !ok {
		// shit - TODO
	}
	chatRoom := c.chatroomsID[chatRoomID]

	valid := chatRoom.groupPrivateKey.Group.Verify([]byte(chatRoomID), sha1.New(), []byte(answer.ChallengeAnswer))

	if valid {
		// send group private key to user
		groupPriv := pem.EncodeToMemory(&pem.Block{Type: "GROUP PRIVATE KEY", Bytes: chatRoom.groupPrivateKey.Marshal()})

		r := c.Network.Node.GetNode(source)
		if r == nil {
			// shit
		}

		address := *remote.Address
		address.Port = answer.Port

		chatRoom.participants[string(source)] = &address

		msg := validChallengeResponse{chatRoomID, groupPriv, chatRoom.Name, c.port, chatRoom.participants}
		message, _ := kademlia.NewMessage()
		message.MessageType = "GROUP_PRIVATE_KEY"
		message.SourceID = c.Network.Node.ID
		message.Token = token
		message.InsertMessage(msg)

		kademlia.SendMsg(c.Network.Connection, remote.Address, message)

		chatRoom.trustedPeers = append(chatRoom.trustedPeers, r)
		return
	}

	message, _ := kademlia.NewMessage()
	message.MessageType = "FAILED_CHALLENGE"
	message.SourceID = c.Network.Node.ID
	message.Token = token

	kademlia.SendMsg(c.Network.Connection, remote.Address, message)

}
예제 #2
0
// challengeResponse is a kademlia.ResponseFunc, hence the elaborate signature
// remote is the challenge issuer
// c is the room requester
func (c *client) challengeResponse(remote *kademlia.RemoteNode, token string, source kademlia.NodeID, data interface{}) {
	// no deleting from AwaitingResponse because the process is not complete yet

	roomID, ok := data.(string)
	if !ok {
		panic("data is not a string. No Room ID")
	}

	chatRoom, ok := c.chatroomsID[roomID]
	if !ok {
		log.Printf("Chatroom not found when responding to challenge. ID: %#v\n", c.chatroomsID)
		c.ui <- "...Chatroom not found when responding to challenge"
		return
	}

	answer := answerChallenge(roomID, chatRoom.memberPrivateKey)

	message, _ := kademlia.NewMessage()
	message.MessageType = "CHALLENGE_RESPONSE"
	message.SourceID = c.Network.Node.ID
	message.InsertMessage(answerPacket{answer, c.port})
	message.Token = token

	kademlia.SendMsg(c.Network.Connection, remote.Address, message)

	// update last response time
	c.Network.AwaitingResponse[token] = time.Now()
}
예제 #3
0
// issueChallenge is a kademlia.ResponseFunc, hence the elaborate signature
// remote is the address on the envelope (i.e. the room requester)
// c is the challenge issuer
func (c *client) issueChallenge(remote *kademlia.RemoteNode, token string, source kademlia.NodeID, data interface{}) {
	roomID, _ := data.(string)
	// todo : what if data is not a string

	message, _ := kademlia.NewMessage()
	message.MessageType = "CHALLENGE"
	message.SourceID = c.Network.Node.ID
	message.Message = roomID
	message.Token = token

	kademlia.SendMsg(c.Network.Connection, remote.Address, message)

	c.Network.AwaitingResponse[token] = time.Now()
	c.Network.ExtraInfo[token] = roomID

}
예제 #4
0
// RequestRoom sends a message via the Kademlia network, looking for nodes with the chatroom ID
func (c *client) RequestRoom(ID string) {
	// find a node with the chatroom id first
	tmpRemote := c.Network.Node.GetNearestNode()
	log.Printf("Nearest Node is: %#v\n", tmpRemote.ID)

	if tmpRemote == nil {
		c.ui <- "...No remote node found" // typically because well, the client is not connected to the kademlia network.
		return
	}

	// issue FIND_VALUE
	token := c.Network.FindValue(tmpRemote, ID)
	ch, ok := c.Network.ResultChan[token]
	defer delete(c.Network.ResultChan, token) // clean up after oneself

	if !ok {
		c.ui <- "...No result channel created for room request"
		return
	}

	var id kademlia.NodeID
	tmp := <-ch
	asBytes, ok := tmp.([]byte)

	if !ok {
		panic("SHIT SHIT")
	}

	err := msgpack.Unmarshal(asBytes, &id)
	if err != nil {
		c.ui <- fmt.Sprintf("...Unable to unmarshal. Error was: %s", err)
		return
	}

	// found the ID? get the remoteNode so we can send it a message asking for a challenge
	remote := c.Network.Node.GetNode(id)

	// get the relevant room settings - member key
	memberFileName := fmt.Sprintf("keys/%s_member.pem", ID)
	memberPemData, err := ioutil.ReadFile(memberFileName)
	if err != nil {
		//shit
		c.ui <- fmt.Sprintf("...No pem file available for room request. It should be in keys/%s_member.pem", ID)
		return
	}

	block, _ := pem.Decode(memberPemData)
	if block == nil {
		// shit
		c.ui <- fmt.Sprintf("...block is not a pem encoded file. Check keys/%s_member.pem", ID)
	}
	if block.Type != "MEMBER PRIVATE KEY" {
		c.ui <- "...Incorrect pem type. Expected MEMBER PRIVATE KEY"
		return
	}

	// get the relevant room settings - public key
	publicFileName := fmt.Sprintf("chatrooms/%s_public.pem", ID)
	publicPemData, err := ioutil.ReadFile(publicFileName)
	if err != nil {
		// shit
		c.ui <- fmt.Sprintf("...No room publick pem file available. It should be in chatrooms/%s_public.pem", ID)
		return
	}

	publicBlock, _ := pem.Decode(publicPemData)
	if publicBlock == nil {
		//shit
		c.ui <- fmt.Sprintf("...Public block is not a pem encoded file. Check chatrooms/%s_public.pem", ID)
		return
	}
	if publicBlock.Type != "GROUP PUBLIC KEY" {
		c.ui <- "...Incorrect pem type. Expected GROUP PUBLIC KEY"
		return
	}

	// create a dummy chatroom. The dummy chatroom is required because to unmarshal the keys, a key is needed to begin with
	chatRoom := createChatroom()
	c.chatroomsID[ID] = chatRoom
	chatRoom.ID = ID

	group, success := chatRoom.groupPublicKey.Unmarshal(publicBlock.Bytes)
	if !success {
		c.ui <- "...Unable to unmarshal group public key"
		return
	}

	memberPriv, success := chatRoom.memberPrivateKey.Unmarshal(group, block.Bytes)
	if !success {
		c.ui <- "...Unable to unmarshal member private key"
		return
	}

	// settings that are important to the challenge - these are dummy keys which are required to unmarshal
	chatRoom.groupPublicKey = group
	chatRoom.memberPrivateKey = memberPriv

	// send message
	message, token := kademlia.NewMessage()
	message.MessageType = "REQUEST_ROOM"
	message.SourceID = c.Network.Node.ID
	message.Message = ID

	kademlia.SendMsg(c.Network.Connection, remote.Address, message)

	// register things with the token so the reply knows wtf is going on
	c.Network.AwaitingResponse[token] = time.Now()
	c.Network.ExtraInfo[token] = ID
}