Tech Racho エンジニアの「?」を「!」に。
  • 開発

JavaでRSAの公開鍵を読み込んだらInvalidKeySpecException: unknown object in factory: org.bouncycastle.asn1.DERInteger

AndroidでRSA鍵を扱おうと思い、以下のようなコードを書きました。

/**
* ファイルの中身を全部取得する
*/
public static byte[] readFile(String filename) {
    try {
        FileInputStream is = new FileInputStream(filename);
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();

        byte[] buf = new byte[256];
        int size = 0;

        while ((size = is.read(buf)) != -1) {
            bytes.write(buf, 0, size);
        }

        return bytes.toByteArray();
    } catch (Exception e) {
        //TODO
    }
    return null;
}

/**
* PEMの最初と最後の行を取り除き、データ部分だけ抜き出し、Base64デコードする
* 手抜き実装
* Base64はこちらを利用: http://iharder.net/base64
*/
public static byte[] decodePem(String pem) {
    String BORDER = "-----";
    try {
        if (pem.indexOf(BORDER) != -1) {
            int s1 = pem.indexOf(BORDER); // BEGINの左側
            int s2 = pem.indexOf(BORDER, s1 + 1); // BEGINの右側
            int s3 = pem.indexOf(BORDER, s2 + 1); // ENDの左側
            int s4 = pem.indexOf(BORDER, s3 + 1); // ENDの右側
            if (s1 != -1 && s2 != -1 && s3 != -1 && s4 != -1) {
                String body = pem.substring(s2 + BORDER.length(), s3);
                return Base64.decode(body);
            }
        }
    } catch (Exception e) {
       //TODO
    }
   return null;
}

/**
* DER形式のバイナリを読み込む
*/
public static PublicKey decodePublicKey(byte[] data) {
    try {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
        return KeyFactory.getInstance(ALGORITHM).generatePublic(spec);
    } catch (Exception e) {
        //TODO
    }
    return null;
}

これでPEMファイルを読ませたところ、以下のようなエラーが発生。

java.security.spec.InvalidKeySpecException: java.lang.IllegalArgumentException: unknown object in factory: org.bouncycastle.asn1.DERInteger

エラーメッセージは少し意味不明ですが、鍵の形式がおかしかったようです。

この鍵は、Rubyで

require 'openssl'
rsa = OpenSSL::PKey::RSA.new(2048)
rsa.to_s # > private.pem
rsa.public_key.to_s # => public.pem

として出力したものです。
秘密鍵のほうは問題なく読めたのですが、公開鍵はX.509になっていないので、それが原因で上記エラーが発生してしまったようです。

そんなわけで、公開鍵を作り直しました。Rubyでやっても良いのですが、コマンドのほうが簡単です。

openssl rsa -in private.pem -pubout -out public2.pem

こちらのpublic2.pemなら、Javaから正常に読み込めました。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。