Проблема заключается в том, что закрытый ключ не является PKCS8EncodedKeySpec, а является объектом RSAPrivateKey из PKCS # 1.Однако поставщик BC все равно будет декодировать эту ошибку без жалоб.Тем не менее, другие поставщики будут справедливо жаловаться.Я предполагаю, что среда выполнения использует более старую версию Android, где поставщиком по умолчанию является BC, но ваш тест использует более новую версию, где это не так.
Исправление состоит в том, чтобы сделать ваш закрытый ключправильный PKCS8EncodedKeySpec.Кроме того, вы можете явно запросить поставщика «BC».Для этого вам нужно указать «BC» в вызове getInstance (): val keyFactory = KeyFactory.getInstance("RSA", "BC")
Однако обратите внимание, что, похоже, поддержка поставщика BC уже вышла .
Чтобы преобразовать закрытый ключ в формат PKCS # 1, либо оберните верхний и нижний колонтитулы в стиле 'BEGIN RSA PRIVATE KEY' и нижний колонтитул base64, либо декодируйте двоичный объект base64 и поместите его в файл, а затем выполните:
openssl pkcs8 -topk8 -in privkey.pem -outform der -nocrypt | openssl base64 -A
или
openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt | openssl base64 -A
Вторая проблема связана с использованием значений по умолчанию.Вместо того, чтобы делать
val c = Cipher.getInstance("RSA")
, который получает значения по умолчанию для режима и заполнения и, следовательно, является непереносимым, всегда указывайте полную строку преобразования " алгоритм / режим / заполнение " в Cipher.getInstance()
,В вашем случае кажется, что данные не дополняются (небезопасный режим), вам нужно что-то вроде
val c = Cipher.getInstance("RSA/ECB/NoPadding")
Однако вам действительно следует использовать правильное рандомизированное заполнение, и в настоящее время это заполнение OAEP.
Резюме
Среда выполнения - это Android, но я думаю, что среда тестирования - это Oracle Java (или, может быть, openjdk).Очевидно, в этих средах есть два критических различия:
- Android использует поставщик BC для KeyFactory, который будет обрабатывать закрытые ключи, закодированные в формате PKCS # 1 RSAPrivateKey.Oracle Java поддерживает только ключи, закодированные в PKCS8.
- В Android
Cipher.getInstance("RSA")
по умолчанию Cipher.getInstance("RSA/ECB/NoPadding")
, но Oracle Java по умолчанию Cipher.getInstance("RSA/ECB/PKCS1Padding")