RSA - Java KeyFactory завершается ошибкой, когда PEM-анализатор bouncycastle успешно работает - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть открытый ключ в формате PEM (полученный от устройства iOS):

String pemPubKey = ""+
"-----BEGIN RSA PUBLIC KEY-----\n"+
"MIIBCgKCAQEA07ACQHTTrgX7ddNtyamh58xwD+S+pSrJz/Rah4zj0HIg4V/Ok5vk\n"+
"Wx6y4UyuKLCtefeiB2ipg/n1ZZ0eRac1B4UwPhAtILGQzgIUgOp0cQ3Cb94ugq92\n"+
"wxkxeEdWmIFIlXgWOf6I8yWp9DZaigrRhA2kPbY01zKxCsX1ZxKMVu2sU/HM1hJy\n"+
"aebLLND002yLzuRDLXbacmCt5U6vDQDjBmm3uZ26fEMF+GTCnn6fJBq5RDfRKjpS\n"+
"fVM0mCePO9RHiwu3oHfqoyLA2QGlCexXcIYq7KbJjC9vcamAWRqQdHlsSj5ezDTR\n"+
"GofA6HtQ+zNdGHOvqsYtbN8MJSlUXXy39wIDAQAB\n"+
"-----END RSA PUBLIC KEY-----";

Если я попытаюсь разобрать его в PublicKey, используя KeyFactory следующим образом:

KeyFactory kf = KeyFactory.getInstance("RSA");
Pattern parse = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*");
String encoded = parse.matcher(pemPubKey).replaceFirst("$1");
byte[] pem = Base64.getMimeDecoder().decode(encoded);
PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(pem));

Я получаю: java.security.InvalidKeyException: IOException: algid parse error, not a sequence.

Но когда я использую bouncycastle вот так:

SubjectPublicKeyInfo subjectPublicKeyInfo =
    (SubjectPublicKeyInfo) new PEMParser(new StringReader(pemPubKey)).readObject();

PublicKey pubKey;

if (PKCSObjectIdentifiers.rsaEncryption == subjectPublicKeyInfo.getAlgorithm().getAlgorithm()) {
    DLSequence der = (DLSequence) subjectPublicKeyInfo.parsePublicKey().toASN1Primitive();
    ASN1Object modulus, exponent;
    modulus = (ASN1Object) der.getObjectAt(0);
    exponent = (ASN1Object) der.getObjectAt(1);
    RSAPublicKeySpec spec =
            new RSAPublicKeySpec(new BigInteger(modulus.toString()), new BigInteger(exponent.toString()));
    KeyFactory factory = KeyFactory.getInstance("RSA");
    pubKey = factory.generatePublic(spec);
} else {
    // Throw some exception
}

Я получил действительный PublicKey, и алгоритм идентифицирован правильно.

Почему здесь не работает парсер java? И правильно ли я делаю миграцию с SubjectPublicKeyInfo на PublicKey?

Обновление

Я пытался проверить ключ, используя openssl:

$ openssl rsa -inform PEM -pubin -in pub.pem -text -noout невозможно загрузить открытый ключ 140735659656136: ошибка: 0906D06C: процедуры PEM: PEM_read_bio: нет запуска линия: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pem/pem_lib.c: 704: Ожидать: ПУБЛИЧНЫЙ КЛЮЧ

И после удаления RSA из верхнего / нижнего колонтитула:

$ openssl rsa -inform PEM -pubin -in pub.pem -text -noout невозможно загрузить открытый ключ 140735659656136: ошибка: 0D0680A8: кодировка asn1 Подпрограммы: ASN1_CHECK_TLEN: неправильно тег: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c: 1164: 140735659656136: ошибка: 0D07803A: кодировка asn1 подпрограммы: ASN1_ITEM_EX_D2I: вложенный asn1 Ошибка: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c: 314: Тип = X509_ALGOR 140735659656136: ошибка: 0D08303A: кодировка asn1 подпрограммы: ASN1_TEMPLATE_NOEXP_D2I: вложенный asn1 Ошибка: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c: 653: Поле = Algor, Тип = X509_PUBKEY 140735659656136: ошибка: 0906700D: PEM Подпрограммы: PEM_ASN1_read_bio: ASN1 Lib: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pem/pem_oth.c: 84:

1 Ответ

0 голосов
/ 15 ноября 2018

Синтаксический анализатор Java не вышел из строя, ваш открытый ключ не является экземпляром закодированной структуры SubjectPublicKeyInfo, которую ожидает Java X509EncodedKeySpec.Я не изучал подпрограммы Bouncycastle, чтобы понять, почему это удалось, но PEMParser предназначен для анализа многих различных типов так называемых файлов "PEM".

SubjectPublicKeyInfo определен в RFC 5280 as:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
     algorithm            AlgorithmIdentifier,
     subjectPublicKey     BIT STRING
}

Ваш открытый ключ представляет собой простой PKAP # 1 RSAPublicKey, определенный в RFC 8017 как:

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

И только последнее словоо файлах "PEM".Вы должны быть осторожны при описании чего-либо как формата "PEM", потому что PEM на самом деле не является конкретным форматом.«PEM» - это чуть больше, чем кодирование истинного формата в base64, а затем завершение base64 в строки «----- BEGIN -----» и «----- END -----», где надеюсь однозначно описывает, что представляют собой данные в кодировке base64.

...