Каковы основные различия между RSAPublicKey и PublicKey в Java? Также я задаю тот же вопрос для RSAPrivateKey и PrivateKey.

2
user5673373 27 Май 2017 в 18:33

2 ответа

Лучший ответ

PublicKey / PrivateKey являются ключами для некоторого алгоритма, использующего пару ключей, без указания того, что это за алгоритм.

Их аналоги, связанные с RSA, являются их специализациями для алгоритма RSA. Например, в RSAPublicKey отсутствует метод getPublicExponent() в PublicKey.

На практике вы можете использовать это правило: если вы уверены, что будете использовать только RSA, используйте RSAPublicKey / RSAPrivateKey; в противном случае используйте PublicKey / PrivateKey.

2
Maarten Bodewes 27 Май 2017 в 17:41

Экземпляры таких классов, как Cipher и Signature, обычно принимают любой PublicKey или PrivateKey экземпляр для своих методов инициализации во время компиляции. Однако тип ключа должен соответствовать реализованному алгоритму. Это проверяется во время выполнения, что приводит к {{X4 }} если ключ и алгоритм не совпадают.

Это позволяет более легко переключаться между алгоритмами, даже если это необходимо, даже во время выполнения. Таким образом, большая часть кода может быть реализована независимо от используемого алгоритма, по крайней мере до тех пор, пока не потребуются специфические для типа ключа операции.


Обратите внимание, что RSAPublicKey расширяет PublicKey и что оба являются интерфейсами Java. В общем, вы сами должны использовать RSAPublicKey, только если вам требуются дополнительные методы, предлагаемые интерфейсом. Это не должно часто иметь место; для криптографических операций обычно достаточно PublicKey.

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


Фабричные классы KeyFactory и KeyPairGenerator просто выводят PublicKey или PrivateKey, последний косвенно, путем вывода универсального экземпляра KeyPair. Если вам нужны дополнительные методы, вам необходимо привести открытый ключ к открытому ключу RSA:

RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;

Однако если вы не уверены, какой тип ключа вы получите, вам сначала нужно проверить, что тип правильный, используя instanceof:

if (publicKey instanceof RSAPublicKey) {
    RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
}

Или вы должны быть готовы поймать ClassCastException, который может последовать.


Криптографические провайдеры , реализованные в соответствии с архитектурой криптографии Java, обеспечивают фактическую реализацию этих интерфейсов.

Это объясняет другое использование этих интерфейсов: до тех пор, пока базовый криптографический материал, такой как модуль и показатель степени, может быть извлечен, можно возможно создать ключ или пару ключей с использованием одного поставщика и использовать его в другом. поставщик . Это было бы невозможно, если бы интерфейс для извлечения модуля и показателя не был стандартизирован.

Поставщики аппаратного обеспечения (смарт-карты, HSM) обычно выдают исключение, когда вы пытаетесь получить частную экспоненту или другой материал закрытого ключа. Это потому, что ключ обычно не покидает аппаратное устройство; Вы можете выполнять операции RSA только на самом устройстве, используя назначенного поставщика.

Невозможно использовать эти ключи в других реализациях Cipher. Поэтому в Java содержится «отложенный выбор провайдера», чтобы убедиться, что выбран правильный провайдер, если он не был явно указан при создании экземпляра, например, Cipher.getInstance(String algorithm). Вместо этого провайдер выбирается во время инициализации.


RSAPrivateCrtKey - это интерфейс, который снова расширяет RSAPrivateKey. Этот класс содержит доступ к параметрам, необходимым для более быстрых вычислений, использующих теорему об остатках в Китае (CRT). Как правило, вам не нужно получать доступ к этим параметрам.

4
Maarten Bodewes 27 Май 2017 в 18:50