Здесь очень мало различий. Формат ключа, который Java называет X.509, более точно известный как структура ASN.1 SubjectPublicKeyInfo
(или SPKI), определенный в X.509 или эквивалентно и более удобный в RFC5280 сек. 4.1 , это довольно простой способ обработки большого и гибкого набора алгоритмов: он состоит из подструктуры AlgorithmIdentifier
, которая идентифицирует алгоритм и его параметры, если это применимо, затем непрозрачной строки BIT, которая содержитфактическая ключевая информация (закодированная) в формате, зависящем от (алгоритма, идентифицированного) AlgorithmIdentifier.
Для RSA зависимая от алгоритма часть представляет собой структуру ASN.1 RSAPublicKey
, определенную в PKCS1 или более удобно RFC8017, приложение A.1.1 и его более ранние версиии дублируется в RFC3279 сек. 2.3.1 .Таким образом, для RSA формат X.509 (SPKI) содержит формат PKCS1, и поскольку RSA не имеет параметров (или, по крайней мере, связанных с ключом параметров), единственное реальное отличие состоит в том, что X.509Формат явно указывает, что ключом является RSA - который в вашем приложении вы уже знаете.
Вы уже обнаружили, что ванильная (Oracle-was-Sun-now-OpenJDK) Java-криптография, также известная как JCA Java Cryptographic Architecture,напрямую поддерживает только формат X.509 (SPKI), что является небольшим преимуществом.Однако, если вы используете BouncyCastle, гораздо проще конвертировать туда и обратно, чем код в вашем Q;вы просто используете класс org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
, чтобы добавить или отбросить AlgorithmIdentifier:
// test data source
KeyStore ks = KeyStore.getInstance("JKS"); ks.load (new FileInputStream (args[0]), args[1].toCharArray());
byte[] spkienc = ks.getCertificate(args[2]).getPublicKey().getEncoded();
System.out.println (DatatypeConverter.printHexBinary(spkienc));
// extract PKCS1 part of original SPKI
byte[] pkcs1enc = SubjectPublicKeyInfo.getInstance(spkienc).parsePublicKey().getEncoded();
System.out.println (DatatypeConverter.printHexBinary(pkcs1enc));
// rebuild SPKI from the PKCS1
AlgorithmIdentifier algid = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
byte[] spki2enc = new SubjectPublicKeyInfo (algid, pkcs1enc).getEncoded();
System.out.println (DatatypeConverter.printHexBinary(spki2enc));
См. мой ответ на аналогичный golang x509.MarshalPKIXPublicKey против x509.MarshalPKCS1PublicKey () и особенно ссылкив:
Преобразование открытого ключа в формате SubjectPublicKeyInfo в формат RSAPublicKey java
Генерация ключей RSA в формате PKCS # 1 в Java
Проблема передачиОткрытый ключ RSA, javaME, надувной замок
Если у вас нет BouncyCastle, это немного сложнее;вам нужно написать частичный парсер или генератор ASN.1.Полная обработка ASN.1 довольно сложна, но для этого случая вам нужно только небольшое подмножество, которое не так уж плохо.(Да, это слабая похвала.) Я могу добавить это позже, если у меня будет больше времени.
Гораздо большая потенциальная проблема заключается в том, что ваш ключ не аутентифицирован. Сложная часть распространения открытого ключа, намного сложнее, чем мелкие детали формата, гарантирует, что только законный ключ распространяется.Если злоумышленник может заменить свой открытый ключ на правильный, то жертва шифрует предположительно секретные данные так, чтобы злоумышленник мог легко их прочитать, и весь ваш модный криптографический код совершенно бесполезен.
Вот почему наиболее актуальносистемы не распространяют открытые публичные ключи, но вместо этого сертификаты, которые позволяют проверять ключ, являются правильным ключом.Существует несколько схем сертификатов, но наиболее распространенной на сегодняшний день является X.509 и его интернет-профиль PKIX - фактически RFC, на которые я ссылался выше, 5280 и 3279, являются частью PKIX.SSL-now-TLS использует X.509.Подписание кода использует X.509.S / MIME электронная почта использует X.509.(PGP / GPG использует другой вид сертификатов, не X.509, но все еще сертификаты.) И (ванильное) Java напрямую поддерживает сертификаты X.509 так же хорошо или даже лучше, чем публичные клавиши «X.509» (SPKI).