@ dave_thompson_085 Спасибо. Я сделал эту ошибку (смешивая нулевой язык программирования с нулевым ASN.1) несколько слишком много раз.

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

byte[] encoded_public_key=publick_key.getEncoded();

И сервер имеет этот код для получения ключа:

EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encoded_public_key);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey puKey = keyFactory.generatePublic(publicKeySpec);

Теперь я посмотрел API для getEncoded и он говорит, что он возвращает DER-кодированную форму ключа в виде байтового массива (http://www.docjar.com/docs/api/sun/s...tml #getEncoded)

Моя реализация для этого в JavaME была такой:

RSAPublicKeyStructure public_key_JAVAME=new RSAPublicKeyStructure(modulus,exponent);
byte[] DER_encoded_public_key_JAVAME=public_key_JAVAME.getDEREncoded();

//the getEncoded functions returns exact the same byte array.

Тем не менее, когда я пытаюсь получить ключ, закодированный с помощью JavaME, с помощью кода сервера, другими словами, когда я пытаюсь это сделать:

EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(DER_encoded_public_key_JAVAME);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey puKey = keyFactory.generatePublic(publicKeySpec);

я получил

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)
at java.security.KeyFactory.generatePublic(KeyFactory.java:304)

Caused by: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
at sun.security.x509.X509Key.decode(X509Key.java:380)
at sun.security.x509.X509Key.decode(X509Key.java:386)
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:66)
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:281)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:184)

Интересный момент: ключ в кодировке DER из обычной Java (с использованием функции getencoded ()) - это байтовый массив длиной 162 байта, в то время как ключ SAME, закодированный в JavaME с использованием надувного замка, имеет длину 140 байтов. Разве эти ключи с 2 DER не должны иметь одинаковую длину? Я имею в виду, что это тот же ключ в формате с кодировкой DER, поэтому они должны быть одинаковыми.

Что я делаю неправильно?

Правда, я этого не заметил. Проблема в том, знаете ли вы, как создать объект subjectPublickeyInfo из PublicKey в bouncyCastle? Я пробовал:

ByteArrayInputStream bIn = new ByteArrayInputStream(RSApublickey.toString().getbytes()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(bIn).readObject());

Но это не сработало. Я также попробовал:

ByteArrayInputStream(RSApublicKeyStructure.getEncoded()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(bIn).readObject());

На самом деле я ожидал, что это не сработает, но я должен был попробовать. Итак, как я могу создать Subjectpublickeyinfo из RSAkeyparameters? (Это одна из точек, где на самом деле сияет незаметность API замкового надувного замка)

Еще раз спасибо за ваш ответ, вы мне очень помогли. Вы поставили меня на правильный путь.

Ответы на вопрос(1)

Решение Вопроса

что ключ закодирован с помощью DER, равносильно тому, что он закодирован с использованием XML: необходимо согласоватькак он кодируется в DER / XML, чтобы иметь возможность его декодировать.

В этом случае вашRSAPublicKeyStructure.getEncoded() возвращает ключ в качестве DER-кодировки ASN.1RSAPublicKey:

RSAPublicKey ::= SEQUENCE {
  modulus INTEGER, -- n
  publicExponent INTEGER -- e 
}

X509EncodedKeySpec с другой стороны, ожидается, что будет передано DER-кодирование ASN.1PublicKeyInfo:

PublicKeyInfo ::= SEQUENCE {
  algorithm AlgorithmIdentifier,
  PublicKey BIT STRING
}

Чтобы создатьPublicKeyInfo с помощью BouncyCastle сделать это (любезноGregs):

RSAPublicKeyStructure rsaPublicKey = /* ... */
AlgorithmIdentifier rsaEncryption = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); 
SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(rsaEncryption, rsaPublicKey);
byte[] encodedPublicKeyInfo = publicKeyInfo.getEncoded();
 tdgs20 янв. 2011 г., 01:25
Я не знаю, правильно ли я поступил, не отвечая на комментарии, но мой ответ был слишком трудным для чтения, как комментарий из-за примера кода
 dave_thompson_08530 дек. 2018 г., 08:13
В соответствии с rfc3279 # 2.3.1, AlgorithmIdentifier для RSA должен иметь параметры, установленные для явного NULL ASN.1, не опущенного как Javanull делает - используетDERNull.INSTANCE вместо
 Nikita Rybak20 янв. 2011 г., 01:57
@ user581979 Вы можете обновить свой вопрос вместо. Видя, что в качестве ответа, вероятно, запутать людей.
 Rasmus Faber01 янв. 2019 г., 13:40
@ dave_thompson_085 Спасибо. Я сделал эту ошибку (смешивая нулевой язык программирования с нулевым ASN.1) несколько слишком много раз.

Ваш ответ на вопрос