Example #1
0
func DecryptAuth(in []byte, ratch *ratchet.Ratchet) (*ratchet.Ratchet, []byte, error) {
	msg, err := ratch.Decrypt(in)
	if err != nil {
		return nil, nil, err
	}
	unpadMsg := proto.Unpad(msg)
	return ratch, unpadMsg, nil
}
Example #2
0
func receiveProtobuf(conn *transport.Conn, inBuf []byte, t *testing.T) *proto.ServerToClient {
	response := new(proto.ServerToClient)
	conn.SetDeadline(time.Now().Add(time.Second))
	num, err := conn.ReadFrame(inBuf)
	handleError(err, t)
	unpadMsg := proto.Unpad(inBuf[:num])
	if err := response.Unmarshal(unpadMsg); err != nil {
		t.Error(err)
	}
	if response.Status == nil {
		t.Error("Server returned nil status.")
	}
	if *response.Status == proto.ServerToClient_PARSE_ERROR {
		t.Error("Server threw a parse error.")
	}
	return response
}
Example #3
0
func ReceiveProtobuf(conn *transport.Conn, inBuf []byte) (*proto.ServerToClient, error) {
	response := new(proto.ServerToClient)
	conn.SetDeadline(time.Now().Add(time.Hour))
	num, err := conn.ReadFrame(inBuf)
	if err != nil {
		return nil, err
	}
	unpadMsg := proto.Unpad(inBuf[:num])
	if err := response.Unmarshal(unpadMsg); err != nil {
		return nil, err
	}
	if response.Status == nil {
		return nil, errors.New("Server returned nil status.")
	}
	if *response.Status != proto.ServerToClient_OK {
		return nil, errors.New("Server did not return OK")
	}
	return response, nil
}
Example #4
0
// readClientCommands reads client commands from a connnection and sends them
// to channel commands. On error, the error is sent to channel disconnect and
// both channels (but not the connection are closed).
// commands is a TWO-WAY channel! the reader must reach return each cmd after
// interpreting it, readClientCommands will call cmd.Reset() and reuse it.
func (server *Server) readClientCommands(conn *transport.Conn,
	commands chan *proto.ClientToServer, disconnected chan error) {
	defer server.wg.Done()
	defer close(commands)
	defer close(disconnected)
	inBuf := make([]byte, proto.SERVER_MESSAGE_SIZE)
	cmd := new(proto.ClientToServer)
	for {
		num, err := conn.ReadFrame(inBuf)
		if err != nil {
			disconnected <- err
			return
		}
		unpadMsg := proto.Unpad(inBuf[:num])
		if err := cmd.Unmarshal(unpadMsg); err != nil {
			disconnected <- err
			return
		}
		commands <- cmd
		cmd = <-commands
		cmd.Reset()
	}
}
Example #5
0
func CheckAuthWith(prt ProfileRatchet) func([]byte, []byte, []byte, *[32]byte) error {
	return func(tag, data, msg []byte, ourAuthPrivate *[32]byte) error {
		var sharedAuthKey [32]byte
		message := new(proto.Message)
		unpadMsg := proto.Unpad(msg)
		err := message.Unmarshal(unpadMsg)
		if err != nil {
			return err
		}

		profile, err := prt(message.Dename, message.DenameLookup)
		if err != nil {
			return err
		}

		chatProfileBytes, err := client.GetProfileField(profile, PROFILE_FIELD_ID)
		if err != nil {
			return err
		}

		chatProfile := new(proto.Profile)
		if err := chatProfile.Unmarshal(chatProfileBytes); err != nil {
			return err
		}

		theirAuthPublic := (*[32]byte)(&chatProfile.MessageAuthKey)

		curve25519.ScalarMult(&sharedAuthKey, ourAuthPrivate, theirAuthPublic)
		h := hmac.New(sha256.New, sharedAuthKey[:])

		h.Write(data)
		if subtle.ConstantTimeCompare(tag, h.Sum(nil)[:len(tag)]) == 0 {
			return errors.New("Authentication failed: failed to reproduce envelope auth tag using the current auth pubkey from dename")
		}
		return nil
	}
}
Example #6
0
func DecryptAuthFirst(in []byte, pkList []*[32]byte, skList []*[32]byte, skAuth *[32]byte, prt ProfileRatchet) (*ratchet.Ratchet, []byte, int, error) {
	ratch := &ratchet.Ratchet{
		FillAuth:  FillAuthWith(skAuth),
		CheckAuth: CheckAuthWith(prt),
	}

	if len(in) < 32 {
		return nil, nil, -1, errors.New("Message length incorrect.")
	}
	var pkAuth [32]byte
	copy(pkAuth[:], in[:32])

	envelope := in[32:]
	for i, pk := range pkList {
		if *pk == pkAuth {
			msg, err := ratch.DecryptFirst(envelope, skList[i])
			if err == nil {
				unpadMsg := proto.Unpad(msg)
				return ratch, unpadMsg, i, nil
			}
		}
	}
	return nil, nil, -1, errors.New("Invalid first message received.") //TODO: Should I make the error message something different?
}