title: RSA - Java's KeyFactory fails where bouncycastle's PEM parser succeeds
body: <p>I have a PEM formatted public key (received from an iOS device):</p>
  
  <pre><code>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-----";
  </code></pre>
  
  <p>If I try to parse it into a <code>PublicKey</code> using KeyFactory like that:</p>
  
  <pre><code>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));
  </code></pre>
  
  <p>I get: <code>java.security.InvalidKeyException: IOException: algid parse error, not a sequence</code>.</p>
  
  <p>But when I use <code>bouncycastle</code> like that:</p>
  
  <pre><code>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
  }
  </code></pre>
  
  <p>I get a valid <code>PublicKey</code> and the algorithm is identified correctly.</p>
  
  <p>Why does java's parser fails here? And am I doing the migration from <code>SubjectPublicKeyInfo</code> to <code>PublicKey</code> correctly?</p>
  
  <p><strong>Update</strong>:</p>
  
  <p>I've tried to verify the key using <code>openssl</code>:</p>
  
  <blockquote>
    <p>$ openssl rsa -inform PEM -pubin -in pub.pem -text -noout
    unable to load Public Key
    140735659656136:error:0906D06C:PEM routines:PEM_read_bio:no start
    line:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pem/pem_lib.c:704:Expecting:
    PUBLIC KEY</p>
  </blockquote>
  
  <p>And after removing <code>RSA</code> from the header / footer:</p>
  
  <blockquote>
    <p>$ openssl rsa -inform PEM -pubin -in pub.pem -text -noout unable to
    load Public Key 140735659656136:error:0D0680A8:asn1 encoding
    routines:ASN1_CHECK_TLEN:wrong
    tag:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c:1164:
    140735659656136:error:0D07803A:asn1 encoding
    routines:ASN1_ITEM_EX_D2I:nested asn1
    error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c:314:Type=X509_ALGOR
    140735659656136:error:0D08303A:asn1 encoding
    routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1
    error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/asn1/tasn_dec.c:653:Field=algor,
    Type=X509_PUBKEY 140735659656136:error:0906700D:PEM
    routines: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:</p>
  </blockquote>