Проверка цифровой подписи, созданной C# на устройстве Android


Я пишу приложение для Android, которое хотело бы проверить, что строка, созданная программой C#, является подлинной (т. е. произведенной другим приложением, которое я написал). Для этого я подписываю строку и передаю строку и хэш строки на устройство Android. Я могу включить открытый ключ, используемый для создания хэшированной строки в приложении Android, чтобы мне не нужно было передавать ее. Код C#, который производит все это, сродни следующему:

bytes = ASCIIEncoding.ASCII.GetBytes(someString);
provider = new RSACryptoServiceProvider();

signature = provider.SignData(bytes, new SHA1CryptoServiceProvider());    

keyParameters = cryptoProvider.ExportParameters(false);

К передавая данные, я кодирую подпись как base64, используя:

SignatureString = Система.Преобразовать.ToBase64String (подпись);

Я вручную извлек модуль и открытый показатель степени из ключевых параметров. Похоже, что они оба уже закодированы в Base64. В приложении для android я пытаюсь проверить подпись следующим образом:

String modulus = "<modulus string here...>";
String exponent = "<exponent string here...>";

BigInteger BIModulus = new BigInteger(1, Base64.decode(modulus));
BigInteger BIExponent = new BigInteger(1, Base64.decode(exponent));

RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(BIModulus, BIExponent);
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);

byte[] decodedBytes = cipher.doFinal(Base64.decode(signature));

Когда я сравниваю decodedBytes с хэшем SHA1 исходной строки, они отличаются. Пытаясь понять, почему, я шагнул через дверь. процесс с уймой операторов регистрации. Похоже, что BigInteger для модуля отличается от модуля, используемого в коде C#. То же самое происходит и с экспонентой. Я подозреваю, что это потому, что тип байта Java не имеет знака?

Итак, два вопроса: 1) Что я делаю (или не делаю) неправильно? Есть ли способ вручную переместить модуль и показатель степени с одного устройства на другое для проверки подписи? 2) есть ли способ достичь того, к чему я стремлюсь? это работает на более подходящем уровне абстракции?
1   2   2011-04-18 20:34:22

1 ответ:

Вопрос #1:

Вы хотите проверить подпись, поэтому вы должны использовать не класс Cipher, А класс Signature.

PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initVerify(publicKey);
sign.update(someString.getBytes("ASCII"));
boolean ok = sign.verify(Base64.decode(signature));

Примечание: SHA1withRSA алгоритм использует RSA с SHA-1, как описано в стандарте PKCS#1. Я не специалист по .net и не знаю, использует ли RSACryptoServiceProvider.SignData(...) Этот стандарт.

Большую часть времени ключи подписи передаются с сертификатами , которые связывают открытый ключ (модуль + экспонента в случае RSA) с сущностью (владелец ключа, может будьте личностью, компьютером, компанией...)

Вопрос #2:

Определенно это зависит от вашего варианта использования: зачем вам нужна подпись (аутентификация, целостность)? что ты подписываешь?


Обновление:

Использование простой подписи RSA, насколько она используется с правильной схемой / протоколом (например, PKCS#1, реализованной везде, по крайней мере в версии 1.5), нормально. Другим решением является использование кода аутентификации сообщения (например, HMAC ) который обеспечивает аутентификацию и службу целостности и использует симметричные ключи.

Для хранения открытого ключа вы можете либо жестко закодировать ключ (или использовать самозаверяющий сертификат) в вашем приложении для проверки. Вы должны знать, что если закрытый ключ будет скомпрометирован, потерян или уничтожен, вам придется обновить все клиенты. Второе решение использует PKI , выдающий сертификат подписи; это решение поддерживает отзыв и обновление ключей, но имеет несколько недостатков: не так простота установки и обслуживания, может быть излишним в зависимости от ваших потребностей и окружающей среды.