Проблемы в коде:
String encrypted = new String(encryptedBytes);
Плохая идея! Cipher#doFinal
возвращает byte[]
по уважительной причине. Это похоже на случайные данные - превращение этого в String наверняка приведет к путанице, потому что кодировка платформы по умолчанию (UTF-8 в большинстве случаев) будет интерпретировать случайные байты неправильно почти наверняка. Так что если вы хотите получить строку из зашифрованных данных, то вам нужно кодировать Base64- или Hex-код байтового массива.
Из того, что вы сказали, что ожидали, я бы сказал, что вам нужны данные в кодировке Base64, поэтому вы должны кодировать Base64 вывод вашего шифра.
Тогда шифрование строки (это настоящий, читаемый человеком текст?) Также не оптимально. Сильно уязвимый, уменьшенная энтропия плюс характеристики режима ECB (это используется шифром RSA) резко снижают безопасность вашего решения.
Простой шифр RSA никогда не должен использоваться для шифрования данных, размер которых превышает один блок (то есть больше, чем размер ключа вашего ключа RSA), а также только в том случае, если данные криптографически защищены случайным образом. В 99% всех случаев это дается только для симметричных ключей, используемых для симметричных шифров, таких как AES и т. Д.
Используйте RSA только для шифрования симметричных ключей и цифровых подписей. Во всех остальных случаях, когда вы хотите фактически зашифровать конфиденциальные данные, вы используете симметричный шифр, AES - хороший выбор - 128 или 256 бит не имеет большого значения .
Рабочий процесс будет выглядеть так:
Создание симметричного ключа для AES (16/32 байта, если вы используете AES-128/256). Теперь вы будете RSA-шифровать этот симметричный ключ и ничего более, используя открытый ключ сервера и отправлять ключ на сервер, а затем шифровать ваши личные данные с использованием AES и симметричного ключа, сервер расшифрует симметричный ключ используя его личный ключ RSA и расшифровывайте отправленные на него пакеты.
Использовать TLS:
Обратите внимание, что я использовал . Вышесказанное - только часть истории. То, что вы только что изобрели, - это ключевой транспортный протокол. И если вы не спроектируете их для живого, высоки шансы, что вы не получите такой защиты с первой попытки (как в атаках «Человек посередине», «Атаки на отражение», «Атаки воспроизведения» ...).
Вот почему, на мой взгляд, широко распространенная защищенная опция only для установки безопасного канала между клиентским устройством и сервером заключается в использовании TLS (прежний SSL). Протокол был разработан специально для обмена частными данными с односторонней (только для сервера) или двухсторонней аутентификацией (клиент и сервер) (аутентификация - это та часть, для которой вы будете использовать RSA в вашем случае - настройка «сертификата сервера» «).
Он годами укреплялся и несколько раз пересматривался, чтобы противостоять всем известным атакам на такие протоколы. И я знаю, что каждый день появляются сообщения о том, как «SSL» был нарушен тем или иным человеком, но, тем не менее, если вы настроите его осторожно, он будет настолько же безопасным, насколько это возможно для простых смертных, не имеющих большого опыта в разработке протоколов.
И приятно то, что вам нужно только настроить его на сервере (что довольно легко по сравнению с созданием протокола с нуля), чтобы иметь возможность использовать полностью зашифрованную и безопасную связь между клиентом и сервером. Если вы настроили пару сертификат / ключ на сервере, который был куплен у «общедоступного ЦС», то использование TSL полностью прозрачно для ваших клиентов - они просто меняют свой URL-адрес доступа с «http» на «https» - сертификат сервера будет быть автоматически доверенным, имея возможность идентифицировать его в пути сертификата, который ведет к одному из корневых сертификатов, хранящихся в хранилище доверия Java по умолчанию cacerts
.