- 開発
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から正常に読み込めました。