Несоответствие между реализациями RSA

Я не крипто-парень, поэтому знаю об этих вещах почти с нуля. Я должен взаимодействовать с системой, использующей криптографию RSA. При использовании их ключей я сталкиваюсь с проблемой получения разных шифров для одного и того же ввода / ключа. Библиотека https://code.google.com/p/pajhome/source/browse/trunk/crypt/md5/rsa/RSA.js?r=133 и я использую Java BouncyCastle RSA Provider следующим образом:

BigInteger e = new BigInteger("9d7aa162117a8a9610ed2ddea713d7b", 16);
BigInteger m = new BigInteger("c9869917572adbb60a2c30ddec2551f", 16);

RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
KeyFactory keyFac = KeyFactory.getInstance("RSA", "BC");
PublicKey pubKey = keyFac.generatePublic(spec);

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);

// UNENCRYPTED_LOGIN = "201211130215"
// UNECRYPTED_TYPE = "1"

byte[] login = cipher.doFinal(UNENCRYPTED_LOGIN.getBytes("ASCII"));
byte[] type = cipher.doFinal(UNENCRYPTED_TYPE.getBytes("ASCII"));

// login = 00d571a40ef7359b2e9e10b7c5dd621c
// should be 02f0cc389fb88e6b4aaa4e2477858ca9

// type = 0a5c2e176c81b23b2e1dd635f2427c0f
// it is correct

1 ответ

Решение

Проблема заключается в способе упаковки от строк 52 до 65 в источнике JS, с которым вы связаны. Это работает для 1-символьных строк, но будет иметь проблемы при выполнении больших строк.

Чтобы проиллюстрировать проблему, рассмотрим, что происходит со строкой длиной 1. Код JS создает массив и помещает значение ascii символа в массив. Затем дополняет массив нулями. Алгоритм упаковки создает новый массив, упаковывая 2 элемента массива в одно значение в новом массиве. Это делает что-то вроде этого:

for i=0, i<len(old_array), i+=2:
  new_array[i] = old_array[i] + (old_array[i+1] << 8)

Для входной строки длиной 1 (скажем, это "1"), вы должны иметь old_array=[0x31, 0x00,...] (еще несколько с нулевым заполнением). Итак, new_array=[0x31 + (0x00 << 8 == 0x00) = 0x0031, ...] (больше заполнения нулями). Обратите внимание, что old_array == new_array (в некоторой степени new_array на самом деле короче, но в любом случае это все нули, поэтому значение при преобразовании в большое целое число одинаково).

С входной строкой длиной 2 (скажем, "12") вы бы имели old_array=[0x31, 0x32, 0x00, ...] (больше отступов). Итак, new_array=[0x31 + (0x32 << 8 == 0x3200) = 0x3231, 0x0000]. Обратите внимание, что это не то же самое, что old_array.

Поэтому, чтобы решить вашу проблему, вам необходимо реализовать упаковку. Затем зашифруйте упакованный массив.

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

Другие вопросы по тегам