Что вы хотите сделать, это использовать SSL с взаимной аутентификацией, чтобы ваш сервер принимал только входящие соединения из вашего приложения, и ваше приложение будет связываться только с вашим сервером.
Вот высокоуровневый подход. Создайте сертификат SSL с самозаверяющим сервером и разверните его на своем веб-сервере. Вы можете использовать keytool, входящий в Android SDK (если вы используете Android, для этого есть другие инструменты для других платформ). Затем создайте самозаверяющий клиент и разверните его в своем приложении в настраиваемом хранилище ключей, включенном в ваше приложение, в качестве ресурса (keytool также генерирует это приложение). Настройте сервер, требующий аутентификации на стороне клиента, и только принять сертификат клиента, который вы создали. Настройте клиента для использования этого сертификата на стороне клиента для идентификации себя и принимайте только тот серверный сертификат, который вы установили на своем сервере для этой части.
Если кто-то, кроме вашего приложения, пытается подключиться к вашему серверу, соединение SSL не будет создано, так как сервер отклонит входящие SSL-соединения, которые не представляют сертификат клиента, который вы включили в ваше приложение.
Шаг за шагом для этого является гораздо более длинным ответом, чем это оправдано здесь. Я бы предложил сделать это поэтапно, так как в Интернете есть ресурсы о том, как работать с самоподписанным сертификатом SSL на Android, как на стороне сервера, так и на стороне клиента. В моей книге также есть полный проход для приложений Android, Application Security for the Android Platform, опубликованный O'Reilly.
Теперь ... вы правы в том, что кто-то с доступом к мобильному приложению может восстановить закрытый ключ, связанный с сертификатом на стороне клиента. Это было бы в хранилище ключей BKS, которое было бы зашифровано, но ваше приложение должно было бы предоставить пароль для открытия этого хранилища ключей. Таким образом, кто-то может перепроектировать ваше приложение (довольно простое на платформе Android), захватить пароль, захватить хранилище ключей и расшифровать его, чтобы восстановить закрытый клиентский ключ. Вы можете смягчить это, запутав приложение, чтобы затруднить изменение пароля хранилища ключей или попросить пользователя войти в приложение и использовать этот пароль для получения пароля хранилища ключей и т. Д. ... это действительно зависит от уровня риска, который вы готовы принять для своей заявки.