Подтвердить что ты не робот

Шифрование RSA с данным открытым ключом (на Java)

Я ищу образец Java, как сделать RSA-шифрование с данным открытым ключом (у меня это в формате base64, кажется, длина 1024 бит).

Ниже мой код, но у меня есть исключение InvalidKeySpec.

String publicKey = "AJOnAeTfeU4K+do5QdBM2BQUhfrRI2rYf/Gk4a3jZJB2ewekgq2VgLNislBdql/glA39w0NjXZyTg0mW917JdUlHqKoQ9765pJc4aTjvX+3IxdFhteyO2jE3vKX1GgA3i3n6+sMBAJiT3ax57i68mbT+KAeP1AX9199aj2W4JZeP";
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] res = new Base64Encoder().decode(publicKey.getBytes());
X509EncodedKeySpec KeySpec = new X509EncodedKeySpec(res);
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec);

// here the exception occurs..

Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(input.getBytes());
return cipherData;

Пожалуйста, дайте мне образец,

4b9b3361

Ответ 1

Вот как мне удается шифровать строку только с открытым ключом RSA.

Сначала сохраните открытый ключ в PEM-формате для имени файла pubkey.pem

-----BEGIN PUBLIC KEY-----
AJOnAeTfeU4K+do5QdBM2BQUhfrRI2rYf/Gk4...
-----END PUBLIC KEY-----

Найти открытый модуль ключа RSA

$ openssl rsa -pubin -in pubkey.pem -modulus -noout
Modulus=F56D...

Найти общедоступный ключ RSA Exponent

$ openssl rsa -pubin -in pubkey.pem -text -noout
...
Exponent: 65537 (0x10001)

Затем вставьте их в следующий код.

BigInteger modulus = new BigInteger("F56D...", 16);
BigInteger pubExp = new BigInteger("010001", 16);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, pubExp);
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec);

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] cipherData = cipher.doFinal(text.getBytes());

Ответ 2

Ваш "ключ" не является действительным открытым ключом. Это строка Base64, которая при декодировании дает последовательность из 129 байтов, первая из которых равна 0x00, а затем 0x93. Это недействительный формат для открытого ключа RSA, но он подозрительно похож на кодировку с кодировкой 1024-битного кодирования в формате big-endian (то есть тип кодировки, возвращаемый BigInteger.toByteArray() и используемый в значениях ASN.1 "INTEGER" ). Открытый ключ RSA номинально состоит из двух целых чисел, один из которых является модулем, а другой - публичным показателем. Типичный модуль RSA имеет длину 1024 бит, поэтому есть вероятность, что у вас есть модуль. Чтобы заполнить ключ, вам все еще нужен публичный экспонент.

X509EncodedKeySpec ожидает кодирование DER структуры ASN.1, которая идентифицирует алгоритм как RSA, и содержит вложенную кодированную структуру, которая сама содержит два целых числа для открытого ключа RSA. Сборка такой структуры вручную может оказаться трудной (она выполнима, но требует некоторого глубокого понимания ASN.1). Более простым методом было бы использовать RSAPublicKeySpec:

String modulusBase64 = "..."; // your Base64 string here
BigInteger modulus = new BigInteger(1,
        new Base64Encoder.decode(modulusBase64.getBytes("UTF-8")));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec ks = new RSAPublicKeySpec(modulus, pubExp);
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec);

В приведенном выше "pubExp" должен быть BigInteger, содержащий публичный показатель, который вы не даете. 3 и 65537 являются традиционными значениями для публичного экспонента, но возможны другие, и вы не даете достаточно информации для дискриминации между публичными экспонентами (т.е. Ваш код будет работать, даже если вы не используете правильный). В принципе, у вас есть только половина открытого ключа; вы должны спросить, кто вам дал эту половину, чтобы отправить вам другую половину.

Примечание. String.getBytes() использует стандартную кодировку платформы, которая не всегда одинакова. Если вы настаиваете на преобразовании строки в последовательность байтов, вы должны использовать явное имя charset, например "UTF-8", иначе вы можете столкнуться с проблемами, если ваш код когда-либо работает, скажем, в русской или китайской системе. Кроме того, я не знаю, откуда взялся ваш класс Base64Encoder (он не является частью стандартного Java API), но есть вероятность, что он также может работать непосредственно над String или StringReader, делая шаг преобразования нет необходимости.

Ответ 3

Является ли ваш открытый ключ действительно закодированным X509? Если нет, то должен помочь некодированный Keyspec.

Ответ 4

Ваш открытый ключ не похож на значение 1024 бит в кодировке Base64. Для значения в 1024 бит потребуется 172 символа (последний является наполнителем =), и здесь у нас есть 175 символов.

Для теста замените последние четыре символа в вашей Строке на один = и проверьте, исключает ли это исключение. Это не решит проблему, но может указывать в правильном направлении.