Проблема передачи открытого ключа RSA, javaME, надувной замок - PullRequest
3 голосов
/ 19 января 2011

Я работаю над переносом экземпляра приложения обмена сообщениями с 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.

Однако, когда я пытаюсь получить ключ, закодированный в DER с помощью 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 Ответ

10 голосов
/ 19 января 2011

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

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

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

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

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();
...